diff --git a/include/netfilter.mk b/include/netfilter.mk index 2159540318..c38fb7931a 100644 --- a/include/netfilter.mk +++ b/include/netfilter.mk @@ -201,27 +201,6 @@ $(eval $(call nf_add,NF_NATHELPER,CONFIG_NF_CONNTRACK_FTP, $(P_XT)nf_conntrack_f $(eval $(call nf_add,NF_NATHELPER,CONFIG_NF_NAT_FTP, $(P_XT)nf_nat_ftp)) -# nathelper-extra - -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_CONNTRACK_BROADCAST, $(P_XT)nf_conntrack_broadcast)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_CONNTRACK_NETBIOS_NS, $(P_XT)nf_conntrack_netbios_ns)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_CONNTRACK_SANE, $(P_XT)nf_conntrack_sane)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_CONNTRACK_AMANDA, $(P_XT)nf_conntrack_amanda)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_NAT_AMANDA, $(P_XT)nf_nat_amanda)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_CONNTRACK_H323, $(P_XT)nf_conntrack_h323)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_NAT_H323, $(P_V4)nf_nat_h323)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_CONNTRACK_PPTP, $(P_XT)nf_conntrack_pptp)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_NAT_PPTP, $(P_V4)nf_nat_pptp)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_CONNTRACK_SIP, $(P_XT)nf_conntrack_sip)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_NAT_SIP, $(P_XT)nf_nat_sip)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_CONNTRACK_SNMP, $(P_XT)nf_conntrack_snmp)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_NAT_SNMP_BASIC, $(P_V4)nf_nat_snmp_basic)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_CONNTRACK_TFTP, $(P_XT)nf_conntrack_tftp)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_NAT_TFTP, $(P_XT)nf_nat_tftp)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_CONNTRACK_IRC, $(P_XT)nf_conntrack_irc)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_NAT_IRC, $(P_XT)nf_nat_irc)) - - # nflog $(eval $(call nf_add,IPT_NFLOG,CONFIG_NETFILTER_XT_TARGET_NFLOG, $(P_XT)xt_NFLOG)) @@ -375,7 +354,6 @@ IPT_BUILTIN += $(IPT_NAT-y) IPT_BUILTIN += $(IPT_NAT6-y) IPT_BUILTIN += $(IPT_NAT_EXTRA-y) IPT_BUILTIN += $(NF_NATHELPER-y) -IPT_BUILTIN += $(NF_NATHELPER_EXTRA-y) IPT_BUILTIN += $(IPT_TPROXY-y) IPT_BUILTIN += $(NFNETLINK-y) IPT_BUILTIN += $(NFNETLINK_LOG-y) diff --git a/include/prereq-build.mk b/include/prereq-build.mk index 9a83d6b4c3..686bfab2ba 100644 --- a/include/prereq-build.mk +++ b/include/prereq-build.mk @@ -35,7 +35,8 @@ $(eval $(call SetupHostCommand,gcc, \ Please install the GNU C Compiler (gcc) 10 or later, \ $(CC) -dumpversion | grep -E '^(1[0-9]|[2-9][0-9])\.?', \ gcc -dumpversion | grep -E '^(1[0-9]|[2-9][0-9])\.?', \ - gcc --version | grep -E 'Apple.(LLVM|clang)' )) + clang -dumpversion | grep -E '^(1[2-9]|[2-9][0-9])\.', \ + clang-12 -dumpversion | grep -E '^(1[2-9]|[2-9][0-9])\.' )) $(eval $(call TestHostCommand,working-gcc, \ Please reinstall the GNU C Compiler (10 or later) - \ @@ -47,7 +48,8 @@ $(eval $(call SetupHostCommand,g++, \ Please install the GNU C++ Compiler (g++) 10 or later, \ $(CXX) -dumpversion | grep -E '^(1[0-9]|[2-9][0-9])\.?', \ g++ -dumpversion | grep -E '^(1[0-9]|[2-9][0-9])\.?', \ - g++ --version | grep -E 'Apple.(LLVM|clang)' )) + clang++ -dumpversion | grep -E '^(1[2-9]|[2-9][0-9])\.', \ + clang++-12 -dumpversion | grep -E '^(1[2-9]|[2-9][0-9])\.' )) $(eval $(call TestHostCommand,working-g++, \ Please reinstall the GNU C++ Compiler (10 or later) - \ @@ -185,6 +187,7 @@ $(eval $(call SetupHostCommand,perl,Please install Perl 5.x, \ perl --version | grep "perl.*v5")) $(eval $(call SetupHostCommand,python,Please install Python >= 3.8, \ + python3.14 -V 2>&1 | grep 'Python 3', \ python3.13 -V 2>&1 | grep 'Python 3', \ python3.12 -V 2>&1 | grep 'Python 3', \ python3.11 -V 2>&1 | grep 'Python 3', \ @@ -194,6 +197,7 @@ $(eval $(call SetupHostCommand,python,Please install Python >= 3.8, \ python3 -V 2>&1 | grep -E 'Python 3\.([8-9]|[0-9][0-9])\.?')) $(eval $(call SetupHostCommand,python3,Please install Python >= 3.8, \ + python3.14 -V 2>&1 | grep 'Python 3', \ python3.13 -V 2>&1 | grep 'Python 3', \ python3.12 -V 2>&1 | grep 'Python 3', \ python3.11 -V 2>&1 | grep 'Python 3', \ diff --git a/include/u-boot.mk b/include/u-boot.mk index d9ddc4fe73..b602596de7 100644 --- a/include/u-boot.mk +++ b/include/u-boot.mk @@ -29,6 +29,7 @@ endif ifdef UBOOT_USE_INTREE_DTC $(eval $(call TestHostCommand,python3-dev, \ Please install the python3-dev package, \ + python3.14-config --includes 2>&1 | grep 'python3', \ python3.13-config --includes 2>&1 | grep 'python3', \ python3.12-config --includes 2>&1 | grep 'python3', \ python3.11-config --includes 2>&1 | grep 'python3', \ diff --git a/package/base-files/Makefile b/package/base-files/Makefile index 2f84179cb3..d19f6fc712 100644 --- a/package/base-files/Makefile +++ b/package/base-files/Makefile @@ -43,7 +43,8 @@ define Package/base-files +netifd +libc +jsonfilter +SIGNED_PACKAGES:usign +SIGNED_PACKAGES:openwrt-keyring \ +NAND_SUPPORT:ubi-utils +fstools +fwtool \ +SELINUX:procd-selinux +!SELINUX:procd +USE_SECCOMP:procd-seccomp \ - +SELINUX:busybox-selinux +!SELINUX:busybox + +SELINUX:busybox-selinux +!SELINUX:busybox \ + +ucode +ucode-mod-fs +ucode-mod-digest TITLE:=Base filesystem for OpenWrt URL:=https://openwrt.org/ VERSION:=$(PKG_RELEASE)~$(lastword $(subst -, ,$(REVISION))) diff --git a/package/base-files/files/etc/uci-defaults/14_network-generate-duid b/package/base-files/files/etc/uci-defaults/14_network-generate-duid index c793dba695..7742897617 100644 --- a/package/base-files/files/etc/uci-defaults/14_network-generate-duid +++ b/package/base-files/files/etc/uci-defaults/14_network-generate-duid @@ -1,8 +1,10 @@ [ "$(uci -q get network.globals.dhcp_default_duid || echo "auto")" != "auto" ] && exit 0 +duid="$(/usr/libexec/duid-generate)" +[ -n "$duid" ] || exit 1 + uci -q batch <<-EOF >/dev/null - # DUID-UUID - RFC6355 - set network.globals.dhcp_default_duid="$(printf '%s%s' '0004' $(cat /proc/sys/kernel/random/uuid | sed -e 's/-//g'))" + set network.globals.dhcp_default_duid="$duid" commit network EOF diff --git a/package/base-files/files/lib/upgrade/nand.sh b/package/base-files/files/lib/upgrade/nand.sh index 22f9cce42a..4bf9fc993e 100644 --- a/package/base-files/files/lib/upgrade/nand.sh +++ b/package/base-files/files/lib/upgrade/nand.sh @@ -7,8 +7,9 @@ CI_KERNPART="${CI_KERNPART:-kernel}" # 'ubi' partition on NAND contains UBI -# There are also CI_KERN_UBIPART and CI_ROOT_UBIPART if kernel -# and rootfs are on separated UBIs. +# If individual UBI volumes are on different partitions, +# they can be set with CI_KERN_UBIPART, CI_ROOT_UBIPART and/or +# CI_DATA_UBIPART. CI_UBIPART="${CI_UBIPART:-ubi}" # 'rootfs' UBI volume on NAND contains the rootfs @@ -77,9 +78,10 @@ identify_if_gzip() { } nand_restore_config() { - local ubidev=$( nand_find_ubi "${CI_ROOT_UBIPART:-$CI_UBIPART}" ) + local ubidev=$( nand_find_ubi "${CI_DATA_UBIPART:-$CI_UBIPART}" ) local ubivol="$( nand_find_volume $ubidev rootfs_data )" if [ ! "$ubivol" ]; then + local ubidev=$( nand_find_ubi "${CI_ROOT_UBIPART:-$CI_UBIPART}" ) ubivol="$( nand_find_volume $ubidev "$CI_ROOTPART" )" if [ ! "$ubivol" ]; then echo "cannot find ubifs data volume" @@ -188,23 +190,21 @@ nand_upgrade_prepare_ubi() { local has_env="${4:-0}" local kern_ubidev local root_ubidev + local data_ubidev [ -n "$rootfs_length" -o -n "$kernel_length" ] || return 1 - if [ -n "$CI_KERN_UBIPART" -a -n "$CI_ROOT_UBIPART" ]; then - kern_ubidev="$( nand_attach_ubi "$CI_KERN_UBIPART" "$has_env" )" - [ -n "$kern_ubidev" ] || return 1 - root_ubidev="$( nand_attach_ubi "$CI_ROOT_UBIPART" )" - [ -n "$root_ubidev" ] || return 1 - else - kern_ubidev="$( nand_attach_ubi "$CI_UBIPART" "$has_env" )" - [ -n "$kern_ubidev" ] || return 1 - root_ubidev="$kern_ubidev" - fi + # Attach UBI partitions (might be identical, but nand_attach_ubi handles that) + kern_ubidev="$( nand_attach_ubi "${CI_KERN_UBIPART:-$CI_UBIPART}" "$has_env" )" + [ -n "$kern_ubidev" ] || return 1 + root_ubidev="$( nand_attach_ubi "${CI_ROOT_UBIPART:-$CI_UBIPART}" )" + [ -n "$root_ubidev" ] || return 1 + data_ubidev="$( nand_attach_ubi "${CI_DATA_UBIPART:-$CI_UBIPART}" )" + [ -n "$data_ubidev" ] || return 1 local kern_ubivol="$( nand_find_volume $kern_ubidev "$CI_KERNPART" )" local root_ubivol="$( nand_find_volume $root_ubidev "$CI_ROOTPART" )" - local data_ubivol="$( nand_find_volume $root_ubidev rootfs_data )" + local data_ubivol="$( nand_find_volume $data_ubidev rootfs_data )" [ "$root_ubivol" = "$kern_ubivol" ] && root_ubivol= # remove ubiblocks @@ -215,7 +215,7 @@ nand_upgrade_prepare_ubi() { # kill volumes [ "$kern_ubivol" ] && ubirmvol /dev/$kern_ubidev -N "$CI_KERNPART" || : [ "$root_ubivol" ] && ubirmvol /dev/$root_ubidev -N "$CI_ROOTPART" || : - [ "$data_ubivol" ] && ubirmvol /dev/$root_ubidev -N rootfs_data || : + [ "$data_ubivol" ] && ubirmvol /dev/$data_ubidev -N rootfs_data || : # create provisioning vol if [ "${UPGRADE_OPT_ADD_PROVISIONING:-0}" -gt 0 ]; then @@ -255,8 +255,8 @@ nand_upgrade_prepare_ubi() { if [ -n "$rootfs_data_max" ]; then rootfs_data_size_param="-s $rootfs_data_max" fi - if ! ubimkvol /dev/$root_ubidev -N rootfs_data $rootfs_data_size_param; then - if ! ubimkvol /dev/$root_ubidev -N rootfs_data -m; then + if ! ubimkvol /dev/$data_ubidev -N rootfs_data $rootfs_data_size_param; then + if ! ubimkvol /dev/$data_ubidev -N rootfs_data -m; then echo "cannot initialize rootfs_data volume" return 1 fi @@ -288,8 +288,8 @@ nand_upgrade_ubifs() { nand_upgrade_prepare_ubi "$ubifs_length" "ubifs" "" "" || return 1 - local ubidev="$( nand_find_ubi "$CI_UBIPART" )" - local root_ubivol="$(nand_find_volume $ubidev "$CI_ROOTPART")" + local root_ubidev="$( nand_find_ubi "${CI_ROOT_UBIPART:-$CI_UBIPART}" )" + local root_ubivol="$(nand_find_volume $root_ubidev "$CI_ROOTPART")" $cmd < "$ubifs_file" | ubiupdatevol /dev/$root_ubivol -s "$ubifs_length" - } @@ -302,7 +302,7 @@ nand_upgrade_fit() { nand_upgrade_prepare_ubi "" "" "$fit_length" "1" || return 1 - local fit_ubidev="$(nand_find_ubi "$CI_UBIPART")" + local fit_ubidev="$(nand_find_ubi "${CI_KERN_UBIPART:-$CI_UBIPART}")" local fit_ubivol="$(nand_find_volume $fit_ubidev "$CI_KERNPART")" $cmd < "$fit_file" | ubiupdatevol /dev/$fit_ubivol -s "$fit_length" - } @@ -328,6 +328,10 @@ nand_upgrade_tar() { local rootfs_type [ "$rootfs_length" ] && rootfs_type="$(identify_tar "$tar_file" "$cmd" "$board_dir/root")" + # If CI_SKIP_KERNEL_MTD is set, ignore any potential kernel MTD partition that was found. + # This is needed if there's an MTD partition with the same name as the kernel's UBI volume. + [ "${CI_SKIP_KERNEL_MTD:-}" ] && kernel_mtd= + local ubi_kernel_length if [ "$kernel_length" ]; then if [ "$kernel_mtd" ]; then diff --git a/package/base-files/files/usr/libexec/duid-generate b/package/base-files/files/usr/libexec/duid-generate new file mode 100755 index 0000000000..2318239feb --- /dev/null +++ b/package/base-files/files/usr/libexec/duid-generate @@ -0,0 +1,120 @@ +#!/usr/bin/env ucode +'use strict'; + +import { readfile } from 'fs'; +import * as digest from 'digest'; + +// Fixed salt prefixed to the MAC address before hashing. It only separates this +// particular use of the MAC from any other; the value itself carries no meaning. +const DUID_SALT = 'openwrt-dhcp-duid:'; +const DUID_TYPE_UUID = '0004'; + +function mac_normalise(mac) { + if (type(mac) != 'string') + return null; + + mac = lc(trim(mac)); + + if (!match(mac, /^[0-9a-f]{2}(:[0-9a-f]{2}){5}$/)) + return null; + + if (mac == '00:00:00:00:00:00') + return null; + + return mac; +} + +function sysfs_mac(dev) { + if (!dev) + return null; + + return mac_normalise(readfile('/sys/class/net/' + dev + '/address')); +} + +function role_mac(board, role) { + if (type(role) != 'object') + return null; + + let dev; + if (type(role.ports) == 'array' && length(role.ports) > 0) + dev = role.ports[0]; + else + dev = role.device; + + // Prefer the live hardware address of the physical port. + let mac = sysfs_mac(dev); + if (mac) + return mac; + + // Fall back to MAC addresses recorded in board.json. + mac = mac_normalise(board?.network_device?.[dev]?.macaddr); + if (mac) + return mac; + + return mac_normalise(role.macaddr); +} + +function board_mac(board) { + let net = board?.network; + if (type(net) != 'object') + return null; + + for (let prefix in ['lan', 'wan']) { + let mac = role_mac(board, net[prefix]); + if (mac) + return mac; + + for (let name in keys(net)) { + if (substr(name, 0, length(prefix)) != prefix) + continue; + + mac = role_mac(board, net[name]); + if (mac) + return mac; + } + } + + return null; +} + +function uuid_set_bits(u, version) { + let b6 = (hex(substr(u, 12, 2)) & 0x0f) | (version << 4); + let b8 = (hex(substr(u, 16, 2)) & 0x3f) | 0x80; + + return substr(u, 0, 12) + sprintf('%02x', b6) + + substr(u, 14, 2) + sprintf('%02x', b8) + + substr(u, 18, 14); +} + +function uuid_from_mac(mac) { + let hash = digest.sha1(DUID_SALT + mac); + if (type(hash) != 'string' || length(hash) < 32) + return null; + + return uuid_set_bits(substr(hash, 0, 32), 5); +} + +function uuid_random() { + let uuid = readfile('/proc/sys/kernel/random/uuid'); + if (!uuid) + return null; + + return join('', split(trim(uuid), '-')); +} + +let board; +try { + board = json(readfile('/etc/board.json')); +} catch (e) { + board = null; +} + +let mac = board_mac(board); +let uuid = mac ? uuid_from_mac(mac) : null; + +uuid ??= uuid_random(); + +if (!uuid) + exit(1); + +print(DUID_TYPE_UUID + uuid + '\n'); diff --git a/package/boot/apboot-aruba-ipq806x/Makefile b/package/boot/apboot-aruba-ipq806x/Makefile new file mode 100644 index 0000000000..141b359b23 --- /dev/null +++ b/package/boot/apboot-aruba-ipq806x/Makefile @@ -0,0 +1,77 @@ +# +# Copyright (C) 2026 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=apboot-aruba-ipq806x +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/lukasstockner/ap325-apboot-openwrt.git +PKG_MIRROR_HASH:=ef91bc1539d50c19c35ae5d38eab1a4944692d3f651952f58800ea1f7ffd4878 +PKG_SOURCE_DATE:=2026-06-12 +PKG_SOURCE_VERSION:=d36bb7270a8a8a5c5988ff778e55de12e0c40745 + +PKG_LICENSE:=GPL-2.0-or-later +PKG_LICENSE_FILES:=COPYING +PKG_MAINTAINER:=Lukas Stockner + +# Legacy U-Boot tree, not Kbuild-parallel safe. +PKG_BUILD_PARALLEL:=0 +PKG_FLAGS:=nonshared + +include $(INCLUDE_DIR)/package.mk + +# Aruba/QCA board name in the APBoot tree (Makefile.releng target): +# octomore -> AP-324 / AP-325 (and Siemens Scalance W1750D) +APBOOT_BOARD:=octomore + +# Stamped into the version banner; the upstream Dockerfile uses the short hash. +APBOOT_LABELID:=$(call version_abbrev,$(PKG_SOURCE_VERSION)) + +define Package/apboot-aruba-ipq806x + SECTION:=boot + CATEGORY:=Boot Loaders + DEPENDS:=@TARGET_ipq806x + TITLE:=Patched Aruba APBoot for AP-32x + URL:=https://github.com/lukasstockner/ap325-apboot-openwrt +endef + +define Package/apboot-aruba-ipq806x/description + Patched build of the Aruba APBoot bootloader (a vendor fork of U-Boot) for + the Aruba AP-324 / AP-325 access points (board "octomore"). The factory + bootloader enforces RSA signatures on the firmware; this build removes the + signature check and switches the console to 115200 baud so that OpenWrt can + be booted. The resulting "u-boot.mbn" is meant to be flashed to the APPSBL + SPI-flash partition via the serial console. +endef + +# APBoot is a freestanding U-Boot, so build it with OpenWrt's target +# cross-toolchain instead of the bare-metal arm-none-eabi- default. The legacy +# Makefile honours an externally supplied CROSS_COMPILE. +define Build/Compile + +$(MAKE) -C $(PKG_BUILD_DIR) -f Makefile.releng $(APBOOT_BOARD) \ + SHELL=/bin/bash \ + CROSS_COMPILE=$(TARGET_CROSS) \ + HOSTCC="$(HOSTCC)" \ + LABELID=$(APBOOT_LABELID) \ + ARUBA_MAKE_VERBOSE=1 +endef + +# The bootloader is flashed by hand and is not part of the root filesystem. +# Stage the image so the ipq806x image build can emit it as a device artifact. +define Build/InstallDev + $(INSTALL_DIR) $(STAGING_DIR_IMAGE) + $(INSTALL_DATA) $(PKG_BUILD_DIR)/u-boot.mbn \ + $(STAGING_DIR_IMAGE)/aruba_ap-32x-apboot.mbn +endef + +define Package/apboot-aruba-ipq806x/install + : +endef + +$(eval $(call BuildPackage,apboot-aruba-ipq806x)) diff --git a/package/boot/arm-trusted-firmware-tools/Makefile b/package/boot/arm-trusted-firmware-tools/Makefile index dd0ed66a21..b709112ce3 100644 --- a/package/boot/arm-trusted-firmware-tools/Makefile +++ b/package/boot/arm-trusted-firmware-tools/Makefile @@ -29,10 +29,16 @@ define Package/arm-trusted-firmware-tools BUILDONLY:=1 endef +ifeq ($(shell uname -s),Linux) + HOST_MUSL_FLAG:=$(shell [ "$$(2>&1 ldd --version | head -n 1 | cut -d ' ' -f1)" = "musl" ] && echo " -D__MUSL__") +else + HOST_MUSL_FLAG:= +endif + define Host/Compile $(MAKE) -C \ $(HOST_BUILD_DIR)/tools/fiptool \ - CPPFLAGS="$(HOST_CFLAGS)" \ + CPPFLAGS="$(HOST_CFLAGS)$(HOST_MUSL_FLAG)" \ LDFLAGS="$(HOST_LDFLAGS)" \ OPENSSL_DIR="$(STAGING_DIR_HOST)" endef diff --git a/package/boot/arm-trusted-firmware-tools/patches/003-fiptool_musl_fix.patch b/package/boot/arm-trusted-firmware-tools/patches/003-fiptool_musl_fix.patch new file mode 100644 index 0000000000..ec94c90d9e --- /dev/null +++ b/package/boot/arm-trusted-firmware-tools/patches/003-fiptool_musl_fix.patch @@ -0,0 +1,39 @@ +From 6f51da2bb799a8b77da0167eeea45d5d5125f39c Mon Sep 17 00:00:00 2001 +From: Shine <4c.fce2@proton.me> +Date: Mon, 22 Jun 2026 14:45:39 +0200 +Subject: fix fiptool build on musl host + +Due to POSIX style ioctl(int,int,...) declaration, building fiptool under +MUSL generates a compiler warning (BLKGETSIZE64 == 0x80081272, ie. integer +overflow). This causes a build failure when compiling with -Werror and +-pedantic GCC switches enabled. + +Selectively cast the parameter to (int) when hinted to be running on a +MUSL based build host. + +Requires a __MUSL__ macro to be defined. MUSL does not provide such a +predefined macro, so this has to be passed explicitly to GCC, e.g. with +-D__MUSL__ during build. + +For OpenWrt, this is done in the arm-trusted-firmware-tools Makefile, +see commit e42e9c8133fbd0dce7abfe1ec696383745448078 + +Signed-off-by: Shine <4c.fce2@proton.me> +--- + tools/fiptool/fiptool.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/tools/fiptool/fiptool.c ++++ b/tools/fiptool/fiptool.c +@@ -318,7 +318,11 @@ static int parse_fip(const char *filename, fip_toc_header_t *toc_header_out) + + #ifdef BLKGETSIZE64 + if ((st.st_mode & S_IFBLK) != 0) ++#ifdef __MUSL__ ++ if (ioctl(fileno(fp), (int)BLKGETSIZE64, &st_size) == -1) ++#else + if (ioctl(fileno(fp), BLKGETSIZE64, &st_size) == -1) ++#endif + log_err("ioctl %s", filename); + #endif + diff --git a/package/boot/tfa-layerscape/Makefile b/package/boot/tfa-layerscape/Makefile index b69944ff81..d734066abb 100644 --- a/package/boot/tfa-layerscape/Makefile +++ b/package/boot/tfa-layerscape/Makefile @@ -8,13 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=tfa-layerscape -PKG_VERSION:=6.12.20.2.0.0 +PKG_VERSION:=6.18.2.1.0.0 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/nxp-qoriq/atf -PKG_SOURCE_VERSION:=lf-6.12.20-2.0.0 -PKG_MIRROR_HASH:=1e1c74900113a8d4354c06fdcedfff2cd6b0899b4a063d393de98f8ca358dfd2 +PKG_SOURCE_VERSION:=lf-6.18.2-1.0.0 +PKG_MIRROR_HASH:=4baa079cdc794bd6095c4d5cecb64d38d94273d592ad6d84da955cff3d443393 PKG_BUILD_DEPENDS:=tfa-layerscape/host include $(INCLUDE_DIR)/host-build.mk diff --git a/package/boot/uboot-airoha/Makefile b/package/boot/uboot-airoha/Makefile index 52b95c68ed..129081268c 100644 --- a/package/boot/uboot-airoha/Makefile +++ b/package/boot/uboot-airoha/Makefile @@ -16,14 +16,32 @@ define U-Boot/Default LZMA_COMPRESS:=1 endef -define U-Boot/en7523_rfb - NAME:=EN7523 Reference Board - UBOOT_CONFIG:=en7523_evb - BUILD_DEVICES:=airoha_en7523-evb - BUILD_SUBTARGET:=en7523 +define U-Boot/an7581_gemtek_w1700k + NAME:=Gemtek W1700K (UBI) + UBOOT_CONFIG:=an7581_w1700k + BUILD_DEVICES:=gemtek_w1700k-ubi + BUILD_SUBTARGET:=an7581 + UBOOT_IMAGE:=u-boot.bin +endef + +define U-Boot/an7581_nokia_valyrian + NAME:=Nokia Valyrian + UBOOT_CONFIG:=an7581_nokia_valyrian + BUILD_DEVICES:=nokia_valyrian + BUILD_SUBTARGET:=an7581 UBOOT_IMAGE:=u-boot.fip - BL2_IMAGE:=en7523-bl2.bin - BL31_IMAGE:=en7523-bl31.bin + BL2_IMAGE:=an7581-bl2.bin + BL31_IMAGE:=an7581-bl31.bin +endef + +define U-Boot/an7581_nokia_xg-040g-md + NAME:=Nokia XG-040G-MD + UBOOT_CONFIG:=an7581_nokia_xg-040g-md + BUILD_DEVICES:=nokia_xg-040g-md-ubi + BUILD_SUBTARGET:=an7581 + UBOOT_IMAGE:=u-boot.fip + BL2_IMAGE:=an7581-bl2.bin + BL31_IMAGE:=an7581-bl31.bin endef define U-Boot/an7581_rfb @@ -46,30 +64,23 @@ define U-Boot/an7583_rfb BL31_IMAGE:=an7583-bl31.bin endef -define U-Boot/an7581_gemtek_w1700k - NAME:=Gemtek W1700K (UBI) - UBOOT_CONFIG:=an7581_w1700k - BUILD_DEVICES:=gemtek_w1700k-ubi - BUILD_SUBTARGET:=an7581 - UBOOT_IMAGE:=u-boot.bin -endef - -define U-Boot/an7581_nokia_valyrian - NAME:=Nokia Valyrian - UBOOT_CONFIG:=an7581_nokia_valyrian - BUILD_DEVICES:=nokia_valyrian - BUILD_SUBTARGET:=an7581 +define U-Boot/en7523_rfb + NAME:=EN7523 Reference Board + UBOOT_CONFIG:=en7523_evb + BUILD_DEVICES:=airoha_en7523-evb + BUILD_SUBTARGET:=en7523 UBOOT_IMAGE:=u-boot.fip - BL2_IMAGE:=an7581-bl2.bin - BL31_IMAGE:=an7581-bl31.bin + BL2_IMAGE:=en7523-bl2.bin + BL31_IMAGE:=en7523-bl31.bin endef UBOOT_TARGETS := \ - en7523_rfb \ + an7581_gemtek_w1700k \ + an7581_nokia_valyrian \ + an7581_nokia_xg-040g-md \ an7581_rfb \ an7583_rfb \ - an7581_gemtek_w1700k \ - an7581_nokia_valyrian + en7523_rfb UBOOT_CUSTOMIZE_CONFIG := \ --disable TOOLS_KWBIMAGE \ diff --git a/package/boot/uboot-airoha/patches/200-cmd-bootmenu-custom-title.patch b/package/boot/uboot-airoha/patches/200-cmd-bootmenu-custom-title.patch new file mode 100644 index 0000000000..3a66aa298a --- /dev/null +++ b/package/boot/uboot-airoha/patches/200-cmd-bootmenu-custom-title.patch @@ -0,0 +1,33 @@ +--- a/cmd/bootmenu.c ++++ b/cmd/bootmenu.c +@@ -482,7 +482,11 @@ static void menu_display_statusline(stru + printf(ANSI_CURSOR_POSITION, 1, 1); + puts(ANSI_CLEAR_LINE); + printf(ANSI_CURSOR_POSITION, 2, 3); +- puts("*** U-Boot Boot Menu ***"); ++ if (menu->mtitle) ++ puts(menu->mtitle); ++ else ++ puts(" *** U-Boot Boot Menu ***"); ++ + puts(ANSI_CLEAR_LINE_TO_END); + printf(ANSI_CURSOR_POSITION, 3, 1); + puts(ANSI_CLEAR_LINE); +@@ -573,6 +577,7 @@ static enum bootmenu_ret bootmenu_show(i + return BOOTMENU_RET_FAIL; + } + ++ bootmenu->mtitle = env_get("bootmenu_title"); + for (iter = bootmenu->first; iter; iter = iter->next) { + if (menu_item_add(menu, iter->key, iter) != 1) + goto cleanup; +--- a/include/menu.h ++++ b/include/menu.h +@@ -43,6 +43,7 @@ struct bootmenu_data { + int last_active; /* last active menu entry */ + int count; /* total count of menu entries */ + struct bootmenu_entry *first; /* first menu entry */ ++ char *mtitle; /* custom menu title */ + }; + + /** enum bootmenu_key - keys that can be returned by the bootmenu */ diff --git a/package/boot/uboot-airoha/patches/201-cmd-env-readmem.patch b/package/boot/uboot-airoha/patches/201-cmd-env-readmem.patch new file mode 100644 index 0000000000..14a4ba112a --- /dev/null +++ b/package/boot/uboot-airoha/patches/201-cmd-env-readmem.patch @@ -0,0 +1,116 @@ +--- a/cmd/Kconfig ++++ b/cmd/Kconfig +@@ -717,6 +717,12 @@ config CMD_ENV_EXISTS + Check if a variable is defined in the environment for use in + shell scripting. + ++config CMD_ENV_READMEM ++ bool "env readmem" ++ default y ++ help ++ Store memory content into environment variable. ++ + config CMD_ENV_CALLBACK + bool "env callbacks - print callbacks and their associated variables" + help +--- a/cmd/nvedit.c ++++ b/cmd/nvedit.c +@@ -273,6 +273,60 @@ static int do_env_ask(struct cmd_tbl *cm + } + #endif + ++#if defined(CONFIG_CMD_ENV_READMEM) ++int do_env_readmem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) ++{ ++ char varstr[CONFIG_SYS_CBSIZE]; ++ const void *buf; ++ char *local_args[4]; ++ ulong addr, bytes = 6; ++ int hexdump = 0; ++ ++ /* ++ * Check the syntax: ++ * ++ * readmem [-b] name address [size] ++ */ ++ if (argc < 3) ++ return CMD_RET_USAGE; ++ ++ local_args[0] = argv[0]; ++ ++ if (!strncmp(argv[1], "-b", 3)) ++ hexdump = 1; ++ ++ local_args[1] = argv[hexdump + 1]; ++ local_args[2] = varstr; ++ local_args[3] = NULL; ++ ++ addr = simple_strtoul(argv[hexdump + 2], NULL, 16); ++ ++ if (!hexdump) ++ bytes = simple_strtoul(argv[hexdump + 3], NULL, 16); ++ ++ if (bytes < 1) ++ return 1; ++ ++ if ((hexdump * 3) * bytes >= CONFIG_SYS_CBSIZE) ++ return 1; ++ ++ buf = map_sysmem(addr, bytes); ++ if (!buf) ++ return 1; ++ ++ if (hexdump) { ++ sprintf(varstr, "%pM", buf); ++ } else { ++ memcpy(varstr, buf, bytes); ++ varstr[bytes] = '\0'; ++ } ++ unmap_sysmem(buf); ++ ++ /* Continue calling setenv code */ ++ return env_do_env_set(flag, 3, local_args, H_INTERACTIVE); ++} ++#endif ++ + #if defined(CONFIG_CMD_ENV_CALLBACK) + static int print_static_binding(const char *var_name, const char *callback_name, + void *priv) +@@ -1095,6 +1149,9 @@ static struct cmd_tbl cmd_env_sub[] = { + U_BOOT_CMD_MKENT(load, 1, 0, do_env_load, "", ""), + #endif + U_BOOT_CMD_MKENT(print, CONFIG_SYS_MAXARGS, 1, do_env_print, "", ""), ++#if defined(CONFIG_CMD_ENV_READMEM) ++ U_BOOT_CMD_MKENT(readmem, CONFIG_SYS_MAXARGS, 3, do_env_readmem, "", ""), ++#endif + #if defined(CONFIG_CMD_RUN) + U_BOOT_CMD_MKENT(run, CONFIG_SYS_MAXARGS, 1, do_run, "", ""), + #endif +@@ -1179,6 +1236,9 @@ U_BOOT_LONGHELP(env, + #if defined(CONFIG_CMD_NVEDIT_EFI) + "env print -e [-guid guid] [-n] [name ...] - print UEFI environment\n" + #endif ++#if defined(CONFIG_CMD_ENV_READMEM) ++ "env readmem [-b] name address size - read variable from memory\n" ++#endif + #if defined(CONFIG_CMD_RUN) + "env run var [...] - run commands in an environment variable\n" + #endif +@@ -1287,6 +1347,17 @@ U_BOOT_CMD( + ); + #endif + ++#if defined(CONFIG_CMD_ENV_READMEM) ++U_BOOT_CMD_COMPLETE( ++ readmem, CONFIG_SYS_MAXARGS, 3, do_env_readmem, ++ "get environment variable from memory address", ++ "[-b] name address size\n" ++ " - store memory address to env variable\n" ++ " \"-b\": read binary ethaddr", ++ var_complete ++); ++#endif ++ + #if defined(CONFIG_CMD_RUN) + U_BOOT_CMD_COMPLETE( + run, CONFIG_SYS_MAXARGS, 1, do_run, diff --git a/package/boot/uboot-airoha/patches/401-add-nokia-xg-040g-md.patch b/package/boot/uboot-airoha/patches/401-add-nokia-xg-040g-md.patch new file mode 100644 index 0000000000..3dc4b09c15 --- /dev/null +++ b/package/boot/uboot-airoha/patches/401-add-nokia-xg-040g-md.patch @@ -0,0 +1,295 @@ +--- /dev/null ++++ b/configs/an7581_nokia_xg-040g-md_defconfig +@@ -0,0 +1,134 @@ ++CONFIG_ARM=y ++CONFIG_ARCH_AIROHA=y ++CONFIG_POSITION_INDEPENDENT=y ++CONFIG_BOOTDELAY=3 ++CONFIG_AUTOBOOT_KEYED=y ++CONFIG_AUTOBOOT_MENU_SHOW=y ++CONFIG_TARGET_AN7581=y ++CONFIG_TEXT_BASE=0x81e00000 ++CONFIG_SYS_MALLOC_F_LEN=0x4000 ++CONFIG_NR_DRAM_BANKS=1 ++CONFIG_DM_GPIO=y ++CONFIG_DEFAULT_DEVICE_TREE="airoha/an7581-nokia-xg-040g-md" ++CONFIG_SYS_LOAD_ADDR=0x81800000 ++CONFIG_BUILD_TARGET="u-boot.bin" ++# CONFIG_EFI_LOADER is not set ++CONFIG_FIT=y ++CONFIG_FIT_VERBOSE=y ++CONFIG_DEFAULT_FDT_FILE="airoha/an7581-nokia-xg-040g-md.dtb" ++CONFIG_LOGLEVEL=9 ++CONFIG_LOG=y ++CONFIG_SYS_PBSIZE=1049 ++CONFIG_SYS_CONSOLE_IS_IN_ENV=y ++# CONFIG_DISPLAY_BOARDINFO is not set ++CONFIG_HUSH_PARSER=y ++CONFIG_SYS_PROMPT="AN7581> " ++CONFIG_SYS_MAXARGS=8 ++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_RNG=y ++CONFIG_CMD_STRINGS=y ++CONFIG_CMD_DM=y ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_MTD=y ++CONFIG_CMD_MTD_MARKBAD=y ++CONFIG_CMD_MTD_NAND_READ_TEST=y ++CONFIG_CMD_MTD_NAND_WRITE_TEST=y ++CONFIG_CMD_PART=y ++CONFIG_CMD_TFTPSRV=y ++CONFIG_CMD_RARP=y ++CONFIG_CMD_CDP=y ++CONFIG_CMD_SNTP=y ++CONFIG_CMD_LINK_LOCAL=y ++CONFIG_CMD_DHCP=y ++CONFIG_CMD_DNS=y ++CONFIG_CMD_PING=y ++CONFIG_CMD_PXE=y ++CONFIG_CMD_CACHE=y ++CONFIG_CMD_UUID=y ++CONFIG_CMD_HASH=y ++CONFIG_CMD_SMC=y ++CONFIG_CMD_UBI=y ++CONFIG_CMD_UBI_RENAME=y ++CONFIG_OF_EMBED=y ++CONFIG_ENV_OVERWRITE=y ++CONFIG_ENV_IS_IN_UBI=y ++CONFIG_ENV_REDUNDANT=y ++CONFIG_ENV_UBI_PART="ubi" ++CONFIG_ENV_UBI_VOLUME="ubootenv" ++CONFIG_ENV_UBI_VOLUME_REDUND="ubootenv2" ++CONFIG_ENV_RELOC_GD_ENV_ADDR=y ++CONFIG_ENV_USE_DEFAULT_ENV_TEXT_FILE=y ++CONFIG_ENV_DEFAULT_ENV_TEXT_FILE="defenvs/an7581_nokia_xg-040g-md_env" ++CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y ++# CONFIG_ENV_IS_IN_MTD is not set ++# CONFIG_MMC is not set ++CONFIG_MTD=y ++CONFIG_DM_MTD=y ++CONFIG_MTD_SPI_NAND=y ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_MODULE=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_LIMIT=20 ++# CONFIG_MTD_UBI_FASTMAP is not set ++CONFIG_UBI_BLOCK=y ++# CONFIG_UBIFS_SILENCE_MSG is not set ++# CONFIG_UBIFS_SILENCE_DEBUG_DUMP is not set ++CONFIG_VERSION_VARIABLE=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_NET_RANDOM_ETHADDR=y ++CONFIG_BUTTON=y ++CONFIG_BUTTON_GPIO=y ++CONFIG_OF_UPSTREAM=y ++CONFIG_SYS_RELOC_GD_ENV_ADDR=y ++CONFIG_SYS_RX_ETH_BUFFER=8 ++CONFIG_REGMAP=y ++CONFIG_SYSCON=y ++CONFIG_CLK=y ++CONFIG_DMA=y ++CONFIG_GPIO_HOG=y ++CONFIG_LED=y ++CONFIG_LED_BLINK=y ++CONFIG_LED_GPIO=y ++CONFIG_SPI_FLASH=y ++CONFIG_SPI_FLASH_EON=y ++CONFIG_SPI_FLASH_GIGADEVICE=y ++CONFIG_SPI_FLASH_ISSI=y ++CONFIG_SPI_FLASH_MACRONIX=y ++CONFIG_SPI_FLASH_SPANSION=y ++CONFIG_SPI_FLASH_STMICRO=y ++CONFIG_SPI_FLASH_WINBOND=y ++CONFIG_SPI_FLASH_MTD=y ++CONFIG_AIROHA_ETH=y ++CONFIG_DM_MDIO=y ++CONFIG_CMD_MII=y ++CONFIG_CMD_MDIO=y ++CONFIG_PCS_AIROHA_AN7581=y ++CONFIG_PHY=y ++CONFIG_PINCTRL=y ++CONFIG_PINCONF=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_DM_REGULATOR=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_RAM=y ++CONFIG_DM_SERIAL=y ++CONFIG_SYS_NS16550=y ++CONFIG_SPI=y ++CONFIG_DM_SPI=y ++CONFIG_AIROHA_SNFI_SPI=y ++CONFIG_SHA512=y ++CONFIG_USE_DEFAULT_ENV_FILE=y ++CONFIG_DEFAULT_ENV_FILE="defenvs/an7581_nokia_xg-040g-md_env" ++CONFIG_PCS_AIROHA_AN7581=y ++CONFIG_PHY_AIROHA_EN8811=y ++CONFIG_PHY_ANEG_TIMEOUT=10000 ++CONFIG_PHY_ETHERNET_ID=y +--- /dev/null ++++ b/defenvs/an7581_nokia_xg-040g-md_env +@@ -0,0 +1,53 @@ ++ipaddr=192.168.1.1 ++serverip=192.168.1.254 ++loadaddr=0x90000000 ++console=earlycon=uart8250,mmio32,0x11002000 console=ttyS0 ++bootcmd=run check_buttons ; run boot_ubi ++bootconf=config-1 ++bootdelay=0 ++bootfile=immortalwrt-airoha-an7581-nokia_xg-040g-md-ubi-initramfs-recovery.itb ++bootfile_bl2=immortalwrt-airoha-an7581-nokia_xg-040g-md-ubi-preloader.bin ++bootfile_fip=immortalwrt-airoha-an7581-nokia_xg-040g-md-ubi-bl31-uboot.fip ++bootfile_upg=immortalwrt-airoha-an7581-nokia_xg-040g-md-ubi-squashfs-sysupgrade.itb ++bootled_status=green:power ++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=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_4=Load BL31+U-Boot FIP via TFTP then write to NAND=run boot_tftp_write_fip ; run bootmenu_confirm_return ++bootmenu_5=Load BL2 preloader via TFTP then write to NAND=run boot_tftp_write_bl2 ; run bootmenu_confirm_return ++bootmenu_6=Reboot=reset ++bootmenu_7=Reset all settings to factory defaults=run reset_factory ; reset ++boot_first=if button reset ; then led $bootled_status on ; run boot_default ; fi ; bootmenu ++boot_default=run bootcmd ; run boot_tftp_forever ++boot_production=led $bootled_status on ; run ubi_read_production && bootm $loadaddr#$bootconf ; led $bootled_status off ++boot_ubi=run boot_production ; run boot_tftp_forever ++boot_tftp_forever=led $bootled_status on ; while true ; do run boot_tftp ; sleep 1 ; done ++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_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=tftpboot $loadaddr $bootfile && bootm $loadaddr#$bootconf ++boot_tftp_write_bl2=mw.b $loadaddr 0xff 0x800 ; setexpr loadaddr_bl2 $loadaddr + 0x800 ; tftpboot $loadaddr_bl2 $bootfile_bl2 && run mtd_write_bl2 ++boot_tftp_write_fip=tftpboot $loadaddr $bootfile_fip && run ubi_write_fip && run reset_factory ++preboot=led $bootled_status on ++check_buttons=if button reset ; then run boot_tftp ; fi ++ethaddr_factory=ubi read 0x90000000 ri && env readmem -b ethaddr 0x9000003e 0x6 ; setenv ethaddr_factory ++part_default=production ++reset_factory=ubi part ubi ; mw $loadaddr 0x0 0x800 ; ubi write $loadaddr ubootenv 0x800 ; ubi write $loadaddr ubootenv2 0x800 ++mtd_write_bl2=mtd erase bl2 && mtd write bl2 $loadaddr ++ubi_create_board_data=ubi check bosa || ubi create bosa 0x40000 || run ubi_format ; ubi check ri || ubi create ri 0x40000 || run ubi_format ++ubi_create_env=ubi check ubootenv || ubi create ubootenv 0x1f000 dynamic || run ubi_format ; ubi check ubootenv2 || ubi create ubootenv2 0x1f000 dynamic || 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_remove_rootfs=ubi check rootfs_data && ubi remove rootfs_data ++ubi_write_fip=run ubi_remove_rootfs ; ubi check fip && ubi remove fip ; ubi create fip 0x100000 static && ubi write $loadaddr fip $filesize ++ubi_write_production=ubi check fit && ubi remove fit ; run ubi_remove_rootfs ; ubi create fit $filesize dynamic && ubi write $loadaddr fit $filesize ++_init_env=setenv _init_env ; run ubi_create_env ; saveenv ; saveenv ; run ubi_create_board_data ++_firstboot=setenv _firstboot ; run ethaddr_factory ; 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" +--- /dev/null ++++ b/dts/upstream/src/arm64/airoha/an7581-nokia-xg-040g-md.dts +@@ -0,0 +1,99 @@ ++// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++/dts-v1/; ++ ++#include ++#include ++#include ++#include "en7581.dtsi" ++ ++/ { ++ model = "Nokia XG-040G-MD"; ++ compatible = "nokia,xg-040g-md", ++ "airoha,an7581", ++ "airoha,en7581"; ++ ++ chosen { ++ bootargs = "console=ttyS0,115200 earlycon"; ++ stdout-path = "serial0:115200n8"; ++ linux,usable-memory-range = <0x0 0x80200000 0x0 0x1fe00000>; ++ }; ++ ++ memory@80000000 { ++ device_type = "memory"; ++ reg = <0x0 0x80000000 0x0 0x20000000>; ++ }; ++ ++ keys { ++ compatible = "gpio-keys"; ++ ++ button-0 { ++ label = "reset"; ++ linux,code = ; ++ gpios = <&en7581_pinctrl 0 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led-0 { ++ label = "green:power"; ++ gpios = <&en7581_pinctrl 17 GPIO_ACTIVE_LOW>; ++ }; ++ ++ led-1 { ++ label = "green:wan"; ++ gpios = <&en7581_pinctrl 18 GPIO_ACTIVE_LOW>; ++ }; ++ ++ led-2 { ++ label = "red:wan"; ++ gpios = <&en7581_pinctrl 19 GPIO_ACTIVE_LOW>; ++ }; ++ ++ led-3 { ++ label = "green:wan-online"; ++ gpios = <&en7581_pinctrl 20 GPIO_ACTIVE_LOW>; ++ }; ++ ++ led-4 { ++ label = "green:usb-2"; ++ gpios = <&en7581_pinctrl 34 GPIO_ACTIVE_LOW>; ++ }; ++ ++ led-5 { ++ label = "green:usb-1"; ++ gpios = <&en7581_pinctrl 35 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; ++ ++&snfi { ++ status = "okay"; ++}; ++ ++&spi_nand { ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "bl2"; ++ reg = <0x0 0x20000>; ++ }; ++ ++ partition@20000 { ++ label = "ubi"; ++ reg = <0x20000 0xffe0000>; ++ }; ++ }; ++}; ++ ++&i2c0 { ++ status = "okay"; ++}; ++ ++ð { ++ status = "okay"; ++}; diff --git a/package/boot/uboot-layerscape/Makefile b/package/boot/uboot-layerscape/Makefile index f97cdd9faf..de6cc2e040 100644 --- a/package/boot/uboot-layerscape/Makefile +++ b/package/boot/uboot-layerscape/Makefile @@ -8,13 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=uboot-layerscape -PKG_VERSION:=6.12.20.2.0.0 +PKG_VERSION:=6.18.2.1.0.0 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/nxp-qoriq/u-boot -PKG_SOURCE_VERSION:=lf-6.12.20-2.0.0 -PKG_MIRROR_HASH:=13594333aa3ee131d5832b4da88f73cf0744d98c28e90ad3e03594788c486e37 +PKG_SOURCE_VERSION:=lf-6.18.2-1.0.0 +PKG_MIRROR_HASH:=047df1acdbf35004bc9d896ee688da5930da3b8a6f02a7bdc109a1367be61fee include $(INCLUDE_DIR)/u-boot.mk include $(INCLUDE_DIR)/package.mk diff --git a/package/boot/uboot-mediatek/Makefile b/package/boot/uboot-mediatek/Makefile index 9b907145c0..cec0e5dafe 100644 --- a/package/boot/uboot-mediatek/Makefile +++ b/package/boot/uboot-mediatek/Makefile @@ -353,6 +353,18 @@ define U-Boot/mt7981_comfast_cf-wr632ax DEPENDS:=+trusted-firmware-a-mt7981-spim-nand-ddr3-1866 endef +define U-Boot/mt7981_creatlentem_clt-r30b1-ubi + NAME:=CreatLentem CLT-R30B1 (UBI) + BUILD_SUBTARGET:=filogic + BUILD_DEVICES:=creatlentem_clt-r30b1-ubi + UBOOT_CONFIG:=mt7981_creatlentem_clt-r30b1-ubi + UBOOT_IMAGE:=u-boot.fip + BL2_BOOTDEV:=spim-nand-ubi + BL2_SOC:=mt7981 + BL2_DDRTYPE:=ddr3-1866 + DEPENDS:=+trusted-firmware-a-mt7981-spim-nand-ubi-ddr3-1866 +endef + define U-Boot/mt7981_cudy_tr3000-v1 NAME:=Cudy TR3000 v1 BUILD_SUBTARGET:=filogic @@ -1359,6 +1371,7 @@ UBOOT_TARGETS := \ mt7981_cmcc_rax3000me-nand-ddr3 \ mt7981_cmcc_rax3000me-nand-ddr4 \ mt7981_comfast_cf-wr632ax \ + mt7981_creatlentem_clt-r30b1-ubi \ mt7981_cudy_tr3000-v1 \ mt7981_cudy_wbr3000uax-v1 \ mt7981_cudy_wr3000e-v1 \ diff --git a/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000e-v1.patch b/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000e-v1.patch index 5234402172..eff0fbdd0b 100644 --- a/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000e-v1.patch +++ b/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000e-v1.patch @@ -1,7 +1,8 @@ --- /dev/null +++ b/configs/mt7981_cudy_wr3000e-v1_defconfig -@@ -0,0 +1,108 @@ +@@ -0,0 +1,112 @@ +CONFIG_ARM=y ++CONFIG_ARM_SMCCC=y +CONFIG_SYS_HAS_NONCACHED_MEMORY=y +CONFIG_POSITION_INDEPENDENT=y +CONFIG_ARCH_MEDIATEK=y @@ -34,6 +35,7 @@ +CONFIG_CMD_ASKENV=y +CONFIG_CMD_ERASEENV=y +CONFIG_CMD_ENV_FLAGS=y ++CONFIG_CMD_RNG=y +CONFIG_CMD_STRINGS=y +CONFIG_CMD_DM=y +CONFIG_CMD_GPIO=y @@ -101,6 +103,8 @@ +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_DM_REGULATOR_GPIO=y +CONFIG_RAM=y ++CONFIG_DM_RNG=y ++CONFIG_RNG_MTK_V2=y +CONFIG_DM_SERIAL=y +CONFIG_SERIAL_RX_BUFFER=y +CONFIG_MTK_SERIAL=y diff --git a/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000h-v1.patch b/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000h-v1.patch index 3dcf8227e3..eee31c7a61 100644 --- a/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000h-v1.patch +++ b/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000h-v1.patch @@ -1,7 +1,8 @@ --- /dev/null +++ b/configs/mt7981_cudy_wr3000h-v1_defconfig -@@ -0,0 +1,108 @@ +@@ -0,0 +1,112 @@ +CONFIG_ARM=y ++CONFIG_ARM_SMCCC=y +CONFIG_SYS_HAS_NONCACHED_MEMORY=y +CONFIG_POSITION_INDEPENDENT=y +CONFIG_ARCH_MEDIATEK=y @@ -34,6 +35,7 @@ +CONFIG_CMD_ASKENV=y +CONFIG_CMD_ERASEENV=y +CONFIG_CMD_ENV_FLAGS=y ++CONFIG_CMD_RNG=y +CONFIG_CMD_STRINGS=y +CONFIG_CMD_DM=y +CONFIG_CMD_GPIO=y @@ -101,6 +103,8 @@ +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_DM_REGULATOR_GPIO=y +CONFIG_RAM=y ++CONFIG_DM_RNG=y ++CONFIG_RNG_MTK_V2=y +CONFIG_DM_SERIAL=y +CONFIG_SERIAL_RX_BUFFER=y +CONFIG_MTK_SERIAL=y diff --git a/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000p-v1.patch b/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000p-v1.patch index fa2e0d1724..8016096fe0 100644 --- a/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000p-v1.patch +++ b/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000p-v1.patch @@ -1,7 +1,8 @@ --- /dev/null +++ b/configs/mt7981_cudy_wr3000p-v1_defconfig -@@ -0,0 +1,108 @@ +@@ -0,0 +1,112 @@ +CONFIG_ARM=y ++CONFIG_ARM_SMCCC=y +CONFIG_SYS_HAS_NONCACHED_MEMORY=y +CONFIG_POSITION_INDEPENDENT=y +CONFIG_ARCH_MEDIATEK=y @@ -34,6 +35,7 @@ +CONFIG_CMD_ASKENV=y +CONFIG_CMD_ERASEENV=y +CONFIG_CMD_ENV_FLAGS=y ++CONFIG_CMD_RNG=y +CONFIG_CMD_STRINGS=y +CONFIG_CMD_DM=y +CONFIG_CMD_GPIO=y @@ -101,6 +103,8 @@ +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_DM_REGULATOR_GPIO=y +CONFIG_RAM=y ++CONFIG_DM_RNG=y ++CONFIG_RNG_MTK_V2=y +CONFIG_DM_SERIAL=y +CONFIG_SERIAL_RX_BUFFER=y +CONFIG_MTK_SERIAL=y diff --git a/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000s-v1.patch b/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000s-v1.patch index 1b52dfddba..b1e46b81d9 100644 --- a/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000s-v1.patch +++ b/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000s-v1.patch @@ -1,7 +1,8 @@ --- /dev/null +++ b/configs/mt7981_cudy_wr3000s-v1_defconfig -@@ -0,0 +1,108 @@ +@@ -0,0 +1,112 @@ +CONFIG_ARM=y ++CONFIG_ARM_SMCCC=y +CONFIG_SYS_HAS_NONCACHED_MEMORY=y +CONFIG_POSITION_INDEPENDENT=y +CONFIG_ARCH_MEDIATEK=y @@ -34,6 +35,7 @@ +CONFIG_CMD_ASKENV=y +CONFIG_CMD_ERASEENV=y +CONFIG_CMD_ENV_FLAGS=y ++CONFIG_CMD_RNG=y +CONFIG_CMD_STRINGS=y +CONFIG_CMD_DM=y +CONFIG_CMD_GPIO=y @@ -101,6 +103,8 @@ +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_DM_REGULATOR_GPIO=y +CONFIG_RAM=y ++CONFIG_DM_RNG=y ++CONFIG_RNG_MTK_V2=y +CONFIG_DM_SERIAL=y +CONFIG_SERIAL_RX_BUFFER=y +CONFIG_MTK_SERIAL=y diff --git a/package/boot/uboot-mediatek/patches/473-add-creatlentem_clt-r30b1-ubi.patch b/package/boot/uboot-mediatek/patches/473-add-creatlentem_clt-r30b1-ubi.patch new file mode 100644 index 0000000000..e53347fe03 --- /dev/null +++ b/package/boot/uboot-mediatek/patches/473-add-creatlentem_clt-r30b1-ubi.patch @@ -0,0 +1,315 @@ +--- /dev/null ++++ b/configs/mt7981_creatlentem_clt-r30b1-ubi_defconfig +@@ -0,0 +1,112 @@ ++CONFIG_ARM=y ++CONFIG_ARM_SMCCC=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_DEFAULT_DEVICE_TREE="mt7981-creatlentem-clt-r30b1-ubi" ++CONFIG_OF_LIBFDT_OVERLAY=y ++CONFIG_TARGET_MT7981=y ++CONFIG_SYS_LOAD_ADDR=0x46000000 ++CONFIG_PRE_CON_BUF_ADDR=0x4007EF00 ++CONFIG_DEBUG_UART_BASE=0x11002000 ++CONFIG_DEBUG_UART_CLOCK=40000000 ++CONFIG_DEBUG_UART=y ++CONFIG_FIT=y ++CONFIG_BOOTDELAY=30 ++CONFIG_AUTOBOOT_KEYED=y ++CONFIG_AUTOBOOT_MENU_SHOW=y ++CONFIG_USE_PREBOOT=y ++CONFIG_DEFAULT_FDT_FILE="mt7981-creatlentem-clt-r30b1-ubi" ++CONFIG_LOGLEVEL=7 ++CONFIG_PRE_CONSOLE_BUFFER=y ++CONFIG_LOG=y ++# CONFIG_BOARD_INIT is not set ++CONFIG_BOARD_LATE_INIT=y ++CONFIG_HUSH_PARSER=y ++CONFIG_SYS_PROMPT="MT7981> " ++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_RNG=y ++CONFIG_CMD_STRINGS=y ++CONFIG_CMD_DM=y ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_MTD=y ++CONFIG_CMD_PART=y ++CONFIG_CMD_TFTPSRV=y ++CONFIG_CMD_RARP=y ++CONFIG_CMD_CDP=y ++CONFIG_CMD_SNTP=y ++CONFIG_CMD_LINK_LOCAL=y ++CONFIG_CMD_DHCP=y ++CONFIG_CMD_DNS=y ++CONFIG_CMD_PING=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_UBI=y ++CONFIG_CMD_UBI_RENAME=y ++CONFIG_OF_EMBED=y ++CONFIG_ENV_OVERWRITE=y ++CONFIG_ENV_IS_IN_UBI=y ++CONFIG_ENV_REDUNDANT=y ++CONFIG_ENV_UBI_PART="ubi" ++CONFIG_ENV_UBI_VOLUME="ubootenv" ++CONFIG_ENV_UBI_VOLUME_REDUND="ubootenv2" ++CONFIG_ENV_RELOC_GD_ENV_ADDR=y ++CONFIG_ENV_USE_DEFAULT_ENV_TEXT_FILE=y ++CONFIG_ENV_DEFAULT_ENV_TEXT_FILE="defenvs/creatlentem_clt-r30b1-ubi_env" ++CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y ++CONFIG_VERSION_VARIABLE=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_NET_RANDOM_ETHADDR=y ++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_MMC is not set ++CONFIG_MTD=y ++CONFIG_DM_MTD=y ++CONFIG_MTD_SPI_NAND=y ++CONFIG_MTD_UBI_FASTMAP=y ++CONFIG_PHY_FIXED=y ++CONFIG_MEDIATEK_ETH=y ++CONFIG_PHY=y ++CONFIG_PINCTRL=y ++CONFIG_PINCONF=y ++CONFIG_PINCTRL_MT7981=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_RAM=y ++CONFIG_DM_RNG=y ++CONFIG_RNG_MTK_V2=y ++CONFIG_DM_SERIAL=y ++CONFIG_MTK_SERIAL=y ++CONFIG_SPI=y ++CONFIG_DM_SPI=y ++CONFIG_MTK_SPIM=y ++CONFIG_ZSTD=y ++CONFIG_HEXDUMP=y +--- /dev/null ++++ b/defenvs/creatlentem_clt-r30b1-ubi_env +@@ -0,0 +1,54 @@ ++ipaddr=192.168.1.1 ++serverip=192.168.1.254 ++loadaddr=0x46000000 ++console=earlycon=uart8250,mmio32,0x11002000 console=ttyS0 ++bootcmd=if pstore check ; then run boot_recovery ; else run boot_ubi ; fi ++bootconf=config-1 ++bootdelay=0 ++bootfile=immortalwrt-mediatek-filogic-creatlentem_clt-r30b1-ubi-initramfs-recovery.itb ++bootfile_bl2=immortalwrt-mediatek-filogic-creatlentem_clt-r30b1-ubi-preloader.bin ++bootfile_fip=immortalwrt-mediatek-filogic-creatlentem_clt-r30b1-ubi-bl31-uboot.fip ++bootfile_upg=immortalwrt-mediatek-filogic-creatlentem_clt-r30b1-ubi-squashfs-sysupgrade.itb ++bootled_pwr=red:status ++bootled_rec=green: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_pwr off ; 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_rec off ; run ubi_read_production && bootm $loadaddr#$bootconf ; led $bootled_pwr off ++boot_recovery=led $bootled_pwr off ; 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_pwr off ; while true ; do run boot_tftp_recovery ; sleep 1 ; done ++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_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=tftpboot $loadaddr $bootfile && bootm $loadaddr#$bootconf ++boot_tftp_write_fip=tftpboot $loadaddr $bootfile_fip && run ubi_write_fip && run reset_factory ++boot_tftp_write_bl2=tftpboot $loadaddr $bootfile_bl2 && run mtd_write_bl2 ++preboot=led $bootled_pwr on ; led $bootled_rec on ++reset_factory=mw $loadaddr 0xff 0x1f000 ; ubi write $loadaddr ubootenv 0x1f000 ; ubi write $loadaddr ubootenv2 0x1f000 ; ubi remove rootfs_data ++mtd_write_bl2=mtd erase bl2 && mtd write bl2 $loadaddr ++ubi_create_env=ubi check ubootenv || ubi create ubootenv 0x1f000 dynamic ; ubi check ubootenv2 || ubi create ubootenv2 0x1f000 dynamic ++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_fip=run ubi_remove_rootfs ; ubi check fip && ubi remove fip ; ubi create fip 0x200000 static ; ubi write $loadaddr fip 0x200000 ++ubi_write_production=ubi check fit && ubi remove fit ; run ubi_remove_rootfs ; ubi create fit $filesize dynamic && ubi write $loadaddr fit $filesize ++ubi_write_recovery=ubi check recovery && ubi remove recovery ; run ubi_remove_rootfs ; ubi create recovery $filesize dynamic && 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" +--- /dev/null ++++ b/arch/arm/dts/mt7981-creatlentem-clt-r30b1-ubi.dts +@@ -0,0 +1,140 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++ ++/dts-v1/; ++#include "mt7981.dtsi" ++#include ++#include ++ ++/ { ++ model = "CreatLentem CLT-R30B1 (UBI)"; ++ compatible = "creatlentem,clt-r30b1-ubi", "mediatek,mt7981"; ++ ++ chosen { ++ stdout-path = &uart0; ++ tick-timer = &timer0; ++ }; ++ ++ memory@40000000 { ++ device_type = "memory"; ++ reg = <0x40000000 0x10000000>; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ ++ button-reset { ++ label = "reset"; ++ linux,code = ; ++ gpios = <&pio 1 GPIO_ACTIVE_LOW>; ++ }; ++ ++ button-wps { ++ label = "wps"; ++ linux,code = ; ++ gpios = <&pio 0 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++ ++ gpio-leds { ++ compatible = "gpio-leds"; ++ ++ led_status_green: led-0 { ++ label = "green:status"; ++ gpios = <&pio 11 GPIO_ACTIVE_LOW>; ++ }; ++ ++ led_status_red: led-1 { ++ label = "red:status"; ++ gpios = <&pio 12 GPIO_ACTIVE_LOW>; ++ default-state = "on"; ++ }; ++ }; ++}; ++ ++ð { ++ status = "okay"; ++ mediatek,gmac-id = <0>; ++ phy-mode = "2500base-x"; ++ mediatek,switch = "mt7531"; ++ reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>; ++ ++ fixed-link { ++ speed = <2500>; ++ full-duplex; ++ }; ++}; ++ ++&pio { ++ 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 = ; ++ }; ++ }; ++ ++ line_8-hog { ++ gpio-hog; ++ gpios = <8 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "LEDs power"; ++ }; ++}; ++ ++&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 = <0x0 0x100000>; ++ }; ++ ++ partition@100000 { ++ label = "ubi"; ++ reg = <0x100000 0x7f00000>; ++ compatible = "linux,ubi"; ++ }; ++ }; ++ }; ++}; ++ ++&uart0 { ++ mediatek,force-highspeed; ++ status = "okay"; ++}; ++ ++&watchdog { ++ status = "disabled"; ++}; diff --git a/package/boot/uboot-mediatek/patches/503-add-wavlink-wl-wnt100x3.patch b/package/boot/uboot-mediatek/patches/503-add-wavlink-wl-wnt100x3.patch index e21dfc60b4..90f260eba9 100644 --- a/package/boot/uboot-mediatek/patches/503-add-wavlink-wl-wnt100x3.patch +++ b/package/boot/uboot-mediatek/patches/503-add-wavlink-wl-wnt100x3.patch @@ -1,7 +1,8 @@ --- /dev/null +++ b/configs/mt7981_wavlink_wl-wnt100x3_defconfig -@@ -0,0 +1,108 @@ +@@ -0,0 +1,112 @@ +CONFIG_ARM=y ++CONFIG_ARM_SMCCC=y +CONFIG_SYS_HAS_NONCACHED_MEMORY=y +CONFIG_POSITION_INDEPENDENT=y +CONFIG_ARCH_MEDIATEK=y @@ -34,6 +35,7 @@ +CONFIG_CMD_ASKENV=y +CONFIG_CMD_ERASEENV=y +CONFIG_CMD_ENV_FLAGS=y ++CONFIG_CMD_RNG=y +CONFIG_CMD_STRINGS=y +CONFIG_CMD_DM=y +CONFIG_CMD_GPIO=y @@ -101,6 +103,8 @@ +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_DM_REGULATOR_GPIO=y +CONFIG_RAM=y ++CONFIG_DM_RNG=y ++CONFIG_RNG_MTK_V2=y +CONFIG_DM_SERIAL=y +CONFIG_SERIAL_RX_BUFFER=y +CONFIG_MTK_SERIAL=y diff --git a/package/boot/uboot-tools/uboot-envtools/files/airoha_an7581 b/package/boot/uboot-tools/uboot-envtools/files/airoha_an7581 index 29e6c39886..c0a5c9fb44 100644 --- a/package/boot/uboot-tools/uboot-envtools/files/airoha_an7581 +++ b/package/boot/uboot-tools/uboot-envtools/files/airoha_an7581 @@ -12,9 +12,13 @@ touch /etc/config/ubootenv board=$(board_name) case "$board" in -gemtek,w1700k-ubi) +gemtek,w1700k-ubi|\ +nokia,xg-040g-md-ubi) ubootenv_add_ubi_default ;; +nokia,xg-040g-md) + ubootenv_add_mtd "u-boot-env" "0x1c000" "0x4000" "0x4000" + ;; esac config_load ubootenv diff --git a/package/boot/uboot-tools/uboot-envtools/files/ipq806x b/package/boot/uboot-tools/uboot-envtools/files/ipq806x index 8fc6e1701d..f8c79ab6a7 100644 --- a/package/boot/uboot-tools/uboot-envtools/files/ipq806x +++ b/package/boot/uboot-tools/uboot-envtools/files/ipq806x @@ -35,6 +35,12 @@ arris,tr4400-v2|\ askey,rt4230w-rev6) ubootenv_add_uci_config "/dev/mtd9" "0x0" "0x40000" "0x20000" ;; +aruba,ap-32x|\ +ignitenet,ss-w2-ac2600|\ +qcom,ipq8064-ap148|\ +qcom,ipq8064-db149) + ubootenv_add_uci_config $(ubootenv_mtdinfo) + ;; edgecore,ecw5410) ubootenv_add_uci_config "/dev/mtd11" "0x0" "0x10000" "0x10000" ;; @@ -42,11 +48,6 @@ extreme,ap3935) ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x10000" "0x10000" ubootenv_add_uci_config "/dev/mtd3" "0x0" "0x10000" "0x10000" ;; -ignitenet,ss-w2-ac2600|\ -qcom,ipq8064-ap148|\ -qcom,ipq8064-db149) - ubootenv_add_uci_config $(ubootenv_mtdinfo) - ;; linksys,ea7500-v1|\ linksys,ea8500) ubootenv_add_uci_config "/dev/mtd10" "0x0" "0x20000" "0x20000" diff --git a/package/boot/uboot-tools/uboot-envtools/files/mediatek_filogic b/package/boot/uboot-tools/uboot-envtools/files/mediatek_filogic index 7b5283210c..85d63b90e3 100644 --- a/package/boot/uboot-tools/uboot-envtools/files/mediatek_filogic +++ b/package/boot/uboot-tools/uboot-envtools/files/mediatek_filogic @@ -28,6 +28,7 @@ asus,zenwifi-bt8-ubootmod|\ cetron,ct3003-ubootmod|\ cmcc,a10-ubootmod|\ comfast,cf-wr632ax-ubootmod|\ +creatlentem,clt-r30b1-ubi|\ cudy,tr3000-v1-ubootmod|\ cudy,wbr3000uax-v1-ubootmod|\ cudy,wr3000e-v1-ubootmod|\ diff --git a/package/boot/uboot-tools/uboot-envtools/files/mvebu b/package/boot/uboot-tools/uboot-envtools/files/mvebu index 7346611acb..018177ab6e 100644 --- a/package/boot/uboot-tools/uboot-envtools/files/mvebu +++ b/package/boot/uboot-tools/uboot-envtools/files/mvebu @@ -78,6 +78,9 @@ methode,edpu) synology,ds213j) ubootenv_add_mtd "u-boot-env" "0x0" "0x10000" "0x10000" ;; +zyxel,nas326) + ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x80000" "0x80000" + ;; esac config_load ubootenv diff --git a/package/boot/uboot-tools/uboot-envtools/files/realtek b/package/boot/uboot-tools/uboot-envtools/files/realtek index 826914e35d..2e4ce297d2 100644 --- a/package/boot/uboot-tools/uboot-envtools/files/realtek +++ b/package/boot/uboot-tools/uboot-envtools/files/realtek @@ -37,6 +37,7 @@ iodata,bsh-g24mb) ubootenv_add_sys_mtd "u-boot-env2" "0x0" "0x3800" "0x10000" ;; tplink,sg2008p-v1|\ +tplink,sg2008p-v3|\ tplink,sg2210p-v3|\ tplink,sg2452p-v4) ubootenv_add_mtd "u-boot-env" "0x0" "0x20000" "0x10000" diff --git a/package/boot/uboot-zynq/Makefile b/package/boot/uboot-zynq/Makefile index 0f93c4f453..dc58d98969 100644 --- a/package/boot/uboot-zynq/Makefile +++ b/package/boot/uboot-zynq/Makefile @@ -30,6 +30,12 @@ define U-Boot/zc702 BUILD_DEVICES:=xlnx_zynq-zc702 endef +define U-Boot/antminer-s9 + NAME:=Bitmain Antminer S9 control board + BUILD_DEVICES:=bitmain_zynq-antminer-s9 + UBOOT_CONFIG:=bitmain_antminer_s9 +endef + define U-Boot/zed NAME:=Avnet Digilent ZedBoard Dev Board BUILD_DEVICES:=avnet_zynq-zed @@ -46,6 +52,7 @@ define U-Boot/zybo_z7 endef UBOOT_TARGETS := \ + antminer-s9 \ zc702 \ zed \ zybo \ diff --git a/package/boot/uboot-zynq/files/uEnv-default.txt b/package/boot/uboot-zynq/files/uEnv-default.txt index 5030b07784..ec15c820e2 100644 --- a/package/boot/uboot-zynq/files/uEnv-default.txt +++ b/package/boot/uboot-zynq/files/uEnv-default.txt @@ -1 +1,2 @@ bootargs=console=ttyPS0,115200n8 root=/dev/mmcblk0p2 rootwait earlyprintk +bootcmd=run sdboot diff --git a/package/boot/uboot-zynq/patches/120-antminer-s9-restore-sdboot-capability.patch b/package/boot/uboot-zynq/patches/120-antminer-s9-restore-sdboot-capability.patch new file mode 100644 index 0000000000..cd90fd22c9 --- /dev/null +++ b/package/boot/uboot-zynq/patches/120-antminer-s9-restore-sdboot-capability.patch @@ -0,0 +1,37 @@ +--- a/include/configs/bitmain_antminer_s9.h ++++ b/include/configs/bitmain_antminer_s9.h +@@ -20,6 +20,34 @@ + "initrd_high=0xefff000\0" \ + "devnum=0\0" \ + "wdstop=mw f8005000 ABC000\0" \ ++ "scriptaddr=0x3000000\0" \ ++ "loadbootenv_addr=0x2000000\0" \ ++ "fit_image=fit.itb\0" \ ++ "load_addr=0x2000000\0" \ ++ "bootenv=uEnv.txt\0" \ ++ "bootenv_dev=mmc\0" \ ++ "loadbootenv=load ${bootenv_dev} 0 ${loadbootenv_addr} ${bootenv}\0" \ ++ "importbootenv=echo Importing environment from ${bootenv_dev} ...; " \ ++ "env import -t ${loadbootenv_addr} $filesize\0" \ ++ "bootenv_existence_test=test -e ${bootenv_dev} 0 /${bootenv}\0" \ ++ "setbootenv=if env run bootenv_existence_test; then " \ ++ "if env run loadbootenv; then " \ ++ "env run importbootenv; " \ ++ "fi; " \ ++ "fi; \0" \ ++ "sd_loadbootenv=setenv bootenv_dev mmc && " \ ++ "run setbootenv \0" \ ++ "preboot=if test $modeboot = sdboot; then " \ ++ "run sd_loadbootenv; " \ ++ "echo Checking if uenvcmd is set ...; " \ ++ "if test -n $uenvcmd; then " \ ++ "echo Running uenvcmd ...; " \ ++ "run uenvcmd; " \ ++ "fi; " \ ++ "fi; \0" \ ++ "sdboot=echo Copying FIT from SD to RAM... && " \ ++ "load mmc 0 ${load_addr} ${fit_image} && " \ ++ "bootm ${load_addr}\0" \ + BOOTENV + + #include diff --git a/package/firmware/layerscape/fman-ucode/Makefile b/package/firmware/layerscape/fman-ucode/Makefile index 315f31a6e6..934f3ad83c 100644 --- a/package/firmware/layerscape/fman-ucode/Makefile +++ b/package/firmware/layerscape/fman-ucode/Makefile @@ -8,13 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=fman-ucode -PKG_VERSION:=6.12.20.2.0.0 +PKG_VERSION:=6.18.2.1.0.0 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/nxp-qoriq/qoriq-fm-ucode -PKG_SOURCE_VERSION:=lf-6.12.20-2.0.0 -PKG_MIRROR_HASH:=15b5df228b23b4cbdd1af484c98069b558d32ece15a80f0dabe22af6e5ee1ba1 +PKG_SOURCE_VERSION:=lf-6.18.2-1.0.0 +PKG_MIRROR_HASH:=155b74a390c8eefc7767b68993eb41cf04ac6d578ae53eb82cff40a1c1251375 PKG_FLAGS:=nonshared diff --git a/package/firmware/layerscape/ls-ddr-phy/Makefile b/package/firmware/layerscape/ls-ddr-phy/Makefile index ff7637ce2f..50496381ee 100644 --- a/package/firmware/layerscape/ls-ddr-phy/Makefile +++ b/package/firmware/layerscape/ls-ddr-phy/Makefile @@ -6,13 +6,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ls-ddr-phy -PKG_VERSION:=6.12.20.2.0.0 +PKG_VERSION:=6.18.2.1.0.0 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/NXP/ddr-phy-binary.git -PKG_SOURCE_VERSION:=lf-6.12.20-2.0.0 -PKG_MIRROR_HASH:=162616b23041e345a9a12080005ee1c24c9903d6809c60a022588a1c7f5b1577 +PKG_SOURCE_VERSION:=lf-6.18.2-1.0.0 +PKG_MIRROR_HASH:=376d9af14bfe4ee6f14ae77ace9d592606d82ad3d7af87dda47d5fa8fd3ba10e PKG_BUILD_DEPENDS:=tfa-layerscape/host PKG_LICENSE:=EULA diff --git a/package/firmware/layerscape/ls-dpl/Makefile b/package/firmware/layerscape/ls-dpl/Makefile index ade37d7dff..b09d900c7b 100644 --- a/package/firmware/layerscape/ls-dpl/Makefile +++ b/package/firmware/layerscape/ls-dpl/Makefile @@ -8,13 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ls-dpl -PKG_VERSION:=10.39.0 +PKG_VERSION:=10.40.0 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/nxp-qoriq/mc-utils -PKG_SOURCE_VERSION:=mc_release_10.39.0 -PKG_MIRROR_HASH:=48e0ad66f536689bf8cfd115420422a1c746cd609816bd9b07ef8ef358a85cf4 +PKG_SOURCE_VERSION:=mc_release_10.40.0 +PKG_MIRROR_HASH:=d29481aeddbfff337b8bdcdd0a93c19dd0673f0408246e7f3f98cd2c0af15cc3 PKG_FLAGS:=nonshared diff --git a/package/firmware/layerscape/ls-mc/Makefile b/package/firmware/layerscape/ls-mc/Makefile index 54b17f3e97..79bc69be6a 100644 --- a/package/firmware/layerscape/ls-mc/Makefile +++ b/package/firmware/layerscape/ls-mc/Makefile @@ -8,13 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ls-mc -PKG_VERSION:=10.39.0 +PKG_VERSION:=10.40.0 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/NXP/qoriq-mc-binary.git -PKG_SOURCE_VERSION:=mc_release_10.39.0 -PKG_MIRROR_HASH:=0676072ec3fcb7ad3ec101ea279f5e7b41b292b44426563aba9062668f9855ab +PKG_SOURCE_VERSION:=mc_release_10.40.0 +PKG_MIRROR_HASH:=d4359637da641108f5c8b39c1db43d9dda4d2f8e64d4a4c89ce0301ebd12b3b1 PKG_FLAGS:=nonshared diff --git a/package/firmware/layerscape/ls-rcw/Makefile b/package/firmware/layerscape/ls-rcw/Makefile index 03049add1c..0ea0165d67 100644 --- a/package/firmware/layerscape/ls-rcw/Makefile +++ b/package/firmware/layerscape/ls-rcw/Makefile @@ -8,13 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ls-rcw -PKG_VERSION:=6.12.20.2.0.0 +PKG_VERSION:=6.18.2.1.0.0 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/nxp-qoriq/rcw -PKG_SOURCE_VERSION:=lf-6.12.20-2.0.0 -PKG_MIRROR_HASH:=8436e04a01fa7a0da3512dae035b47122691fc860fa2c36da20552bceec9246a +PKG_SOURCE_VERSION:=lf-6.18.2-1.0.0 +PKG_MIRROR_HASH:=a2f908c2b0a31a728f72ca9b9edb1a349c3f9037d65bed6a8236818a1a243873 PKG_FLAGS:=nonshared diff --git a/package/firmware/layerscape/ppfe-firmware/Makefile b/package/firmware/layerscape/ppfe-firmware/Makefile index 52df30c36d..81d0d3cc8e 100644 --- a/package/firmware/layerscape/ppfe-firmware/Makefile +++ b/package/firmware/layerscape/ppfe-firmware/Makefile @@ -8,13 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ppfe -PKG_VERSION:=6.12.20.2.0.0 +PKG_VERSION:=6.18.2.1.0.0 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/nxp-qoriq/qoriq-engine-pfe-bin -PKG_SOURCE_VERSION:=lf-6.12.20-2.0.0 -PKG_MIRROR_HASH:=57ff6ebc78e774a12f64ac7d4738621edabdeee3a46c6ee69343ba0a8bff73cd +PKG_SOURCE_VERSION:=lf-6.18.2-1.0.0 +PKG_MIRROR_HASH:=71bed42bc91366967a8efe9343ccecd1cec7d7538a9605f642b24cfd6a4ba07e PKG_FLAGS:=nonshared diff --git a/package/firmware/linux-firmware/Makefile b/package/firmware/linux-firmware/Makefile index 74b23de710..61fce656b6 100644 --- a/package/firmware/linux-firmware/Makefile +++ b/package/firmware/linux-firmware/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=linux-firmware -PKG_VERSION:=20260519 +PKG_VERSION:=20260622 PKG_RELEASE:=1 PKG_SOURCE_URL:=@KERNEL/linux/kernel/firmware PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz -PKG_HASH:=b14e7197a290a7e5569f5ef790cde289bddc47e32126f2eb262a8e677fc39727 +PKG_HASH:=2b9d8a358e76eb766588609135e53fa548b902c551daae33ee32f26f25e60dbb PKG_MAINTAINER:=Felix Fietkau diff --git a/package/kernel/button-hotplug/Makefile b/package/kernel/button-hotplug/Makefile index 8e8c02609c..2908e5b030 100644 --- a/package/kernel/button-hotplug/Makefile +++ b/package/kernel/button-hotplug/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=button-hotplug -PKG_RELEASE:=3 +PKG_RELEASE:=4 PKG_LICENSE:=GPL-2.0 include $(INCLUDE_DIR)/package.mk diff --git a/package/kernel/lantiq/vrx518_ep/src/ep.c b/package/kernel/lantiq/vrx518_ep/src/ep.c index 40fc9d3629..ab350b672d 100644 --- a/package/kernel/lantiq/vrx518_ep/src/ep.c +++ b/package/kernel/lantiq/vrx518_ep/src/ep.c @@ -52,13 +52,8 @@ module_param(pcie_switch_exist, bool, 0644); MODULE_PARM_DESC(pcie_switch_exist, "pcie switch existed or not"); static const char dc_ep_driver_name[] = "vrx518"; -static const char dc_ep_driver_version[] = DRV_VERSION; -static const char dc_ep_driver_string[] = - "Intel(R) SmartPHY DSL(VRX518) PCIe EP/ACA Driver"; -static const char dc_ep_copyright[] = - "Copyright (c) 2016 Intel Corporation."; -static struct dc_ep_info g_dc_ep_info; +static struct dc_ep_info g_dc_ep_info = {}; static DEFINE_SPINLOCK(dc_ep_lock); static inline void reset_assert_device(struct dc_ep_dev *dev, u32 bits) @@ -729,7 +724,7 @@ static const struct pci_device_id dc_ep_id_table[] = { MODULE_DEVICE_TABLE(pci, dc_ep_id_table); static struct pci_driver dc_ep_driver = { - .name = (char *)dc_ep_driver_name, + .name = dc_ep_driver_name, .id_table = dc_ep_id_table, .probe = dc_ep_probe, .remove = dc_ep_remove, @@ -738,31 +733,7 @@ static struct pci_driver dc_ep_driver = { /* AER is controlled by RC */ }; -static int __init dc_ep_init(void) -{ - pr_info("%s - version %s\n", - dc_ep_driver_string, dc_ep_driver_version); - - pr_info("%s\n", dc_ep_copyright); - memset(&g_dc_ep_info, 0, sizeof(struct dc_ep_info)); - - if (pci_register_driver(&dc_ep_driver) < 0) { - pr_err("%s: No devices found, driver not installed.\n", - __func__); - return -ENODEV; - } - return 0; -} -module_init(dc_ep_init); - -static void __exit dc_ep_exit(void) -{ - pci_unregister_driver(&dc_ep_driver); - - pr_info("%s: %s driver unloaded\n", __func__, - dc_ep_driver_name); -} -module_exit(dc_ep_exit); +module_pci_driver(dc_ep_driver); MODULE_AUTHOR("Intel Corporation, "); MODULE_DESCRIPTION("Intel(R) SmartPHY PCIe EP/ACA Driver"); diff --git a/package/kernel/linux/modules/fs.mk b/package/kernel/linux/modules/fs.mk index 59e7b99634..ff132aa712 100644 --- a/package/kernel/linux/modules/fs.mk +++ b/package/kernel/linux/modules/fs.mk @@ -491,14 +491,15 @@ define KernelPackage/fs-nfs-common-rpcsec TITLE:=NFS Secure RPC DEPENDS:= \ +kmod-fs-nfs-common \ - +kmod-crypto-des \ - +kmod-crypto-cbc \ - +kmod-crypto-cts \ - +kmod-crypto-md5 \ - +kmod-crypto-sha1 \ + +kmod-crypto-manager \ + +kmod-crypto-authenc \ +kmod-crypto-hmac \ - +kmod-crypto-ecb \ - +kmod-crypto-arc4 + +kmod-crypto-cmac \ + +kmod-crypto-sha1 \ + +kmod-crypto-sha256 \ + +kmod-crypto-sha512 \ + +kmod-crypto-cbc \ + +kmod-crypto-cts KCONFIG:= \ CONFIG_SUNRPC_GSS \ CONFIG_RPCSEC_GSS_KRB5 diff --git a/package/kernel/linux/modules/netfilter.mk b/package/kernel/linux/modules/netfilter.mk index ffacd80a73..6ef1522115 100644 --- a/package/kernel/linux/modules/netfilter.mk +++ b/package/kernel/linux/modules/netfilter.mk @@ -512,7 +512,7 @@ define KernelPackage/nf-ipvs-sip SUBMENU:=$(NF_MENU) TITLE:=Virtual Server SIP protocol support KCONFIG:=CONFIG_IP_VS_PE_SIP - DEPENDS:=kmod-nf-ipvs +kmod-nf-nathelper-extra + DEPENDS:=kmod-nf-ipvs +kmod-nf-nathelper-sip FILES:=$(LINUX_DIR)/net/netfilter/ipvs/ip_vs_pe_sip.ko endef @@ -621,30 +621,194 @@ $(eval $(call KernelPackage,nf-nathelper)) define KernelPackage/nf-nathelper-extra SUBMENU:=$(NF_MENU) TITLE:=Extra Conntrack and NAT helpers - KCONFIG:=$(KCONFIG_NF_NATHELPER_EXTRA) - FILES:=$(foreach mod,$(NF_NATHELPER_EXTRA-m),$(LINUX_DIR)/net/$(mod).ko) - AUTOLOAD:=$(call AutoProbe,$(notdir $(NF_NATHELPER_EXTRA-m))) - DEPENDS:=+kmod-nf-nat +kmod-lib-textsearch +kmod-asn1-decoder + DEPENDS:= \ + +kmod-nf-nathelper-amanda \ + +kmod-nf-nathelper-broadcast \ + +kmod-nf-nathelper-h323 \ + +kmod-nf-nathelper-irc \ + +kmod-nf-nathelper-netbios \ + +kmod-nf-nathelper-pptp \ + +kmod-nf-nathelper-sane \ + +kmod-nf-nathelper-sip \ + +kmod-nf-nathelper-snmp \ + +kmod-nf-nathelper-tftp endef define KernelPackage/nf-nathelper-extra/description - Extra Netfilter (IPv4) Conntrack and NAT helpers - Includes: + Compatibility package providing all extra Netfilter + conntrack and NAT helpers. + This package depends on all individual helper packages: - amanda + - broadcast - h323 - irc - - mms + - netbios - pptp - - proto_gre + - sane - sip - - snmp_basic + - snmp - tftp - - broadcast + Select individual helper packages instead if only a + subset is required. endef $(eval $(call KernelPackage,nf-nathelper-extra)) +define KernelPackage/nf-nathelper-amanda + SUBMENU:=$(NF_MENU) + TITLE:=Amanda conntrack and NAT helper + KCONFIG:= \ + CONFIG_NF_CONNTRACK_AMANDA \ + CONFIG_NF_NAT_AMANDA + FILES:= \ + $(LINUX_DIR)/net/$(P_XT)nf_conntrack_amanda.ko \ + $(LINUX_DIR)/net/$(P_XT)nf_nat_amanda.ko + AUTOLOAD:=$(call AutoProbe,nf_conntrack_amanda nf_nat_amanda) + DEPENDS:=+kmod-nf-nat +kmod-lib-textsearch +endef + +$(eval $(call KernelPackage,nf-nathelper-amanda)) + + +define KernelPackage/nf-nathelper-broadcast + SUBMENU:=$(NF_MENU) + TITLE:=Broadcast conntrack helper + KCONFIG:=CONFIG_NF_CONNTRACK_BROADCAST + FILES:= \ + $(LINUX_DIR)/net/$(P_XT)nf_conntrack_broadcast.ko + AUTOLOAD:=$(call AutoProbe,nf_conntrack_broadcast) + DEPENDS:=+kmod-nf-conntrack +endef + +$(eval $(call KernelPackage,nf-nathelper-broadcast)) + + +define KernelPackage/nf-nathelper-h323 + SUBMENU:=$(NF_MENU) + TITLE:=H.323 conntrack and NAT helper + KCONFIG:= \ + CONFIG_NF_CONNTRACK_H323 \ + CONFIG_NF_NAT_H323 + FILES:= \ + $(LINUX_DIR)/net/$(P_XT)nf_conntrack_h323.ko \ + $(LINUX_DIR)/net/$(P_V4)nf_nat_h323.ko + AUTOLOAD:=$(call AutoProbe,nf_conntrack_h323 nf_nat_h323) + DEPENDS:=+kmod-nf-nat +endef + +$(eval $(call KernelPackage,nf-nathelper-h323)) + + +define KernelPackage/nf-nathelper-irc + SUBMENU:=$(NF_MENU) + TITLE:=IRC conntrack and NAT helper + KCONFIG:= \ + CONFIG_NF_CONNTRACK_IRC \ + CONFIG_NF_NAT_IRC + FILES:= \ + $(LINUX_DIR)/net/$(P_XT)nf_conntrack_irc.ko \ + $(LINUX_DIR)/net/$(P_XT)nf_nat_irc.ko + AUTOLOAD:=$(call AutoProbe,nf_conntrack_irc nf_nat_irc) + DEPENDS:=+kmod-nf-nat +endef + +$(eval $(call KernelPackage,nf-nathelper-irc)) + + +define KernelPackage/nf-nathelper-netbios + SUBMENU:=$(NF_MENU) + TITLE:=NetBIOS NS conntrack helper + KCONFIG:=CONFIG_NF_CONNTRACK_NETBIOS_NS + FILES:= \ + $(LINUX_DIR)/net/$(P_XT)nf_conntrack_netbios_ns.ko + AUTOLOAD:=$(call AutoProbe,nf_conntrack_netbios_ns) + DEPENDS:=+kmod-nf-conntrack +kmod-nf-nathelper-broadcast +endef + +$(eval $(call KernelPackage,nf-nathelper-netbios)) + + +define KernelPackage/nf-nathelper-pptp + SUBMENU:=$(NF_MENU) + TITLE:=PPTP conntrack and NAT helper + KCONFIG:= \ + CONFIG_NF_CONNTRACK_PPTP \ + CONFIG_NF_NAT_PPTP + FILES:= \ + $(LINUX_DIR)/net/$(P_XT)nf_conntrack_pptp.ko \ + $(LINUX_DIR)/net/$(P_V4)nf_nat_pptp.ko + AUTOLOAD:=$(call AutoProbe,nf_conntrack_pptp nf_nat_pptp) + DEPENDS:=+kmod-nf-nat +endef + +$(eval $(call KernelPackage,nf-nathelper-pptp)) + + +define KernelPackage/nf-nathelper-sane + SUBMENU:=$(NF_MENU) + TITLE:=SANE conntrack helper + KCONFIG:=CONFIG_NF_CONNTRACK_SANE + FILES:= \ + $(LINUX_DIR)/net/$(P_XT)nf_conntrack_sane.ko + AUTOLOAD:=$(call AutoProbe,nf_conntrack_sane) + DEPENDS:=+kmod-nf-conntrack +endef + +$(eval $(call KernelPackage,nf-nathelper-sane)) + + +define KernelPackage/nf-nathelper-sip + SUBMENU:=$(NF_MENU) + TITLE:=SIP conntrack and NAT helper + KCONFIG:= \ + CONFIG_NF_CONNTRACK_SIP \ + CONFIG_NF_NAT_SIP + FILES:= \ + $(LINUX_DIR)/net/$(P_XT)nf_conntrack_sip.ko \ + $(LINUX_DIR)/net/$(P_XT)nf_nat_sip.ko + AUTOLOAD:=$(call AutoProbe,nf_conntrack_sip nf_nat_sip) + DEPENDS:=+kmod-nf-nat +endef + +$(eval $(call KernelPackage,nf-nathelper-sip)) + + +define KernelPackage/nf-nathelper-snmp + SUBMENU:=$(NF_MENU) + TITLE:=SNMP conntrack and NAT helper + KCONFIG:= \ + CONFIG_NF_CONNTRACK_SNMP \ + CONFIG_NF_NAT_SNMP_BASIC + FILES:= \ + $(LINUX_DIR)/net/$(P_XT)nf_conntrack_snmp.ko \ + $(LINUX_DIR)/net/$(P_V4)nf_nat_snmp_basic.ko + AUTOLOAD:=$(call AutoProbe,nf_conntrack_snmp nf_nat_snmp_basic) + DEPENDS:= \ + +kmod-asn1-decoder \ + +kmod-nf-nat \ + +kmod-nf-nathelper-broadcast +endef + +$(eval $(call KernelPackage,nf-nathelper-snmp)) + + +define KernelPackage/nf-nathelper-tftp + SUBMENU:=$(NF_MENU) + TITLE:=TFTP conntrack and NAT helper + KCONFIG:= \ + CONFIG_NF_CONNTRACK_TFTP \ + CONFIG_NF_NAT_TFTP + FILES:= \ + $(LINUX_DIR)/net/$(P_XT)nf_conntrack_tftp.ko \ + $(LINUX_DIR)/net/$(P_XT)nf_nat_tftp.ko + AUTOLOAD:=$(call AutoProbe,nf_conntrack_tftp nf_nat_tftp) + DEPENDS:=+kmod-nf-nat +endef + +$(eval $(call KernelPackage,nf-nathelper-tftp)) + + define KernelPackage/ipt-nflog TITLE:=Module for user-space packet logging KCONFIG:=$(KCONFIG_IPT_NFLOG) diff --git a/package/kernel/mac80211/patches/ath9k/600-wifi-ath9k-Clear-DMA-descriptors-without-memset.patch b/package/kernel/mac80211/patches/ath9k/600-wifi-ath9k-Clear-DMA-descriptors-without-memset.patch new file mode 100644 index 0000000000..9c64ae2c03 --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/600-wifi-ath9k-Clear-DMA-descriptors-without-memset.patch @@ -0,0 +1,108 @@ +From 3e14d832e30b10478d2b0945ff2651f6784385a7 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Sat, 16 May 2026 16:43:10 -0700 +Subject: [PATCH] wifi: ath9k: Clear DMA descriptors without memset + +Clear ath9k DMA descriptors with explicit status word stores instead of +memset(). The descriptor rings are coherent DMA memory, which may be +mapped uncached on 32-bit powerpc. The optimized memset() path can use +dcbz there and trigger an alignment warning. + +Use WRITE_ONCE() for the descriptor status words so the compiler keeps +the clears as ordinary stores instead of folding them back into bulk +memset(). This covers AR9003 TX status descriptors as well as the RX +status area cleared when setting up RX descriptors. + +Assisted-by: Codex:GPT-5.5 +Signed-off-by: Rosen Penev +--- + drivers/net/wireless/ath/ath9k/ar9002_mac.c | 15 +++++++++++++- + drivers/net/wireless/ath/ath9k/ar9003_mac.c | 23 +++++++++++++++++---- + 2 files changed, 33 insertions(+), 5 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c ++++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c +@@ -403,6 +403,19 @@ static int ar9002_hw_get_duration(struct + } + } + ++static void ath9k_hw_clear_rxdesc_status(struct ar5416_desc *ads) ++{ ++ WRITE_ONCE(ads->u.rx.status0, 0); ++ WRITE_ONCE(ads->u.rx.status1, 0); ++ WRITE_ONCE(ads->u.rx.status2, 0); ++ WRITE_ONCE(ads->u.rx.status3, 0); ++ WRITE_ONCE(ads->u.rx.status4, 0); ++ WRITE_ONCE(ads->u.rx.status5, 0); ++ WRITE_ONCE(ads->u.rx.status6, 0); ++ WRITE_ONCE(ads->u.rx.status7, 0); ++ WRITE_ONCE(ads->u.rx.status8, 0); ++} ++ + void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, + u32 size, u32 flags) + { +@@ -412,7 +425,7 @@ void ath9k_hw_setuprxdesc(struct ath_hw + if (flags & ATH9K_RXDESC_INTREQ) + ads->ds_ctl1 |= AR_RxIntrReq; + +- memset(&ads->u.rx, 0, sizeof(ads->u.rx)); ++ ath9k_hw_clear_rxdesc_status(ads); + } + EXPORT_SYMBOL(ath9k_hw_setuprxdesc); + +--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c ++++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c +@@ -352,6 +352,19 @@ static bool ar9003_hw_get_isr(struct ath + return true; + } + ++static void ath9k_hw_clear_txstatus(struct ar9003_txs *ads) ++{ ++ WRITE_ONCE(ads->ds_info, 0); ++ WRITE_ONCE(ads->status1, 0); ++ WRITE_ONCE(ads->status2, 0); ++ WRITE_ONCE(ads->status3, 0); ++ WRITE_ONCE(ads->status4, 0); ++ WRITE_ONCE(ads->status5, 0); ++ WRITE_ONCE(ads->status6, 0); ++ WRITE_ONCE(ads->status7, 0); ++ WRITE_ONCE(ads->status8, 0); ++} ++ + static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, + struct ath_tx_status *ts) + { +@@ -370,7 +383,7 @@ static int ar9003_hw_proc_txdesc(struct + (MS(ads->ds_info, AR_TxRxDesc) != 1)) { + ath_dbg(ath9k_hw_common(ah), XMIT, + "Tx Descriptor error %x\n", ads->ds_info); +- memset(ads, 0, sizeof(*ads)); ++ ath9k_hw_clear_txstatus(ads); + return -EIO; + } + +@@ -427,7 +440,7 @@ static int ar9003_hw_proc_txdesc(struct + ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11); + ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12); + +- memset(ads, 0, sizeof(*ads)); ++ ath9k_hw_clear_txstatus(ads); + + return 0; + } +@@ -591,10 +604,12 @@ EXPORT_SYMBOL(ath9k_hw_process_rxdesc_ed + + void ath9k_hw_reset_txstatus_ring(struct ath_hw *ah) + { ++ int i; ++ + ah->ts_tail = 0; + +- memset((void *) ah->ts_ring, 0, +- ah->ts_size * sizeof(struct ar9003_txs)); ++ for (i = 0; i < ah->ts_size; i++) ++ ath9k_hw_clear_txstatus(&ah->ts_ring[i]); + + ath_dbg(ath9k_hw_common(ah), XMIT, + "TS Start 0x%x End 0x%x Virt %p, Size %d\n", diff --git a/package/kernel/mac80211/patches/ath9k/601-wifi-ath9k-remove-TX99-power-array-zero-init.patch b/package/kernel/mac80211/patches/ath9k/601-wifi-ath9k-remove-TX99-power-array-zero-init.patch new file mode 100644 index 0000000000..84c7e67fa9 --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/601-wifi-ath9k-remove-TX99-power-array-zero-init.patch @@ -0,0 +1,34 @@ +From 0da0cfb0840f7fe7df34bde4f787d3435e3db674 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Sat, 16 May 2026 20:28:16 -0700 +Subject: [PATCH] wifi: ath9k: remove TX99 power array zero init + +This array is fully initialized in the loop itself. No need to zero +initialize and then overwrite. + +Remove static from the array. This was a holdover from when the array +was a static global variable. It no longer confers any benefit. + +Also add a min() call to avoid the manual if/ternary operation. + +Assisted-by: Codex:GPT-5.5 +Signed-off-by: Rosen Penev +--- + drivers/net/wireless/ath/ath9k/ar9003_phy.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c +@@ -1737,10 +1737,10 @@ static void ar9003_hw_tx99_stop(struct a + + static void ar9003_hw_tx99_set_txpower(struct ath_hw *ah, u8 txpower) + { +- static u8 p_pwr_array[ar9300RateSize] = { 0 }; ++ u8 p_pwr_array[ar9300RateSize]; + unsigned int i; + +- txpower = txpower <= MAX_RATE_POWER ? txpower : MAX_RATE_POWER; ++ txpower = min(txpower, MAX_RATE_POWER); + for (i = 0; i < ar9300RateSize; i++) + p_pwr_array[i] = txpower; + diff --git a/package/kernel/mt76/Makefile b/package/kernel/mt76/Makefile index a09f64beb4..6200294309 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:=2026-03-21 -PKG_SOURCE_VERSION:=018f60316d4dd6b4e741874eda40e2dfaa29df3b -PKG_MIRROR_HASH:=54a8125453a6fe04c89cf5335bdf0ea16c409361e1e5a79fb339d67cee26df0e +PKG_SOURCE_DATE:=2026-06-23 +PKG_SOURCE_VERSION:=2dd6e4c8892f59b7943ee163afd6ced881bfb31b +PKG_MIRROR_HASH:=9cd490cc08ccbcdd1476edfefd689d01ba5ef43a4a0cc7e23f13ac3a1e1522c5 PKG_MAINTAINER:=Felix Fietkau PKG_USE_NINJA:=0 diff --git a/package/kernel/mt76/patches/002-use-hrtimer_setup-in-mt76x02u-beacon-init.patch b/package/kernel/mt76/patches/002-use-hrtimer_setup-in-mt76x02u-beacon-init.patch deleted file mode 100644 index 705104cc4b..0000000000 --- a/package/kernel/mt76/patches/002-use-hrtimer_setup-in-mt76x02u-beacon-init.patch +++ /dev/null @@ -1,33 +0,0 @@ -From a95e567eb0e06d460dee234f9c845fbfb215ab11 Mon Sep 17 00:00:00 2001 -From: Mieczyslaw Nalewaj -Date: Thu, 29 Jan 2026 16:36:25 +0100 -Subject: [PATCH] wifi: mt76: use hrtimer_setup() in mt76x02u beacon init - -Replace the two-step hrtimer initialization pattern with a single -consolidated call to hrtimer_setup(). -The legacy approach of calling hrtimer_init() followed by manual -assignment to timer.function is deprecated. The new hrtimer_setup() -helper atomically initializes the timer and assigns the callback -function in one operation, eliminating the race-prone intermediate -state where the timer is initialized but lacks a handler. - -Signed-off-by: Mieczyslaw Nalewaj ---- - mt76x02_usb_core.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/mt76x02_usb_core.c b/mt76x02_usb_core.c -index c94c2f661..3a28a8cc1 100644 ---- a/mt76x02_usb_core.c -+++ b/mt76x02_usb_core.c -@@ -264,8 +264,8 @@ void mt76x02u_init_beacon_config(struct mt76x02_dev *dev) - }; - dev->beacon_ops = &beacon_ops; - -- hrtimer_init(&dev->pre_tbtt_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); -- dev->pre_tbtt_timer.function = mt76x02u_pre_tbtt_interrupt; -+ hrtimer_setup(&dev->pre_tbtt_timer, mt76x02u_pre_tbtt_interrupt, CLOCK_MONOTONIC, -+ HRTIMER_MODE_REL); - INIT_WORK(&dev->pre_tbtt_work, mt76x02u_pre_tbtt_work); - - mt76x02_init_beacon_config(dev); diff --git a/package/kernel/mt76/patches/003-pass-LED-define-via-ccflags-y.patch b/package/kernel/mt76/patches/003-pass-LED-define-via-ccflags-y.patch deleted file mode 100644 index 243d4efee8..0000000000 --- a/package/kernel/mt76/patches/003-pass-LED-define-via-ccflags-y.patch +++ /dev/null @@ -1,26 +0,0 @@ -From: Mieczyslaw Nalewaj -Date: Thu, 2 Apr 2026 19:01:10 +0200 -Subject: Subject: [PATCH] mt76: pass LED define via ccflags-y - -Replace the deprecated EXTRA_CFLAGS with ccflags-y so that -the -DCONFIG_MT76_LEDS define is applied correctly by the kernel -build system. EXTRA_CFLAGS is no longer honored by recent -kbuilds[1]; ccflags-y is the supported variable and works -on kernels 6.12 and 6.18. - -1. https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v6.18.20&id=f77bf01425b11947eeb3b5b54685212c302741b8 - -Signed-off-by: Mieczyslaw Nalewaj ---- - Makefile | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/Makefile -+++ b/Makefile -@@ -1,5 +1,5 @@ - # SPDX-License-Identifier: BSD-3-Clause-Clear --EXTRA_CFLAGS += -Werror -DCONFIG_MT76_LEDS -+ccflags-y += -Werror -DCONFIG_MT76_LEDS - obj-m := mt76.o - obj-$(CONFIG_MT76_USB) += mt76-usb.o - obj-$(CONFIG_MT76_SDIO) += mt76-sdio.o diff --git a/package/kernel/mt76/patches/100-wifi-mt76-mt7996-Use-tx_power-from-default-fw-if-EEP.patch b/package/kernel/mt76/patches/100-wifi-mt76-mt7996-Use-tx_power-from-default-fw-if-EEP.patch index 2eb9ab07dc..7ecf57dcbc 100644 --- a/package/kernel/mt76/patches/100-wifi-mt76-mt7996-Use-tx_power-from-default-fw-if-EEP.patch +++ b/package/kernel/mt76/patches/100-wifi-mt76-mt7996-Use-tx_power-from-default-fw-if-EEP.patch @@ -22,7 +22,7 @@ Link: https://github.com/openwrt/mt76/pull/954 --- a/mt7996/eeprom.c +++ b/mt7996/eeprom.c -@@ -93,6 +93,36 @@ mt7996_eeprom_parse_stream(const u8 *eep +@@ -95,6 +95,36 @@ mt7996_eeprom_parse_stream(const u8 *eep } } @@ -59,7 +59,7 @@ Link: https://github.com/openwrt/mt76/pull/954 static bool mt7996_eeprom_variant_valid(struct mt7996_dev *dev, const u8 *def) { #define FEM_INT 0 -@@ -148,6 +178,8 @@ mt7996_eeprom_check_or_use_default(struc +@@ -150,6 +180,8 @@ mt7996_eeprom_check_or_use_default(struc goto out; } diff --git a/package/kernel/rtl8812au-ct/patches/012-fix-mismatched-include-guards.patch b/package/kernel/rtl8812au-ct/patches/012-fix-mismatched-include-guards.patch new file mode 100644 index 0000000000..efcc854c14 --- /dev/null +++ b/package/kernel/rtl8812au-ct/patches/012-fix-mismatched-include-guards.patch @@ -0,0 +1,58 @@ +From 4cfefb927313c389f76adff88f863abefbb040ec Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sat, 27 Jun 2026 00:48:52 +0200 +Subject: [PATCH] Fix mismatched include guards + +GCC 15 enables -Wheader-guard and the kernel module build treats it as +an error, so the mismatched include guards in these headers break the +build: + + include/rtl8812a_sreset.h:20: error: header guard + '_RTL88812A_SRESET_H_' followed by '#define' of a different macro + [-Werror=header-guard] + +Make each '#ifndef' match its '#define'. rtl8192e_sreset.h was a +copy/paste of the rtl8812a guard, so give it its own +'_RTL8192E_SRESET_H_' name instead of duplicating '_RTL8812A_SRESET_H_'. + +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Hauke Mehrtens +--- + include/custom_gpio.h | 2 +- + include/rtl8192e_sreset.h | 4 ++-- + include/rtl8812a_sreset.h | 2 +- + 3 files changed, 4 insertions(+), 4 deletions(-) + +--- a/include/custom_gpio.h ++++ b/include/custom_gpio.h +@@ -1,5 +1,5 @@ + #ifndef __CUSTOM_GPIO_H__ +-#define __CUSTOM_GPIO_H___ ++#define __CUSTOM_GPIO_H__ + + #include + #include +--- a/include/rtl8192e_sreset.h ++++ b/include/rtl8192e_sreset.h +@@ -17,8 +17,8 @@ + * + * + ******************************************************************************/ +-#ifndef _RTL88812A_SRESET_H_ +-#define _RTL8812A_SRESET_H_ ++#ifndef _RTL8192E_SRESET_H_ ++#define _RTL8192E_SRESET_H_ + + #include + +--- a/include/rtl8812a_sreset.h ++++ b/include/rtl8812a_sreset.h +@@ -17,7 +17,7 @@ + * + * + ******************************************************************************/ +-#ifndef _RTL88812A_SRESET_H_ ++#ifndef _RTL8812A_SRESET_H_ + #define _RTL8812A_SRESET_H_ + + #include diff --git a/package/libs/elfutils/Makefile b/package/libs/elfutils/Makefile index 4507a01089..030392b54e 100644 --- a/package/libs/elfutils/Makefile +++ b/package/libs/elfutils/Makefile @@ -7,13 +7,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=elfutils -PKG_VERSION:=0.192 -PKG_RELEASE:=2 +PKG_VERSION:=0.195 +PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 PKG_SOURCE_URL:=https://sourceware.org/$(PKG_NAME)/ftp/$(PKG_VERSION) \ https://mirrors.kernel.org/sourceware/$(PKG_NAME)/$(PKG_VERSION) -PKG_HASH:=616099beae24aba11f9b63d86ca6cc8d566d968b802391334c91df54eab416b4 +PKG_HASH:=37629fdf7f1f3dc2818e138fca2b8094177d6c2d0f701d3bb650a561218dc026 PKG_MAINTAINER:=Luiz Angelo Daros de Luca PKG_LICENSE:=GPL-2.0-or-later LGPL-3.0-or-later diff --git a/package/libs/elfutils/patches/003-libintl-compatibility.patch b/package/libs/elfutils/patches/003-libintl-compatibility.patch index eda9f2204a..655f8f3cfe 100644 --- a/package/libs/elfutils/patches/003-libintl-compatibility.patch +++ b/package/libs/elfutils/patches/003-libintl-compatibility.patch @@ -11,7 +11,7 @@ Requires.private: zlib @LIBZSTD@ --- a/configure.ac +++ b/configure.ac -@@ -728,6 +728,9 @@ dnl AM_GNU_GETTEXT_REQUIRE_VERSION suppo +@@ -788,6 +788,9 @@ dnl AM_GNU_GETTEXT_REQUIRE_VERSION suppo AM_GNU_GETTEXT_VERSION([0.19.6]) AM_GNU_GETTEXT_REQUIRE_VERSION([0.19.6]) diff --git a/package/libs/elfutils/patches/005-build_only_libs.patch b/package/libs/elfutils/patches/005-build_only_libs.patch index 177ac659e6..2d68b3e7a5 100644 --- a/package/libs/elfutils/patches/005-build_only_libs.patch +++ b/package/libs/elfutils/patches/005-build_only_libs.patch @@ -1,11 +1,11 @@ --- a/Makefile.am +++ b/Makefile.am -@@ -27,7 +27,7 @@ AM_MAKEFLAGS = --no-print-directory +@@ -29,7 +29,7 @@ AM_MAKEFLAGS = --no-print-directory pkginclude_HEADERS = version.h - SUBDIRS = config lib libelf libcpu backends libebl libdwelf libdwfl libdw \ -- libasm debuginfod src po doc tests -+ libasm + SUBDIRS = config lib libelf libcpu backends libebl libdwelf libdwfl \ +- libdwfl_stacktrace libdw libasm debuginfod src po doc tests ++ libdwfl_stacktrace libdw libasm EXTRA_DIST = elfutils.spec GPG-KEY NOTES CONTRIBUTING SECURITY \ COPYING COPYING-GPLV2 COPYING-LGPLV3 CONDUCT diff --git a/package/libs/elfutils/patches/006-Fix-build-on-aarch64-musl.patch b/package/libs/elfutils/patches/006-Fix-build-on-aarch64-musl.patch index a7786ed2c0..bd387e7a66 100644 --- a/package/libs/elfutils/patches/006-Fix-build-on-aarch64-musl.patch +++ b/package/libs/elfutils/patches/006-Fix-build-on-aarch64-musl.patch @@ -33,7 +33,7 @@ Signed-off-by: Hongxu Jia # include # include # include -@@ -94,7 +94,7 @@ aarch64_set_initial_registers_tid (pid_t +@@ -115,7 +115,7 @@ aarch64_set_initial_registers_tid (pid_t Dwarf_Word dwarf_fregs[32]; for (int r = 0; r < 32; r++) diff --git a/package/libs/elfutils/patches/007-add-libeu-symbols-to-libelf.patch b/package/libs/elfutils/patches/007-add-libeu-symbols-to-libelf.patch deleted file mode 100644 index 23489b5625..0000000000 --- a/package/libs/elfutils/patches/007-add-libeu-symbols-to-libelf.patch +++ /dev/null @@ -1,31 +0,0 @@ -From f5d6e088f84dd05278c4698a21cbf1ff4569978d Mon Sep 17 00:00:00 2001 -From: Mark Wielaard -Date: Tue, 22 Oct 2024 15:03:42 +0200 -Subject: [PATCH] libelf: Add libeu objects to libelf.a static archive - -libelf might use some symbols from libeu.a, specifically the eu-search -wrappers. But we don't ship libeu.a separately. So include the libeu -objects in the libelf.a archive to facilitate static linking. - - * libelf/Makefile.am (libeu_objects): New variable. - (libelf_a_LIBADD): New, add libeu_objects. - -https://sourceware.org/bugzilla/show_bug.cgi?id=32293 - -Signed-off-by: Mark Wielaard ---- - libelf/Makefile.am | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/libelf/Makefile.am -+++ b/libelf/Makefile.am -@@ -122,6 +122,9 @@ libelf.so: $(srcdir)/libelf.map $(libelf - @$(textrel_check) - $(AM_V_at)ln -fs $@ $@.$(VERSION) - -+libeu_objects = $(shell $(AR) t ../lib/libeu.a) -+libelf_a_LIBADD = $(addprefix ../lib/,$(libeu_objects)) -+ - install: install-am libelf.so - $(mkinstalldirs) $(DESTDIR)$(libdir) - $(INSTALL_PROGRAM) libelf.so $(DESTDIR)$(libdir)/libelf-$(PACKAGE_VERSION).so diff --git a/package/libs/elfutils/patches/008-fix-autoconf-ENABLE_IMA_VERIFICATION.patch b/package/libs/elfutils/patches/008-fix-autoconf-ENABLE_IMA_VERIFICATION.patch deleted file mode 100644 index e5732d2b08..0000000000 --- a/package/libs/elfutils/patches/008-fix-autoconf-ENABLE_IMA_VERIFICATION.patch +++ /dev/null @@ -1,24 +0,0 @@ -From f3c664d069d81a4872a1ec8241ee709f37c53e9c Mon Sep 17 00:00:00 2001 -From: Aaron Merey -Date: Tue, 29 Oct 2024 14:16:57 -0400 -Subject: [PATCH] configure.ac: Fix ENABLE_IMA_VERIFICATION conditional - -Fix test statement for ENABLE_IMA_VERIFICATION always evalutating to -false due to a missing 'x'. - -Signed-off-by: Aaron Merey ---- - configure.ac | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/configure.ac -+++ b/configure.ac -@@ -895,7 +895,7 @@ AS_IF([test "x$enable_debuginfod" != "xn - AM_CONDITIONAL([DEBUGINFOD],[test "x$enable_debuginfod" = "xyes"]) - AS_IF([test "x$enable_debuginfod_ima_verification" = "xyes"],AC_DEFINE([ENABLE_IMA_VERIFICATION],[1],[Build IMA verification])) - AS_IF([test "x$have_libarchive" = "xyes"],AC_DEFINE([HAVE_LIBARCHIVE],[1],[Define to 1 if libarchive is available])) --AM_CONDITIONAL([ENABLE_IMA_VERIFICATION],[test "$enable_debuginfod_ima_verification" = "xyes"]) -+AM_CONDITIONAL([ENABLE_IMA_VERIFICATION],[test "x$enable_debuginfod_ima_verification" = "xyes"]) - AM_CONDITIONAL([OLD_LIBMICROHTTPD],[test "x$old_libmicrohttpd" = "xyes"]) - - dnl for /etc/profile.d/elfutils.{csh,sh} diff --git a/package/libs/elfutils/patches/009-fix-null-dereference-with-lto.patch b/package/libs/elfutils/patches/009-fix-null-dereference-with-lto.patch deleted file mode 100644 index 1179a1e1a0..0000000000 --- a/package/libs/elfutils/patches/009-fix-null-dereference-with-lto.patch +++ /dev/null @@ -1,193 +0,0 @@ -From 8707194a9f2f0b13e53041b03ebfdbdbd2942e43 Mon Sep 17 00:00:00 2001 -From: Mark Wielaard -Date: Tue, 5 Nov 2024 23:31:14 +0100 -Subject: [PATCH 1/1] libelf: Only fetch shdr once in elf_compress[_gnu] - -Some compilers assume the second call to elf[32|64]_getshdr can fail -and produce error: potential null pointer dereference. Just store the -result of the first call and reuse (when not NULL). - - * libelf/elf_compress.c (elf_compress): Store getshdr result in - a shdr union var. - * libelf/elf_compress_gnu.c (): Likewise - -https://sourceware.org/bugzilla/show_bug.cgi?id=32311 - -Signed-off-by: Mark Wielaard ---- - libelf/elf_compress.c | 55 +++++++++++++++++++++------------------ - libelf/elf_compress_gnu.c | 45 ++++++++++++++------------------ - 2 files changed, 48 insertions(+), 52 deletions(-) - ---- a/libelf/elf_compress.c -+++ b/libelf/elf_compress.c -@@ -584,25 +584,30 @@ elf_compress (Elf_Scn *scn, int type, un - Elf64_Xword sh_flags; - Elf64_Word sh_type; - Elf64_Xword sh_addralign; -+ union shdr -+ { -+ Elf32_Shdr *s32; -+ Elf64_Shdr *s64; -+ } shdr; - if (elfclass == ELFCLASS32) - { -- Elf32_Shdr *shdr = elf32_getshdr (scn); -- if (shdr == NULL) -+ shdr.s32 = elf32_getshdr (scn); -+ if (shdr.s32 == NULL) - return -1; - -- sh_flags = shdr->sh_flags; -- sh_type = shdr->sh_type; -- sh_addralign = shdr->sh_addralign; -+ sh_flags = shdr.s32->sh_flags; -+ sh_type = shdr.s32->sh_type; -+ sh_addralign = shdr.s32->sh_addralign; - } - else - { -- Elf64_Shdr *shdr = elf64_getshdr (scn); -- if (shdr == NULL) -+ shdr.s64 = elf64_getshdr (scn); -+ if (shdr.s64 == NULL) - return -1; - -- sh_flags = shdr->sh_flags; -- sh_type = shdr->sh_type; -- sh_addralign = shdr->sh_addralign; -+ sh_flags = shdr.s64->sh_flags; -+ sh_type = shdr.s64->sh_type; -+ sh_addralign = shdr.s64->sh_addralign; - } - - if ((sh_flags & SHF_ALLOC) != 0) -@@ -679,17 +684,17 @@ elf_compress (Elf_Scn *scn, int type, un - correctly and ignored when SHF_COMPRESSED is set. */ - if (elfclass == ELFCLASS32) - { -- Elf32_Shdr *shdr = elf32_getshdr (scn); -- shdr->sh_size = new_size; -- shdr->sh_addralign = __libelf_type_align (ELFCLASS32, ELF_T_CHDR); -- shdr->sh_flags |= SHF_COMPRESSED; -+ shdr.s32->sh_size = new_size; -+ shdr.s32->sh_addralign = __libelf_type_align (ELFCLASS32, -+ ELF_T_CHDR); -+ shdr.s32->sh_flags |= SHF_COMPRESSED; - } - else - { -- Elf64_Shdr *shdr = elf64_getshdr (scn); -- shdr->sh_size = new_size; -- shdr->sh_addralign = __libelf_type_align (ELFCLASS64, ELF_T_CHDR); -- shdr->sh_flags |= SHF_COMPRESSED; -+ shdr.s64->sh_size = new_size; -+ shdr.s64->sh_addralign = __libelf_type_align (ELFCLASS64, -+ ELF_T_CHDR); -+ shdr.s64->sh_flags |= SHF_COMPRESSED; - } - - __libelf_reset_rawdata (scn, out_buf, new_size, 1, ELF_T_CHDR); -@@ -731,17 +736,15 @@ elf_compress (Elf_Scn *scn, int type, un - correctly and ignored when SHF_COMPRESSED is set. */ - if (elfclass == ELFCLASS32) - { -- Elf32_Shdr *shdr = elf32_getshdr (scn); -- shdr->sh_size = scn->zdata_size; -- shdr->sh_addralign = scn->zdata_align; -- shdr->sh_flags &= ~SHF_COMPRESSED; -+ shdr.s32->sh_size = scn->zdata_size; -+ shdr.s32->sh_addralign = scn->zdata_align; -+ shdr.s32->sh_flags &= ~SHF_COMPRESSED; - } - else - { -- Elf64_Shdr *shdr = elf64_getshdr (scn); -- shdr->sh_size = scn->zdata_size; -- shdr->sh_addralign = scn->zdata_align; -- shdr->sh_flags &= ~SHF_COMPRESSED; -+ shdr.s64->sh_size = scn->zdata_size; -+ shdr.s64->sh_addralign = scn->zdata_align; -+ shdr.s64->sh_flags &= ~SHF_COMPRESSED; - } - - __libelf_reset_rawdata (scn, scn->zdata_base, ---- a/libelf/elf_compress_gnu.c -+++ b/libelf/elf_compress_gnu.c -@@ -59,25 +59,30 @@ elf_compress_gnu (Elf_Scn *scn, int infl - Elf64_Xword sh_flags; - Elf64_Word sh_type; - Elf64_Xword sh_addralign; -+ union shdr -+ { -+ Elf32_Shdr *s32; -+ Elf64_Shdr *s64; -+ } shdr; - if (elfclass == ELFCLASS32) - { -- Elf32_Shdr *shdr = elf32_getshdr (scn); -- if (shdr == NULL) -+ shdr.s32 = elf32_getshdr (scn); -+ if (shdr.s32 == NULL) - return -1; - -- sh_flags = shdr->sh_flags; -- sh_type = shdr->sh_type; -- sh_addralign = shdr->sh_addralign; -+ sh_flags = shdr.s32->sh_flags; -+ sh_type = shdr.s32->sh_type; -+ sh_addralign = shdr.s32->sh_addralign; - } - else - { -- Elf64_Shdr *shdr = elf64_getshdr (scn); -- if (shdr == NULL) -+ shdr.s64 = elf64_getshdr (scn); -+ if (shdr.s64 == NULL) - return -1; - -- sh_flags = shdr->sh_flags; -- sh_type = shdr->sh_type; -- sh_addralign = shdr->sh_addralign; -+ sh_flags = shdr.s64->sh_flags; -+ sh_type = shdr.s64->sh_type; -+ sh_addralign = shdr.s64->sh_addralign; - } - - /* Allocated sections, or sections that are already are compressed -@@ -122,15 +127,9 @@ elf_compress_gnu (Elf_Scn *scn, int infl - sh_flags won't have a SHF_COMPRESSED hint in the GNU format. - Just adjust the sh_size. */ - if (elfclass == ELFCLASS32) -- { -- Elf32_Shdr *shdr = elf32_getshdr (scn); -- shdr->sh_size = new_size; -- } -+ shdr.s32->sh_size = new_size; - else -- { -- Elf64_Shdr *shdr = elf64_getshdr (scn); -- shdr->sh_size = new_size; -- } -+ shdr.s64->sh_size = new_size; - - __libelf_reset_rawdata (scn, out_buf, new_size, 1, ELF_T_BYTE); - -@@ -187,15 +186,9 @@ elf_compress_gnu (Elf_Scn *scn, int infl - sh_flags won't have a SHF_COMPRESSED hint in the GNU format. - Just adjust the sh_size. */ - if (elfclass == ELFCLASS32) -- { -- Elf32_Shdr *shdr = elf32_getshdr (scn); -- shdr->sh_size = size; -- } -+ shdr.s32->sh_size = size; - else -- { -- Elf64_Shdr *shdr = elf64_getshdr (scn); -- shdr->sh_size = size; -- } -+ shdr.s64->sh_size = size; - - __libelf_reset_rawdata (scn, buf_out, size, sh_addralign, - __libelf_data_type (&ehdr, sh_type, diff --git a/package/libs/elfutils/patches/101-no-fts.patch b/package/libs/elfutils/patches/101-no-fts.patch index 29a6c4b36c..3483ef203e 100644 --- a/package/libs/elfutils/patches/101-no-fts.patch +++ b/package/libs/elfutils/patches/101-no-fts.patch @@ -72,7 +72,7 @@ struct parse_opt *opt = state->hook; --- a/libdwfl/Makefile.am +++ b/libdwfl/Makefile.am -@@ -50,7 +50,7 @@ libdwfl_a_SOURCES = dwfl_begin.c dwfl_en +@@ -51,7 +51,7 @@ libdwfl_a_SOURCES = dwfl_begin.c dwfl_en argp-std.c find-debuginfo.c \ dwfl_build_id_find_elf.c \ dwfl_build_id_find_debuginfo.c \ diff --git a/package/libs/elfutils/patches/102-fix-potential-deref-of-null-error.patch b/package/libs/elfutils/patches/102-fix-potential-deref-of-null-error.patch deleted file mode 100644 index 6710e4ef9c..0000000000 --- a/package/libs/elfutils/patches/102-fix-potential-deref-of-null-error.patch +++ /dev/null @@ -1,55 +0,0 @@ -strip.c: Pointer `arhdr` created at strip.c:2741 and then dereferenced without NULL-check. -The same situation for the `arhdr` pointer at the objdump.c:313 and -the `h` pointer at the readelf.c:13545. - -Triggers found by static analyzer Svace. - -Signed-off-by: Maks Mishin ---- - src/objdump.c | 5 +++++ - src/readelf.c | 5 +++++ - src/strip.c | 5 +++++ - 3 files changed, 15 insertions(+) - ---- a/src/objdump.c -+++ b/src/objdump.c -@@ -311,6 +311,11 @@ handle_ar (int fd, Elf *elf, const char - { - /* The the header for this element. */ - Elf_Arhdr *arhdr = elf_getarhdr (subelf); -+ if (arhdr == NULL) -+ { -+ printf ("cannot get arhdr: %s\n", elf_errmsg (-1)); -+ exit (1); -+ } - - /* Skip over the index entries. */ - if (strcmp (arhdr->ar_name, "/") != 0 ---- a/src/readelf.c -+++ b/src/readelf.c -@@ -13543,6 +13543,11 @@ dump_archive_index (Elf *elf, const char - as_off, fname, elf_errmsg (-1)); - - const Elf_Arhdr *h = elf_getarhdr (subelf); -+ if (h == NULL) -+ { -+ printf ("cannot get arhdr: %s\n", elf_errmsg (-1)); -+ exit (1); -+ } - - printf (_("Archive member '%s' contains:\n"), h->ar_name); - ---- a/src/strip.c -+++ b/src/strip.c -@@ -2739,6 +2739,11 @@ handle_ar (int fd, Elf *elf, const char - { - /* The the header for this element. */ - Elf_Arhdr *arhdr = elf_getarhdr (subelf); -+ if (arhdr == NULL) -+ { -+ printf ("cannot get arhdr: %s\n", elf_errmsg (-1)); -+ exit (1); -+ } - - if (elf_kind (subelf) == ELF_K_ELF) - result |= handle_elf (fd, subelf, new_prefix, arhdr->ar_name, 0, NULL); diff --git a/package/libs/openssl/Makefile b/package/libs/openssl/Makefile index b7eb5e6c21..daf470bf66 100644 --- a/package/libs/openssl/Makefile +++ b/package/libs/openssl/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=openssl -PKG_VERSION:=3.5.6 +PKG_VERSION:=3.5.7 PKG_RELEASE:=1 PKG_BUILD_FLAGS:=no-mips16 gc-sections no-lto @@ -21,7 +21,7 @@ PKG_SOURCE_URL:= \ https://www.openssl.org/source/old/$(PKG_BASE)/ \ https://github.com/openssl/openssl/releases/download/$(PKG_NAME)-$(PKG_VERSION)/ -PKG_HASH:=deae7c80cba99c4b4f940ecadb3c3338b13cb77418409238e57d7f31f2a3b736 +PKG_HASH:=a8c0d28a529ca480f9f36cf5792e2cd21984552a3c8e4aa11a24aa31aeac98e8 PKG_LICENSE:=Apache-2.0 PKG_LICENSE_FILES:=LICENSE.txt diff --git a/package/libs/openssl/patches/100-Configure-afalg-support.patch b/package/libs/openssl/patches/100-Configure-afalg-support.patch index 0596e36202..3ff962d7a8 100644 --- a/package/libs/openssl/patches/100-Configure-afalg-support.patch +++ b/package/libs/openssl/patches/100-Configure-afalg-support.patch @@ -10,7 +10,7 @@ Signed-off-by: Eneas U de Queiroz --- a/Configure +++ b/Configure -@@ -1811,7 +1811,9 @@ $config{CFLAGS} = [ map { $_ eq '--ossl- +@@ -1816,7 +1816,9 @@ $config{CFLAGS} = [ map { $_ eq '--ossl- unless ($disabled{afalgeng}) { $config{afalgeng}=""; diff --git a/package/libs/openssl/patches/140-allow-prefer-chacha20.patch b/package/libs/openssl/patches/140-allow-prefer-chacha20.patch index beeceef7c5..2a3f476cab 100644 --- a/package/libs/openssl/patches/140-allow-prefer-chacha20.patch +++ b/package/libs/openssl/patches/140-allow-prefer-chacha20.patch @@ -16,7 +16,7 @@ Signed-off-by: Eneas U de Queiroz --- a/ssl/ssl_ciph.c +++ b/ssl/ssl_ciph.c -@@ -1471,11 +1471,29 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_ +@@ -1475,11 +1475,29 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_ ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_DEL, -1, &head, &tail); @@ -46,7 +46,7 @@ Signed-off-by: Eneas U de Queiroz /* * ...and generally, our preferred cipher is AES. -@@ -1530,7 +1548,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_ +@@ -1534,7 +1552,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_ * Within each group, ciphers remain sorted by strength and previous * preference, i.e., * 1) ECDHE > DHE @@ -55,7 +55,7 @@ Signed-off-by: Eneas U de Queiroz * 3) AES > rest * 4) TLS 1.2 > legacy * -@@ -2232,7 +2250,13 @@ const char *OSSL_default_cipher_list(voi +@@ -2236,7 +2254,13 @@ const char *OSSL_default_cipher_list(voi */ const char *OSSL_default_ciphersuites(void) { diff --git a/package/network/config/netifd/Makefile b/package/network/config/netifd/Makefile index 8ef6d3cdb7..748678894c 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:=2026-04-23 -PKG_SOURCE_VERSION:=e45b890fa532bb89380b78008c2cc70bfad2c4c7 -PKG_MIRROR_HASH:=bf318b9905ca2a63a8bb834d356bef3eec031acc843ba0137495708090894f75 +PKG_SOURCE_DATE:=2026-06-16 +PKG_SOURCE_VERSION:=d155e4cefbd964b7c022618c1d74b549de25e8a8 +PKG_MIRROR_HASH:=a9b9cf01e800ac072a353a6c7f7c7854b5b9139b336645b50cc21c5b8ef38390 PKG_MAINTAINER:=Felix Fietkau PKG_LICENSE:=GPL-2.0 diff --git a/package/network/config/netifd/files/lib/netifd/proto/dhcp.sh b/package/network/config/netifd/files/lib/netifd/proto/dhcp.sh index 2214fc0b8d..5765efffaa 100755 --- a/package/network/config/netifd/files/lib/netifd/proto/dhcp.sh +++ b/package/network/config/netifd/files/lib/netifd/proto/dhcp.sh @@ -10,6 +10,7 @@ init_proto "$@" proto_dhcp_init_config() { renew_handler=1 + restart_handler=1 proto_config_add_string 'ipaddr:ipaddr' proto_config_add_string 'hostname:hostname' @@ -27,6 +28,9 @@ proto_dhcp_init_config() { proto_config_add_string mtu6rd proto_config_add_string customroutes proto_config_add_boolean classlessroute + proto_config_add_int timeout + proto_config_add_int retry + proto_config_add_int tryagain } proto_dhcp_add_sendopts() { @@ -54,8 +58,8 @@ proto_dhcp_setup() { local config="$1" local iface="$2" - local ipaddr hostname clientid vendorid broadcast norelease reqopts defaultreqopts iface6rd sendopts delegate zone6rd zone mtu6rd customroutes classlessroute - json_get_vars ipaddr hostname clientid vendorid broadcast norelease reqopts defaultreqopts iface6rd delegate zone6rd zone mtu6rd customroutes classlessroute + local ipaddr hostname clientid vendorid broadcast norelease reqopts defaultreqopts iface6rd sendopts delegate zone6rd zone mtu6rd customroutes classlessroute timeout retry tryagain + json_get_vars ipaddr hostname clientid vendorid broadcast norelease reqopts defaultreqopts iface6rd delegate zone6rd zone mtu6rd customroutes classlessroute timeout retry tryagain local opt dhcpopts for opt in $reqopts; do @@ -101,7 +105,9 @@ proto_dhcp_setup() { proto_run_command "$config" udhcpc \ -p /var/run/udhcpc-$iface.pid \ -s /lib/netifd/dhcp.script \ - -f -t 0 -i "$iface" \ + -f -t "${retry:-0}" -i "$iface" \ + ${timeout:+-T "$timeout"} \ + ${tryagain:+-A "$tryagain"} \ ${ipaddr:+-r ${ipaddr/\/*/}} \ ${hostname:+-x "hostname:$hostname"} \ ${emptyvendorid:+-V ""} \ @@ -115,6 +121,15 @@ proto_dhcp_renew() { [ -n "$sigusr1" ] && proto_kill_command "$interface" $sigusr1 } +proto_dhcp_restart() { + local interface="$1" + # SIGHUP asks a patched udhcpc to release the current lease and + # immediately re-enter INIT_SELECTING so a fresh DHCPDISCOVER goes + # out. Requires the matching busybox udhcpc patch. + local sighup="$(kill -l SIGHUP)" + [ -n "$sighup" ] && proto_kill_command "$interface" $sighup +} + proto_dhcp_teardown() { local interface="$1" proto_kill_command "$interface" diff --git a/package/network/config/wifi-scripts/files-ucode/usr/bin/iwinfo b/package/network/config/wifi-scripts/files-ucode/usr/bin/iwinfo index d36268b06e..8bda0bd15f 100755 --- a/package/network/config/wifi-scripts/files-ucode/usr/bin/iwinfo +++ b/package/network/config/wifi-scripts/files-ucode/usr/bin/iwinfo @@ -95,23 +95,32 @@ function print_scan(cells) { if (cell.vht) { printf('\t VHT Operation:\n'); - printf('\t\tCenter Frequency 1: %d\n', cell.vht.center_chan_1); - printf('\t\tCenter Frequency 2: %s\n', cell.vht.center_chan_2); - printf('\t\tChannel Width: %s\n', cell.vht.chan_width); + if (cell.vht.center_chan_1) + printf('\t\tCenter Frequency 1: %d\n', cell.vht.center_chan_1); + if (cell.vht.center_chan_2) + printf('\t\tCenter Frequency 2: %d\n', cell.vht.center_chan_2); + if (cell.vht.chan_width) + printf('\t\tChannel Width: %s\n', cell.vht.chan_width); } if (cell.he) { printf('\t HE Operation:\n'); - printf('\t\tCenter Frequency 1: %d\n', cell.he.center_chan_1); - printf('\t\tCenter Frequency 2: %s\n', cell.he.center_chan_2); - printf('\t\tChannel Width: %s\n', cell.he.chan_width); + if (cell.he.center_chan_1) + printf('\t\tCenter Frequency 1: %d\n', cell.he.center_chan_1); + if (cell.he.center_chan_2) + printf('\t\tCenter Frequency 2: %d\n', cell.he.center_chan_2); + if (cell.he.chan_width) + printf('\t\tChannel Width: %s\n', cell.he.chan_width); } if (cell.eht) { printf('\t EHT Operation:\n'); - printf('\t\tCenter Frequency 1: %d\n', cell.eht.center_chan_1); - printf('\t\tCenter Frequency 2: %s\n', cell.eht.center_chan_2); - printf('\t\tChannel Width: %s\n', cell.eht.chan_width); + if (cell.eht.center_chan_1) + printf('\t\tCenter Frequency 1: %d\n', cell.eht.center_chan_1); + if (cell.eht.center_chan_2) + printf('\t\tCenter Frequency 2: %d\n', cell.eht.center_chan_2); + if (cell.eht.chan_width) + printf('\t\tChannel Width: %s\n', cell.eht.chan_width); } printf('\n'); diff --git a/package/network/config/wifi-scripts/files-ucode/usr/share/ucode/iwinfo.uc b/package/network/config/wifi-scripts/files-ucode/usr/share/ucode/iwinfo.uc index c56026f104..7519bdda94 100644 --- a/package/network/config/wifi-scripts/files-ucode/usr/share/ucode/iwinfo.uc +++ b/package/network/config/wifi-scripts/files-ucode/usr/share/ucode/iwinfo.uc @@ -370,6 +370,7 @@ export function assoclist(dev) { flags: assoc_flags(station.sta_info.tx_bitrate ?? {}), }, expected_throughput: format_expected_throughput(station.sta_info.expected_throughput ?? 0), + connected_time: station.sta_info.connected_time ?? 0, }; ret[sta.mac] = sta; } @@ -533,22 +534,27 @@ function scan_extension(ext, cell) { switch(ord(ext, 0)) { case 36: - let offset = 7; + cell.he = {}; - if (!(ord(ext, 3) & 0x2)) - break; + if (cell.band == '6') { + let offset = 7; - if (ord(ext, 2) & 0x40) - offset += 3; + if (ord(ext, 2) & 0x40) + offset += 3; - if (ord(ext, 2) & 0x80) - offset += 1; + if (ord(ext, 2) & 0x80) + offset += 1; - cell.he = { - chan_width: eht_chan_width[ord(ext, offset + 1) & 0x3], - center_chan_1: ord(ext, offset + 2), - center_chan_2: ord(ext, offset + 3), - }; + cell.he.chan_width = eht_chan_width[ord(ext, offset + 1) & 0x3]; + cell.he.center_chan_1 = ord(ext, offset + 2); + cell.he.center_chan_2 = ord(ext, offset + 3); + } else if (cell.vht) { + cell.he.chan_width = cell.vht.chan_width; + cell.he.center_chan_1 = cell.vht.center_chan_1; + cell.he.center_chan_2 = cell.vht.center_chan_2; + } else if (cell.ht) { + cell.he.chan_width = cell.ht.chan_width; + } break; case 106: diff --git a/package/network/config/wifi-scripts/files-ucode/usr/share/ucode/wifi/supplicant.uc b/package/network/config/wifi-scripts/files-ucode/usr/share/ucode/wifi/supplicant.uc index 7104357f39..7f0effadd8 100644 --- a/package/network/config/wifi-scripts/files-ucode/usr/share/ucode/wifi/supplicant.uc +++ b/package/network/config/wifi-scripts/files-ucode/usr/share/ucode/wifi/supplicant.uc @@ -155,11 +155,16 @@ function setup_sta(data, config) { if (config.ca_cert_usesystem && fs.stat('/etc/ssl/certs/ca-certificates.crt')) config.ca_cert = '/etc/ssl/certs/ca-certificates.crt'; + const eap_method_map = { fast: 'FAST', peap: 'PEAP', ttls: 'TTLS', tls: 'TLS' }; + if (eap_method_map[config.eap_type]) + config.eap = eap_method_map[config.eap_type]; + switch(config.eap_type) { case 'fast': case 'peap': case 'ttls': set_default(config, 'auth', 'MSCHAPV2'); + config.phase2 = `"auth=${config.auth}"`; if (config.auth == 'EAP-TLS') { if (config.ca_cert2_usesystem && fs.stat('/etc/ssl/certs/ca-certificates.crt')) config.ca_cert2 = '/etc/ssl/certs/ca-certificates.crt'; @@ -205,7 +210,7 @@ function setup_sta(data, config) { 'disable_ht', 'disable_ht40', 'disable_vht', 'vht', 'max_oper_chwidth', 'ht40', 'beacon_int', 'ieee80211w', 'rates', 'mesh_basic_rates', 'mcast_rate', 'altsubject_match', 'domain_match', 'domain_suffix_match', - 'bssid_blacklist', 'bssid_whitelist', 'erp', + 'bssid_blacklist', 'bssid_whitelist', 'erp', 'eap', 'phase2', 'dpp_connector', 'dpp_csign', 'dpp_netaccesskey', ]); } diff --git a/package/network/config/wifi-scripts/files/lib/netifd/wireless-device.uc b/package/network/config/wifi-scripts/files/lib/netifd/wireless-device.uc index 768a421480..f55fc31189 100644 --- a/package/network/config/wifi-scripts/files/lib/netifd/wireless-device.uc +++ b/package/network/config/wifi-scripts/files/lib/netifd/wireless-device.uc @@ -353,7 +353,7 @@ function wdev_update_disabled_vifs(wdev) let name = vif.name; if (enabled == false) - disabled[wdev] = true; + disabled[name] = true; else if (ifindex != cache[name]) changed = true; diff --git a/package/network/ipv6/odhcp6c/Makefile b/package/network/ipv6/odhcp6c/Makefile index 238672b1e1..eddb1858d0 100644 --- a/package/network/ipv6/odhcp6c/Makefile +++ b/package/network/ipv6/odhcp6c/Makefile @@ -12,9 +12,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/odhcp6c.git -PKG_SOURCE_DATE:=2026-06-04 -PKG_SOURCE_VERSION:=daf4ec3054e753c99fdcc3ac5464926548b38351 -PKG_MIRROR_HASH:=a6239fde325f4815d186bde99e30f95877e58b03fa4fab25013a769127ce3369 +PKG_SOURCE_DATE:=2026-06-27 +PKG_SOURCE_VERSION:=10a52220aec9d45803518d8cc4d63e552484ed61 +PKG_MIRROR_HASH:=2194569b6899febaa70070e19b9849737952e2f96edf02d3bd504c6e76160ce4 PKG_MAINTAINER:=Álvaro Fernández Rojas PKG_LICENSE:=GPL-2.0 diff --git a/package/network/ipv6/odhcp6c/files/dhcpv6.sh b/package/network/ipv6/odhcp6c/files/dhcpv6.sh index 6e257e11cb..71777bc4e1 100755 --- a/package/network/ipv6/odhcp6c/files/dhcpv6.sh +++ b/package/network/ipv6/odhcp6c/files/dhcpv6.sh @@ -1,6 +1,7 @@ #!/bin/sh . /lib/functions.sh +. /lib/functions/network.sh . ../netifd-proto.sh . /lib/config/uci.sh init_proto "$@" @@ -9,7 +10,7 @@ proto_dhcpv6_init_config() { renew_handler=1 proto_config_add_string 'reqaddress:or("try","force","none")' - proto_config_add_string 'reqprefix:or("auto","no",range(0, 64))' + proto_config_add_string reqprefix proto_config_add_string clientid proto_config_add_string 'reqopts:list(uinteger)' proto_config_add_string 'defaultreqopts:bool' @@ -85,7 +86,25 @@ proto_dhcpv6_setup() { [ -n "$reqaddress" ] && append opts "-N$reqaddress" [ -z "$reqprefix" -o "$reqprefix" = "auto" ] && reqprefix=0 - [ "$reqprefix" != "no" ] && append opts "-P$reqprefix" + [ "$reqprefix" != "no" ] && { + # append interface IAID if none specified + local iaid=$(echo -n $reqprefix | sed -nr 's/^.*:([0-9A-Fa-f]{1,8})$/\1/p') + [ -z "$iaid" ] && { + network_generate_iface_iaid iaid "$iface" + reqprefix="$reqprefix:$iaid" + } + # validate prefix/length hint + local hint=${reqprefix%:$iaid} + [ "${hint#/}" -le "128" ] 2>/dev/null && { + reqprefix=${reqprefix#/} + } || { + validate_data cidr6 "$hint" 2>/dev/null || { + reqprefix="0:$iaid" + logger -p warn -t dhcpv6 "$iface: ignoring invalid prefix hint" + } + } + append opts "-P$reqprefix" + } [ -n "$clientid" ] && { clientid="$(hexdump_2hex "$clientid")" diff --git a/package/network/ipv6/thc-ipv6/patches/102-fix-thc_open_ipv6-prototype.patch b/package/network/ipv6/thc-ipv6/patches/102-fix-thc_open_ipv6-prototype.patch new file mode 100644 index 0000000000..25446e22a1 --- /dev/null +++ b/package/network/ipv6/thc-ipv6/patches/102-fix-thc_open_ipv6-prototype.patch @@ -0,0 +1,37 @@ +From 0f6e30c03a093bba52f16570635b9f778925f2d7 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sat, 27 Jun 2026 00:34:23 +0200 +Subject: [PATCH] Fix thc_open_ipv6() prototype for GCC 15 / C23 + +GCC 15 defaults to C23, where an empty parameter list "()" means +"(void)" instead of an unspecified argument list. thc-ipv6.h declared + + extern int thc_open_ipv6(); + +so the prototype became "int(void)" and clashed with the actual +definition "int thc_open_ipv6(char *interface)" and all of its callers: + + thc-ipv6-lib.c:127: error: too many arguments to function + 'thc_open_ipv6'; expected 0, have 1 + thc-ipv6-lib.c:2555: error: conflicting types for 'thc_open_ipv6'; + have 'int(char *)' + +Give the prototype its real signature. + +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Hauke Mehrtens +--- + thc-ipv6.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/thc-ipv6.h ++++ b/thc-ipv6.h +@@ -208,7 +208,7 @@ extern int thc_generate_pkt(char *interf + int *pkt_len); + extern int thc_send_pkt(char *interface, unsigned char *pkt, int *pkt_len); + extern unsigned char *thc_destroy_packet(unsigned char *pkt); +-extern int thc_open_ipv6(); ++extern int thc_open_ipv6(char *interface); + extern int thc_is_dst_local(char *interface, unsigned char *dst); + extern int checksum_pseudo_header(unsigned char *src, unsigned char *dst, + unsigned char type, unsigned char *data, diff --git a/package/network/ipv6/thc-ipv6/patches/103-fix-signal-handler-prototypes.patch b/package/network/ipv6/thc-ipv6/patches/103-fix-signal-handler-prototypes.patch new file mode 100644 index 0000000000..e70fbe9298 --- /dev/null +++ b/package/network/ipv6/thc-ipv6/patches/103-fix-signal-handler-prototypes.patch @@ -0,0 +1,55 @@ +From 1e48ae83dddaca892d78025fdd1d3fe6652c8522 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sat, 27 Jun 2026 02:24:41 +0200 +Subject: [PATCH] Fix signal handler prototypes for GCC 15 / C23 + +GCC 15 defaults to C23, where an empty parameter list "()" means +"(void)" instead of an unspecified argument list. The alarming() SIGALRM +handlers in detect_sniffer6.c and thcping6.c were declared with "()", so +their type became "void (*)(void)" and no longer matched the +"void (*)(int)" expected by signal(): + + detect_sniffer6.c:140:19: error: passing argument 2 of 'signal' from + incompatible pointer type [-Wincompatible-pointer-types] + +Give them the proper signal handler signature. Also pass an argument to +the direct alarming() call in detect_sniffer6.c. + +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Hauke Mehrtens +--- + detect_sniffer6.c | 4 ++-- + thcping6.c | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +--- a/detect_sniffer6.c ++++ b/detect_sniffer6.c +@@ -27,7 +27,7 @@ void help(char *prg) { + exit(-1); + } + +-void alarming() { ++void alarming(int sig) { + if (found == 0) + printf("No packets received, no vulnerable system seems to be sniffing.\n"); + else +@@ -63,7 +63,7 @@ void check_packets(u_char *pingdata, con + printf(" Sniffing host detected: %s\n", thc_ipv62notation(ptr + 8)); + memcpy(doubles[found], thc_ipv62notation(ptr + 8), 16); + found++; +- if (oneonly) alarming(); ++ if (oneonly) alarming(0); + } + } + } +--- a/thcping6.c ++++ b/thcping6.c +@@ -89,7 +89,7 @@ void help(char *prg, int help) { + exit(-1); + } + +-void alarming() { ++void alarming(int sig) { + if (done == 0) printf("No packet received, terminating.\n"); + exit(resp_type); + } diff --git a/package/network/services/ead/src/ead.c b/package/network/services/ead/src/ead.c index ad97c543c5..b065b4100a 100644 --- a/package/network/services/ead/src/ead.c +++ b/package/network/services/ead/src/ead.c @@ -428,11 +428,14 @@ handle_send_a(struct ead_packet *pkt, int len, int *nstate) { struct ead_msg *msg = &pkt->msg; struct ead_msg_number *number = EAD_DATA(msg, number); - len = ntohl(msg->len) - sizeof(struct ead_msg_number); + uint32_t msg_len = ntohl(msg->len); - if (len > MAXPARAMLEN + 1) + if (msg_len < sizeof(struct ead_msg_number) || + msg_len - sizeof(struct ead_msg_number) > MAXPARAMLEN + 1) return false; + len = msg_len - sizeof(struct ead_msg_number); + A.len = len; A.data = abuf; memcpy(A.data, number->data, len); diff --git a/package/network/services/ead/src/tinysrp/t_defines.h b/package/network/services/ead/src/tinysrp/t_defines.h index 4128093f60..1a8e4034d1 100644 --- a/package/network/services/ead/src/tinysrp/t_defines.h +++ b/package/network/services/ead/src/tinysrp/t_defines.h @@ -79,19 +79,8 @@ #endif #endif -#if STDC_HEADERS #include #include -#else /* not STDC_HEADERS */ -#ifndef HAVE_STRCHR -#define strchr index -#define strrchr rindex -#endif -char *strchr(), *strrchr(), *strtok(); -#ifndef HAVE_MEMCPY -#define memcpy(d, s, n) bcopy((s), (d), (n)) -#endif -#endif /* not STDC_HEADERS */ #include diff --git a/package/network/services/ead/src/tinysrp/t_truerand.c b/package/network/services/ead/src/tinysrp/t_truerand.c index fa0d6ce603..f46a1e1857 100644 --- a/package/network/services/ead/src/tinysrp/t_truerand.c +++ b/package/network/services/ead/src/tinysrp/t_truerand.c @@ -86,7 +86,7 @@ tick() } static void -interrupt() +interrupt(int sig) { if (count) { #ifdef OLD_TRUERAND diff --git a/package/network/services/hostapd/patches/600-ubus_support.patch b/package/network/services/hostapd/patches/600-ubus_support.patch index 290f2e8e4a..1c7f013c37 100644 --- a/package/network/services/hostapd/patches/600-ubus_support.patch +++ b/package/network/services/hostapd/patches/600-ubus_support.patch @@ -81,15 +81,15 @@ probe/assoc/auth requests via object subscribe. --- a/src/ap/dfs.c +++ b/src/ap/dfs.c -@@ -1295,6 +1295,8 @@ int hostapd_dfs_pre_cac_expired(struct h +@@ -1543,6 +1543,8 @@ int hostapd_dfs_radar_detected(struct ho "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d", freq, ht_enabled, chan_offset, chan_width, cf1, cf2); + hostapd_ubus_notify_radar_detected(iface, freq, chan_width, cf1, cf2); + + iface->radar_detected = true; + /* Proceed only if DFS is not offloaded to the driver */ - if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) - return 0; --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -333,6 +333,10 @@ int hostapd_notif_assoc(struct hostapd_d diff --git a/package/network/services/lldpd/files/lldpd.init b/package/network/services/lldpd/files/lldpd.init index e9891389c2..50063a01bc 100644 --- a/package/network/services/lldpd/files/lldpd.init +++ b/package/network/services/lldpd/files/lldpd.init @@ -123,6 +123,23 @@ get_config_restart_hash() { export -n "$var=$_hash" } +resolve_bridge_member_ports() { + local _lower _bridge _port _ports="" + + _lower=$(ls "/sys/class/net/$1/" 2>/dev/null | grep "^lower_" | head -1) + [ -n "$_lower" ] || return 1 + + _bridge="${_lower#lower_}" + [ -d "/sys/class/net/$_bridge/bridge" ] || return 1 + + for _port in $(ls "/sys/class/net/$_bridge/" 2>/dev/null | grep "^lower_"); do + append _ports "${_port#lower_}" "," + done + + [ -n "$_ports" ] || return 1 + echo "$_ports" +} + get_interface_csv() { local _ifaces config_get _ifaces "$2" "$3" @@ -134,7 +151,15 @@ get_interface_csv() { local _l2device="" if network_get_physdev _l2device "$_iface" || [ -e "/sys/class/net/$_iface" ]; then - append _ifnames "${_l2device:-$_iface}" "," + local _resolved="${_l2device:-$_iface}" + local _ports + # LLDP uses reserved multicast (01:80:c2:00:00:0e) that bridges + # trap rather than forward; trapped frames arrive on the member + # ports, not on bridge VLAN sub-interfaces, so resolve down to + # the individual bridge member ports + _ports=$(resolve_bridge_member_ports "$_resolved") + [ -n "$_ports" ] && _resolved="$_ports" + append _ifnames "$_resolved" "," else # Glob case (interface is e.g. '!eth1' or 'eth*' or '*') append _ifnames "$_iface" "," diff --git a/package/network/services/odhcpd/Makefile b/package/network/services/odhcpd/Makefile index a6340f0966..d2d3759c92 100644 --- a/package/network/services/odhcpd/Makefile +++ b/package/network/services/odhcpd/Makefile @@ -12,9 +12,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/odhcpd.git -PKG_MIRROR_HASH:=f982e7fc12f928359835ccb4b8e650ce935aa67e099bcacded6987d18452ae8d -PKG_SOURCE_DATE:=2026-06-14 -PKG_SOURCE_VERSION:=c6792bac3905d4bf726d914e9994f6d4b98c5b57 +PKG_MIRROR_HASH:=0080feb1757c95b7a844f82728abc6d9c89b792c8170efcb73b04e728c547665 +PKG_SOURCE_DATE:=2026-06-28 +PKG_SOURCE_VERSION:=68f382690bfaec56d5b1f31c3c31c48bcb642e3a PKG_MAINTAINER:=Álvaro Fernández Rojas PKG_LICENSE:=GPL-2.0 diff --git a/package/network/services/uhttpd/Makefile b/package/network/services/uhttpd/Makefile index 61a856a3b8..915baa07ab 100644 --- a/package/network/services/uhttpd/Makefile +++ b/package/network/services/uhttpd/Makefile @@ -9,9 +9,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/uhttpd.git -PKG_SOURCE_DATE:=2026-05-21 -PKG_SOURCE_VERSION:=1b624f8f814ed568608d756512892416e0431d77 -PKG_MIRROR_HASH:=7fb56c4aa2e67a8d6d90e0cbb91f8108a363d0242bb62a8880c41ad4c10ff5ff +PKG_SOURCE_DATE:=2026-06-16 +PKG_SOURCE_VERSION:=7b1bec45826bd78c8afc993435bdc0f1df2fe399 +PKG_MIRROR_HASH:=ee52821b04cc78f46875e9870b6ed41670606d6b90fb31b31312666c4ed809dd PKG_MAINTAINER:=Felix Fietkau PKG_LICENSE:=ISC diff --git a/package/network/services/umdns/Makefile b/package/network/services/umdns/Makefile index 60a56e2469..d317fac304 100644 --- a/package/network/services/umdns/Makefile +++ b/package/network/services/umdns/Makefile @@ -12,9 +12,9 @@ PKG_RELEASE:=1 PKG_SOURCE_URL=$(PROJECT_GIT)/project/mdnsd.git PKG_SOURCE_PROTO:=git -PKG_SOURCE_DATE:=2026-05-22 -PKG_SOURCE_VERSION:=bd7599d021571e785bd32a75469e7148eb1772e3 -PKG_MIRROR_HASH:=0e1942f8aacb730fa7a32642dbf812ed24f4929fe532039d48ace3cba46c040c +PKG_SOURCE_DATE:=2026-06-27 +PKG_SOURCE_VERSION:=dbee55098c2e7a0a76feec414a11d76838572918 +PKG_MIRROR_HASH:=726e7874f7399fd286d81479ff00cb1cdd231cf3a25b8f89e4a9a1c45bb670bc PKG_MAINTAINER:=John Crispin PKG_LICENSE:=LGPL-2.1 diff --git a/package/network/utils/layerscape/restool/Makefile b/package/network/utils/layerscape/restool/Makefile index ac8c5887a2..eecc8d5a0d 100644 --- a/package/network/utils/layerscape/restool/Makefile +++ b/package/network/utils/layerscape/restool/Makefile @@ -8,13 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=restool -PKG_VERSION:=6.6.23.2.0.0 +PKG_VERSION:=6.18.2.1.0.0 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/nxp-qoriq/restool -PKG_SOURCE_VERSION:=lf-6.6.23-2.0.0 -PKG_MIRROR_HASH:=e669c9faf5a00e36d763dbbd6dd866d878b0101df086582c38908d281fa3b465 +PKG_SOURCE_VERSION:=lf-6.18.2-1.0.0 +PKG_MIRROR_HASH:=d3e35b9e8e0db98aa52c0f48fba4b2c9c6e124a0d32e8bf36c208f9dfe3a8dc2 PKG_FLAGS:=nonshared @@ -27,7 +27,7 @@ define Package/restool DEPENDS:=@TARGET_layerscape_armv8_64b endef -MAKE_FLAGS += \ +MAKE_FLAGS += MANPAGE="" \ DESTDIR="$(PKG_BUILD_DIR)"/output/ \ install diff --git a/package/network/utils/layerscape/restool/patches/remove-manpage.patch b/package/network/utils/layerscape/restool/patches/remove-manpage.patch deleted file mode 100644 index ffd73c31fa..0000000000 --- a/package/network/utils/layerscape/restool/patches/remove-manpage.patch +++ /dev/null @@ -1,18 +0,0 @@ ---- a/Makefile -+++ b/Makefile -@@ -55,14 +55,13 @@ restool: $(OBJ) - %.1: %.md - pandoc --standalone --to man $^ -o $@ - --install: restool scripts/ls-main scripts/ls-append-dpl scripts/ls-debug scripts/restool_completion.sh $(MANPAGE) -+install: restool scripts/ls-main scripts/ls-append-dpl scripts/ls-debug scripts/restool_completion.sh - install -D -m 755 restool $(DESTDIR)$(bindir)/restool - install -D -m 755 scripts/ls-main $(DESTDIR)$(bindir)/ls-main - install -D -m 755 scripts/ls-append-dpl $(DESTDIR)$(bindir)/ls-append-dpl - install -D -m 755 scripts/ls-debug $(DESTDIR)$(bindir)/ls-debug - $(foreach symlink, $(RESTOOL_SCRIPT_SYMLINKS), sh -c "cd $(DESTDIR)$(bindir) && ln -sf ls-main $(symlink)" ;) - install -D -m 755 scripts/restool_completion.sh $(DESTDIR)$(bindir_completion)/restool -- install -m 0644 -D $(MANPAGE) $(call get_manpage_destination,$(MANPAGE)) - - clean: - rm -f $(OBJ) $(MANPAGE) \ diff --git a/package/network/utils/nftables/Makefile b/package/network/utils/nftables/Makefile index ff0d04b6c4..6075ebb5af 100644 --- a/package/network/utils/nftables/Makefile +++ b/package/network/utils/nftables/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=nftables PKG_VERSION:=1.1.6 -PKG_RELEASE:=2 +PKG_RELEASE:=4 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=https://netfilter.org/projects/$(PKG_NAME)/files diff --git a/package/network/utils/nftables/patches/000-build-fix-configure-with-non-bash-shell.patch b/package/network/utils/nftables/patches/000-build-fix-configure-with-non-bash-shell.patch new file mode 100644 index 0000000000..03c2d4809b --- /dev/null +++ b/package/network/utils/nftables/patches/000-build-fix-configure-with-non-bash-shell.patch @@ -0,0 +1,29 @@ +From 2e3c68f26d5bd60c8ea7467fa9018c282a7d8c47 Mon Sep 17 00:00:00 2001 +From: Jan Palus +Date: Sat, 6 Dec 2025 00:43:58 +0100 +Subject: build: fix ./configure with non-bash shell + + CONFIG_SHELL=/bin/dash ./configure + +breaks with: + + ./config.status: 2044: Syntax error: Bad for loop variable + +Fixes: 64c07e38f049 ("table: Embed creating nft version into userdata") +Signed-off-by: Jan Palus +Signed-off-by: Pablo Neira Ayuso +--- + configure.ac | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/configure.ac ++++ b/configure.ac +@@ -157,7 +157,7 @@ AC_CONFIG_COMMANDS([nftversion.h], [ + echo " ${STABLE_RELEASE}" + echo "};" + echo "static char nftbuildstamp[[]] = {" +- for ((i = 56; i >= 0; i-= 8)); do ++ for i in `seq 56 -8 0`; do + echo " ((uint64_t)MAKE_STAMP >> $i) & 0xff," + done + echo "};" diff --git a/package/network/utils/nftables/patches/001-build-simplify-the-instantiation-of-nftversion-h.patch b/package/network/utils/nftables/patches/001-build-simplify-the-instantiation-of-nftversion-h.patch index 64ca9b228d..933c0b599a 100644 --- a/package/network/utils/nftables/patches/001-build-simplify-the-instantiation-of-nftversion-h.patch +++ b/package/network/utils/nftables/patches/001-build-simplify-the-instantiation-of-nftversion-h.patch @@ -1,7 +1,7 @@ From 2a0ec8a7246e5c5eb85270e3d4de43e20a00c577 Mon Sep 17 00:00:00 2001 From: Jeremy Sowden Date: Wed, 28 Jan 2026 18:31:05 +0000 -Subject: [PATCH] build: simplify the instantation of nftversion.h +Subject: build: simplify the instantation of nftversion.h Add an nftversion.h.in autoconf input file which configure uses to instantiate nftversion.h in the usual way. @@ -14,11 +14,9 @@ Signed-off-by: Phil Sutter 2 files changed, 22 insertions(+), 16 deletions(-) create mode 100644 nftversion.h.in -diff --git a/configure.ac b/configure.ac -index 6825474..2c61072 100644 --- a/configure.ac +++ b/configure.ac -@@ -147,22 +147,8 @@ AM_CONDITIONAL([BUILD_SERVICE], [test "x$unitdir" != x]) +@@ -147,22 +147,8 @@ AM_CONDITIONAL([BUILD_SERVICE], [test "x AC_ARG_WITH([stable-release], [AS_HELP_STRING([--with-stable-release], [Stable release number])], [], [with_stable_release=0]) @@ -32,7 +30,7 @@ index 6825474..2c61072 100644 - echo " ${STABLE_RELEASE}" - echo "};" - echo "static char nftbuildstamp[[]] = {" -- for ((i = 56; i >= 0; i-= 8)); do +- for i in `seq 56 -8 0`; do - echo " ((uint64_t)MAKE_STAMP >> $i) & 0xff," - done - echo "};" @@ -43,7 +41,7 @@ index 6825474..2c61072 100644 # Current date should be fetched exactly once per build, # so have 'make' call date and pass the value to every 'gcc' call AC_SUBST([MAKE_STAMP], ["\$(shell date +%s)"]) -@@ -175,6 +161,7 @@ AM_CONDITIONAL([BUILD_DISTCHECK], [test "x$enable_distcheck" = "xyes"]) +@@ -175,6 +161,7 @@ AM_CONDITIONAL([BUILD_DISTCHECK], [test AC_CONFIG_FILES([ \ Makefile \ libnftables.pc \ @@ -51,9 +49,6 @@ index 6825474..2c61072 100644 ]) AC_OUTPUT -diff --git a/nftversion.h.in b/nftversion.h.in -new file mode 100644 -index 0000000..6f89771 --- /dev/null +++ b/nftversion.h.in @@ -0,0 +1,19 @@ diff --git a/package/network/utils/nftables/patches/002-build-generate-build-time-stamp-once-at-configure.patch b/package/network/utils/nftables/patches/002-build-generate-build-time-stamp-once-at-configure.patch index eae6a5bc07..82b19b1dbc 100644 --- a/package/network/utils/nftables/patches/002-build-generate-build-time-stamp-once-at-configure.patch +++ b/package/network/utils/nftables/patches/002-build-generate-build-time-stamp-once-at-configure.patch @@ -19,8 +19,6 @@ Signed-off-by: Phil Sutter nftversion.h.in | 18 ++++++++++-------- 3 files changed, 11 insertions(+), 13 deletions(-) -diff --git a/Makefile.am b/Makefile.am -index b134330..ceb2225 100644 --- a/Makefile.am +++ b/Makefile.am @@ -159,8 +159,6 @@ AM_CFLAGS = \ @@ -32,11 +30,9 @@ index b134330..ceb2225 100644 $(NULL) AM_YFLAGS = -d -Wno-yacc -diff --git a/configure.ac b/configure.ac -index 2c61072..9859072 100644 --- a/configure.ac +++ b/configure.ac -@@ -149,9 +149,7 @@ AC_ARG_WITH([stable-release], [AS_HELP_STRING([--with-stable-release], +@@ -149,9 +149,7 @@ AC_ARG_WITH([stable-release], [AS_HELP_S [], [with_stable_release=0]) AC_SUBST([STABLE_RELEASE],[$with_stable_release]) AC_SUBST([NFT_VERSION], [$(echo "${VERSION}" | tr '.' ',')]) @@ -47,8 +43,6 @@ index 2c61072..9859072 100644 AC_ARG_ENABLE([distcheck], AS_HELP_STRING([--enable-distcheck], [Build for distcheck]), -diff --git a/nftversion.h.in b/nftversion.h.in -index 6f89771..325b9dc 100644 --- a/nftversion.h.in +++ b/nftversion.h.in @@ -1,19 +1,21 @@ diff --git a/package/network/utils/nftables/patches/003-build-support-SOURCE_DATE_EPOCH-for-build-time-stamp.patch b/package/network/utils/nftables/patches/003-build-support-SOURCE_DATE_EPOCH-for-build-time-stamp.patch index c37c77b7d2..83b014c7da 100644 --- a/package/network/utils/nftables/patches/003-build-support-SOURCE_DATE_EPOCH-for-build-time-stamp.patch +++ b/package/network/utils/nftables/patches/003-build-support-SOURCE_DATE_EPOCH-for-build-time-stamp.patch @@ -18,11 +18,9 @@ Signed-off-by: Phil Sutter configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) -diff --git a/configure.ac b/configure.ac -index 9859072..0226086 100644 --- a/configure.ac +++ b/configure.ac -@@ -149,7 +149,7 @@ AC_ARG_WITH([stable-release], [AS_HELP_STRING([--with-stable-release], +@@ -149,7 +149,7 @@ AC_ARG_WITH([stable-release], [AS_HELP_S [], [with_stable_release=0]) AC_SUBST([STABLE_RELEASE],[$with_stable_release]) AC_SUBST([NFT_VERSION], [$(echo "${VERSION}" | tr '.' ',')]) diff --git a/package/system/mtd/Makefile b/package/system/mtd/Makefile index d83e3599d8..adc4a3d218 100644 --- a/package/system/mtd/Makefile +++ b/package/system/mtd/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=mtd -PKG_RELEASE:=27 +PKG_RELEASE:=28 PKG_BUILD_DIR := $(KERNEL_BUILD_DIR)/$(PKG_NAME) STAMP_PREPARED := $(STAMP_PREPARED)_$(call confvar,CONFIG_MTD_REDBOOT_PARTS) diff --git a/package/system/procd/Makefile b/package/system/procd/Makefile index de7d5f77e0..1603c89131 100644 --- a/package/system/procd/Makefile +++ b/package/system/procd/Makefile @@ -12,9 +12,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/procd.git -PKG_MIRROR_HASH:=f57f124eb1f6a0a7100cc9327bc4842d3667f611d789fc4b3e8ea4a18f73955f -PKG_SOURCE_DATE:=2026-05-22 -PKG_SOURCE_VERSION:=74bfbee8adb8162ee3f1427905af06836f332a37 +PKG_MIRROR_HASH:=bd9e510b303b58f1edb1bfc4629e523f9a96c80a5b66cf5c972f9245bfec5596 +PKG_SOURCE_DATE:=2026-06-17 +PKG_SOURCE_VERSION:=60fdbf00e924fff0a510c4ec31c520d35e69bfe1 CMAKE_INSTALL:=1 PKG_LICENSE:=GPL-2.0 diff --git a/package/system/ubus/Makefile b/package/system/ubus/Makefile index 936a2984fa..3b31d346ca 100644 --- a/package/system/ubus/Makefile +++ b/package/system/ubus/Makefile @@ -5,9 +5,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/ubus.git -PKG_SOURCE_DATE:=2026-05-23 -PKG_SOURCE_VERSION:=795b32bb96b611493f423666236e9c1e49e0736c -PKG_MIRROR_HASH:=7fdc7c111b21277603448f20b15ebbf3adeab6e3f51fb99f216587f3b5998fbd +PKG_SOURCE_DATE:=2026-06-28 +PKG_SOURCE_VERSION:=24864e7840b3a02a9ef76284a373f6b2f00b8a9b +PKG_MIRROR_HASH:=33072c12e6d9a1fd59e3774f029575df61393b5a465486726609ff59314b8a84 PKG_ABI_VERSION:=$(call abi_version_str,$(PKG_SOURCE_DATE)) CMAKE_INSTALL:=1 diff --git a/package/utils/busybox/Config-defaults.in b/package/utils/busybox/Config-defaults.in index b391441fb5..d2f6b8ef6a 100644 --- a/package/utils/busybox/Config-defaults.in +++ b/package/utils/busybox/Config-defaults.in @@ -867,7 +867,7 @@ config BUSYBOX_DEFAULT_FEATURE_TEST_64 default y config BUSYBOX_DEFAULT_TIMEOUT bool - default n + default y config BUSYBOX_DEFAULT_TOUCH bool default y diff --git a/package/utils/busybox/patches/700-udhcpc-sighup-restart.patch b/package/utils/busybox/patches/700-udhcpc-sighup-restart.patch new file mode 100644 index 0000000000..b58d54b616 --- /dev/null +++ b/package/utils/busybox/patches/700-udhcpc-sighup-restart.patch @@ -0,0 +1,48 @@ +From: John Crispin +Date: Wed, 15 Apr 2026 16:15:38 +0200 +Subject: [PATCH] udhcpc: treat SIGHUP as release + rediscover + +Add a SIGHUP handler to udhcpc that releases the current lease (if any) +and immediately transitions the state machine to INIT_SELECTING so the +next main-loop iteration sends a fresh DHCPDISCOVER. This lets a single +signal express 'release this lease and get a new one' without exiting +the client, so upstream watchdogs (e.g. a DNS-health monitor) can +request a clean re-lease without tearing down the interface. + +Signed-off-by: John Crispin +--- +--- a/networking/udhcp/dhcpc.c ++++ b/networking/udhcp/dhcpc.c +@@ -1606,6 +1606,22 @@ int udhcpc_main(int argc UNUSED_PARAM, c + /* ^^^ switches to LISTEN_NONE */ + timeout = INT_MAX; + continue; ++ case SIGHUP: ++ bb_info_msg("received SIGHUP, restarting DHCP session"); ++ /* release the current lease if we have one */ ++ if (client_data.state != INIT_SELECTING ++ && client_data.state != RELEASED) ++ perform_release(server_id, requested_ip); ++ /* drop any cached offer, kick the state machine into ++ * INIT_SELECTING so the next iteration sends a fresh ++ * DHCPDISCOVER */ ++ change_listen_mode(LISTEN_NONE); ++ server_id = 0; ++ requested_ip = 0; ++ packet_num = 0; ++ client_data.state = INIT_SELECTING; ++ timeout = 0; ++ continue; + case SIGTERM: + bb_info_msg("received %s", "SIGTERM"); + goto ret0; +--- a/networking/udhcp/signalpipe.c ++++ b/networking/udhcp/signalpipe.c +@@ -58,6 +58,7 @@ void FAST_FUNC udhcp_sp_setup(void) + bb_signals(0 + + (1 << SIGUSR1) + + (1 << SIGUSR2) ++ + (1 << SIGHUP) + + (1 << SIGTERM) + , signal_handler); + } diff --git a/package/utils/dtc/Makefile b/package/utils/dtc/Makefile index 9a03662afa..c6db139c23 100644 --- a/package/utils/dtc/Makefile +++ b/package/utils/dtc/Makefile @@ -5,11 +5,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=dtc -PKG_VERSION:=1.7.2 +PKG_VERSION:=1.8.1 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz -PKG_HASH:=f200e5ebd7afd20d4b3804a3085af0870fcf3c194f8d7f0f6985cf8bbb4ac0f4 +PKG_HASH:=454e5cce748ce957c91e7f45e66da2cff5100ddb52155d7a909c43cbeaf1bcb0 PKG_SOURCE_URL:=@KERNEL/software/utils/dtc PKG_MAINTAINER:=Yousong Zhou @@ -93,7 +93,7 @@ MESON_ARGS += \ -Dyaml=disabled \ -Dvalgrind=disabled \ -Dpython=disabled \ - -Dstatic-build=$(if $(CONFIG_DTC_STATIC_BUILD),true,false) + $(if $(CONFIG_DTC_STATIC_BUILD),--prefer-static) define Build/InstallDev $(INSTALL_DIR) $(1)/usr/lib diff --git a/package/utils/fritz-tools/Makefile b/package/utils/fritz-tools/Makefile index b43fe20e9e..4cb196bbfe 100644 --- a/package/utils/fritz-tools/Makefile +++ b/package/utils/fritz-tools/Makefile @@ -1,7 +1,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=fritz-tools -PKG_RELEASE:=3 +PKG_RELEASE:=4 CMAKE_INSTALL:=1 include $(INCLUDE_DIR)/package.mk diff --git a/package/utils/fritz-tools/src/fritz_tffs_nand_read.c b/package/utils/fritz-tools/src/fritz_tffs_nand_read.c index 05179bb423..65d405063e 100644 --- a/package/utils/fritz-tools/src/fritz_tffs_nand_read.c +++ b/package/utils/fritz-tools/src/fritz_tffs_nand_read.c @@ -245,7 +245,7 @@ static int find_entry(uint32_t id, struct tffs_entry *entry) uint32_t new_num_segs = next_seg == 0 ? seg + 1 : next_seg + 1; if (new_num_segs > num_segments) { segments = realloc(segments, new_num_segs * sizeof(struct tffs_entry_segment)); - memset(segments + (num_segments * sizeof(struct tffs_entry_segment)), 0x0, + memset(segments + num_segments, 0x0, (new_num_segs - num_segments) * sizeof(struct tffs_entry_segment)); num_segments = new_num_segs; } diff --git a/package/utils/util-linux/Makefile b/package/utils/util-linux/Makefile index aee0235f21..b7adcd195a 100644 --- a/package/utils/util-linux/Makefile +++ b/package/utils/util-linux/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=util-linux -PKG_VERSION:=2.42.1 +PKG_VERSION:=2.42.2 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=@KERNEL/linux/utils/$(PKG_NAME)/v2.42 -PKG_HASH:=82e9158eb12a9b0b569d84e1687fed9dd18fe89ccd8ef5ac3427218a7c0d7f7f +PKG_HASH:=03a05d3adf9602ef128f2da05b84b3205ce60c351e5737c0370f74000679ce8a PKG_CPE_ID:=cpe:/a:kernel:util-linux PKG_INSTALL:=1 diff --git a/scripts/aruba-header.py b/scripts/aruba-header.py new file mode 100755 index 0000000000..e7dfa62e14 --- /dev/null +++ b/scripts/aruba-header.py @@ -0,0 +1,225 @@ +#!/usr/bin/python3 +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright (C) 2025 Lukas Stockner +# +# ./aruba-header.py +# +# Generates a header for use with the APBoot bootloader on (some?) Aruba APs. + +import argparse + +LEN_BUILD = 256 +LEN_VERSION = 24 +LEN_OEM = 32 + +HEADER_MAGIC = b'ARUBA\0\0\0' + + +class ValidFlag: + YES = 1 + + +class FormatVersion: + CURRENT = 2 + + +class ImageType: + ELF = 0 + FPGA_BINARY = 1 + CPBOOT_BINARY = 2 + APBOOT_BINARY = 3 + TPMINFO = 4 + APBOOT_STAGE1_BINARY = 5 + APBOOT_STAGE2_BINARY = 6 + APBOOT_COMBINED_BINARY = 7 + OS_ANCILLARY_IMAGE = 8 + XLOADER_BINARY = 9 + GRUB_BIN = 10 + LSM_PACKAGE = 11 + + +class CompressionType: + NONE = 0 + BZIP2 = 1 + GZIP = 2 + + +MACHINE_TYPES = { + 'MSWITCH': 0, + 'CABERNET': 1, + 'SYRAH': 2, + 'MERLOT': 3, + 'MUSCAT': 4, + 'NEBBIOLO': 5, + 'MALBEC': 6, + 'PALOMINO': 7, + 'GRENACHE': 8, + 'MOSCATO': 9, + 'TALISKER': 10, + 'JURA_R': 11, + 'SCAPA': 12, + 'JURA_O': 13, + 'CORVINA': 14, + 'ARRAN': 15, + 'BLUEBLOOD': 16, + 'MSR2K': 17, + 'PORFIDIO': 18, + 'CAZULO': 19, + 'SCAPA_H': 20, + 'CARDHU': 21, + 'BOWMORE': 22, + 'TAMDHU': 23, + 'ARDBEG': 24, + 'ARDMORE': 25, + 'DALMORE': 26, + 'K2': 27, + 'GRAPPA': 28, + 'SHUMWAY': 29, + 'SPRINGBANK': 30, + 'OUZO': 31, + 'AMARULA': 32, + 'GROZDOVA': 33, + 'PALINKA': 34, + 'HAZELBURN': 35, + 'TOMATIN': 36, + 'HAZELBURN_H': 37, + 'TOMATIN_16': 38, + 'SPRINGBANK_16': 39, + 'OCTOMORE': 40, + 'BALVENIE': 41, + 'OUZO_PLUS': 42, + 'X4': 43, + 'EINAR': 44, + 'GLENFARCLAS': 45, + 'GLENFIDDICH': 46, + 'EIGER': 47, + 'GLENMORANGIE': 48, + 'MILAGRO': 49, + 'OPUSONE': 50, + 'ABERLOUR': 51, + 'MILLSTONE': 52, + 'DEWARS': 53, + 'BUNKER': 54, + 'MASTERSON': 55, + 'SIERRA': 56, + 'KILCHOMAN': 57, + 'SPEYBURN': 58, + 'LAGAVULIN': 59, + 'LAPHROAIG': 60, + 'TOBA': 61, + 'ARRANTA': 62, +} + + +class NextHeader: + NONE = 0x00000000 + SIGN = 0x01111111 + + +class Flags: + C_TEST_BUILD = 0x00000001 + SWATCH = 0x00000002 + # Preserves the image with "clear all" + DONT_CLEAR_ON_PURGE = 0x00000004 + SECURE_BOOTLOADER = 0x00000008 + FACTORY_IMAGE = 0x00000010 + FIPS_CERTIFIED = 0x00000020 + + +def make_header(data: bytes, build: str, version: str, oem: str, imageType: int, machine: int) -> bytes: + buildBytes = build.encode(encoding='ascii') + assert len(buildBytes) < LEN_BUILD + buildBytes += b'\0' * (LEN_BUILD - len(buildBytes)) + + versionBytes = version.encode(encoding='ascii') + assert len(versionBytes) < LEN_VERSION + versionBytes += b'\0' * (LEN_VERSION - len(versionBytes)) + + oemBytes = oem.encode(encoding='ascii') + assert len(oemBytes) < LEN_OEM + oemBytes += b'\0' * (LEN_OEM - len(oemBytes)) + + header = b'' + # Payload size, image plus optional signature (which we don't use) + header += len(data).to_bytes(4, 'big') + # Use what appears to be the current version + header += FormatVersion.CURRENT.to_bytes(4, 'big') + # Checksum is computed later + header += b'\0\0\0\0' + # Vendor magic number + header += HEADER_MAGIC + # Long build information string + header += buildBytes + # Short version information string + header += versionBytes + # Image is valid + header += ValidFlag.YES.to_bytes(1, 'big') + # Image type + header += imageType.to_bytes(1, 'big') + # APBoot doesn't appear to actually support compression + header += CompressionType.NONE.to_bytes(1, 'big') + # Machine type + header += machine.to_bytes(1, 'big') + # Image size + header += len(data).to_bytes(4, 'big') + # Next header (we don't support signing) + header += NextHeader.NONE.to_bytes(4, 'big') + # MD5 checksum plus fudge factor (to ensure non-zero hash), appears unused + header += b'\0' * 16 + header += b'\0' * 4 + # No flags are set + header += int(0).to_bytes(4, 'big') + # No next header is used + header += b'\0' * 12 + # Padding + header += b'\0' * 36 + # OEM string + header += oemBytes + # Padding + header += b'\0' * 96 + + assert len(header) == 512 + assert len(data) % 4 == 0 + + # Compute checksum such that the big-endian sum of all 32-bit integers becomes zero. + curSum = sum(int.from_bytes(header[i : i + 4], 'big') for i in range(0, 512, 4)) + curSum += sum(int.from_bytes(data[i : i + 4], 'big') for i in range(0, len(data), 4)) + + # Set checksum + checksum = 0x100000000 - (curSum % 0x100000000) + header = header[:8] + checksum.to_bytes(4, 'big') + header[12:] + + return header + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Generate Aruba header.') + parser.add_argument('source') + parser.add_argument('dest') + parser.add_argument('build') + parser.add_argument('version') + parser.add_argument('oem') + parser.add_argument('type', choices=['os', 'boot']) + parser.add_argument('machine', choices=MACHINE_TYPES.keys(), type=str.upper) + args = parser.parse_args() + + # Parse image type. + # The OS image must be type "ELF" even though it's not an ELF file... + imageType = {'os': ImageType.ELF, 'boot': ImageType.APBOOT_BINARY}[args.type] + # Parse machine type. + machineType = MACHINE_TYPES[args.machine] + + source = open(args.source, 'rb') + image = source.read() + # Pad image. + if len(image) % 4 != 0: + image += b'\0' * (4 - len(image) % 4) + + # Generate header. + header = make_header(image, args.build, args.version, args.oem, imageType, machineType) + + # Write output. + dest = open(args.dest, 'wb') + dest.write(header) + dest.write(image) diff --git a/target/linux/airoha/an7581/base-files/etc/board.d/02_network b/target/linux/airoha/an7581/base-files/etc/board.d/02_network index 267873f022..107ca37046 100644 --- a/target/linux/airoha/an7581/base-files/etc/board.d/02_network +++ b/target/linux/airoha/an7581/base-files/etc/board.d/02_network @@ -20,6 +20,10 @@ an7581_setup_interfaces() nokia,valyrian) ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 10g" "wan" ;; + nokia,xg-040g-md |\ + nokia,xg-040g-md-ubi) + ucidef_set_interface_lan "lan1 lan2 lan3 lan4" + ;; *) echo "Unsupported hardware. Network interfaces not initialized" ;; diff --git a/target/linux/airoha/an7581/base-files/etc/init.d/airoha_fan b/target/linux/airoha/an7581/base-files/etc/init.d/airoha_fan index d30205f546..b9d5633bd1 100755 --- a/target/linux/airoha/an7581/base-files/etc/init.d/airoha_fan +++ b/target/linux/airoha/an7581/base-files/etc/init.d/airoha_fan @@ -5,7 +5,7 @@ START=99 -. /lib/functions.sh +. "$IPKG_INSTROOT/lib/functions.sh" find_nct7802() { diff --git a/target/linux/airoha/an7581/base-files/lib/upgrade/platform.sh b/target/linux/airoha/an7581/base-files/lib/upgrade/platform.sh index 767f499faa..8584b84e0c 100644 --- a/target/linux/airoha/an7581/base-files/lib/upgrade/platform.sh +++ b/target/linux/airoha/an7581/base-files/lib/upgrade/platform.sh @@ -1,11 +1,39 @@ -REQUIRE_IMAGE_METADATA=1 RAMFS_COPY_BIN='fitblk fit_check_sign' +REQUIRE_IMAGE_METADATA=1 + +nokia_initial_setup() +{ + [ "$(rootfs_type)" = "tmpfs" ] || return 0 + + fw_setenv bootcmd "flash read 0xc0000 0x800000 0x85000000; bootm 0x85000000" +} + +platform_check_image() { + local board=$(board_name) + + [ "$#" -gt 1 ] && return 1 + + case "$board" in + nokia,xg-040g-md) + nand_do_platform_check "$board" "$1" + return $? + ;; + nokia,xg-040g-md-ubi) + fit_check_image "$1" + return $? + ;; + esac + + return 0 +} + platform_do_upgrade() { local board=$(board_name) case "$board" in - gemtek,w1700k-ubi) + gemtek,w1700k-ubi|\ + nokia,xg-040g-md-ubi) fit_do_upgrade "$1" ;; *) @@ -14,6 +42,14 @@ platform_do_upgrade() { esac } -platform_check_image() { - return 0 +platform_pre_upgrade() { + local board=$(board_name) + + case "$board" in + nokia,xg-040g-md) + nokia_initial_setup + ;; + *) + ;; + esac } diff --git a/target/linux/airoha/an7581/config-6.18 b/target/linux/airoha/an7581/config-6.18 index b08771357f..59f7325212 100644 --- a/target/linux/airoha/an7581/config-6.18 +++ b/target/linux/airoha/an7581/config-6.18 @@ -212,6 +212,7 @@ CONFIG_MTD_UBI_BEB_LIMIT=20 CONFIG_MTD_UBI_BLOCK=y CONFIG_MTD_UBI_NVMEM=y CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTD_VIRT_CONCAT=y CONFIG_MTK_NET_PHYLIB=y CONFIG_MUTEX_SPIN_ON_OWNER=y CONFIG_NEED_DMA_MAP_STATE=y diff --git a/target/linux/airoha/dts/an7581-nokia_xg-040g-md-common.dtsi b/target/linux/airoha/dts/an7581-nokia_xg-040g-md-common.dtsi new file mode 100644 index 0000000000..aecddc73da --- /dev/null +++ b/target/linux/airoha/dts/an7581-nokia_xg-040g-md-common.dtsi @@ -0,0 +1,350 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT + +/dts-v1/; +#include +#include +#include +#include "an7581.dtsi" + +/ { + aliases { + label-mac-device = &gdm1; + + led-boot = &led_power_green; + led-failsafe = &led_power_green; + led-running = &led_power_green; + led-upgrade = &led_power_green; + + serial0 = &uart1; + }; + + chosen { + bootargs = "console=ttyS0,115200 earlycon"; + stdout-path = "serial0:115200n8"; + linux,usable-memory-range = + <0x0 0x80200000 0x0 0x1fe00000>; + }; + + gpio-keys { + compatible = "gpio-keys"; + + button-0 { + label = "reset"; + linux,code = ; + gpios = <&en7581_pinctrl 0 GPIO_ACTIVE_LOW>; + debounce-interval = <60>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_power_green: led-0 { + color = ; + function = LED_FUNCTION_POWER; + gpios = <&en7581_pinctrl 17 GPIO_ACTIVE_LOW>; + panic-indicator; + }; + + led-1 { + color = ; + function = LED_FUNCTION_WAN; + gpios = <&en7581_pinctrl 18 GPIO_ACTIVE_LOW>; + }; + + led-2 { + color = ; + function = LED_FUNCTION_WAN; + gpios = <&en7581_pinctrl 19 GPIO_ACTIVE_LOW>; + }; + + led-3 { + color = ; + function = LED_FUNCTION_WAN_ONLINE; + gpios = <&en7581_pinctrl 20 GPIO_ACTIVE_LOW>; + }; + + led-4 { + color = ; + function = LED_FUNCTION_USB; + function-enumerator = <2>; + gpios = <&en7581_pinctrl 34 GPIO_ACTIVE_LOW>; + linux,default-trigger = "usbport"; + trigger-sources = <&usb_port2>; + }; + + led-5 { + color = ; + function = LED_FUNCTION_USB; + function-enumerator = <1>; + gpios = <&en7581_pinctrl 35 GPIO_ACTIVE_LOW>; + linux,default-trigger = "usbport"; + trigger-sources = <&usb_port1>; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x0 0x80000000 0x0 0x20000000>; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "fixed-3.3V"; + }; + + reg_usb_5v: regulator-usb-5v { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&en7581_pinctrl 24 GPIO_ACTIVE_HIGH>; + regulator-boot-on; + regulator-max-microvolt = <5000000>; + regulator-min-microvolt = <5000000>; + regulator-name = "usb-5v"; + }; + + /* + * Controls both USB ports at once + */ + usb-power { + compatible = "regulator-output"; + vout-supply = <®_usb_5v>; + }; +}; + +&en7581_pinctrl { + gpio-ranges = <&en7581_pinctrl 0 13 47>; + + mdio_pins: mdio-pins { + mux { + function = "mdio"; + groups = "mdio"; + }; + + conf { + pins = "gpio2"; + output-high; + }; + }; + + gswp2_led0_pins: gswp2-led0-pins { + mux { + function = "phy2_led0"; + pins = "gpio44"; + }; + }; + + gswp3_led0_pins: gswp3-led0-pins { + mux { + function = "phy3_led0"; + pins = "gpio45"; + }; + }; + + gswp4_led0_pins: gswp4-led0-pins { + mux { + function = "phy4_led0"; + pins = "gpio46"; + }; + }; +}; + +ð { + status = "okay"; +}; + +ð_pcs { + status = "okay"; +}; + +&i2c0 { + status = "okay"; +}; + +&mdio { + /* Airoha EN8811 2.5Gbps phy */ + en8811: ethernet-phy@f { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <0xf>; + + reset-gpios = <&en7581_pinctrl 31 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <20000>; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + led-0 { + reg = <0>; + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <1>; + default-state = "keep"; + }; + }; + }; +}; + +&npu { + status = "okay"; +}; + +&pon_pcs { + status = "okay"; +}; + +&snfi { + status = "okay"; +}; + +/* + * SkyHigh ML02G300WHI00 + */ +&spi_nand { + /* + * ECC must be aligned with bootloader to prevent read errors. + * Stock fw also uses NAND_ECC_NONE. + */ + nand-ecc-mode = "none"; + nand-ecc-step-size = <2048>; + nand-ecc-strength = <0>; + + partitions: partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + }; +}; + +&gdm1 { + status = "okay"; + + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_factory_3e (0)>; +}; + +&switch { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; +}; + +&gsw_port2 { + status = "okay"; + + label = "lan2"; +}; + +&gsw_phy2 { + status = "okay"; + + interrupts = <2>; + + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gswp2_led0_pins>; +}; + +&gsw_phy2_led0 { + status = "okay"; + + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <2>; + active-low; +}; + +&gsw_port3 { + status = "okay"; + + label = "lan3"; +}; + +&gsw_phy3 { + status = "okay"; + + interrupts = <3>; + + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gswp3_led0_pins>; +}; + +&gsw_phy3_led0 { + status = "okay"; + + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <3>; + active-low; +}; + +&gsw_port4 { + status = "okay"; + + label = "lan4"; +}; + +&gsw_phy4 { + status = "okay"; + + interrupts = <4>; + + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gswp4_led0_pins>; +}; + +&gsw_phy4_led0 { + status = "okay"; + + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <4>; + active-low; +}; + +&gdm4 { + status = "okay"; + + openwrt,netdev-name = "lan1"; + + phy-handle = <&en8811>; + phy-mode = "2500base-x"; + + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_factory_3e (0)>; +}; + +&usb0 { + status = "okay"; + + vusb33-supply = <®_3p3v>; + + #address-cells = <1>; + #size-cells = <0>; + + usb_port1: port@1 { + reg = <1>; + #trigger-source-cells = <0>; + }; +}; + +&usb1 { + status = "okay"; + + mediatek,u3p-dis-msk = <0x1>; + phys = <&usb1_phy PHY_TYPE_USB2>; + vusb33-supply = <®_3p3v>; + + #address-cells = <1>; + #size-cells = <0>; + + usb_port2: port@1 { + reg = <1>; + #trigger-source-cells = <0>; + }; +}; diff --git a/target/linux/airoha/dts/an7581-nokia_xg-040g-md-ubi.dts b/target/linux/airoha/dts/an7581-nokia_xg-040g-md-ubi.dts new file mode 100644 index 0000000000..b61f613e7a --- /dev/null +++ b/target/linux/airoha/dts/an7581-nokia_xg-040g-md-ubi.dts @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT + +#include "an7581-nokia_xg-040g-md-common.dtsi" + +/ { + model = "Nokia XG-040G-MD (UBI)"; + compatible = "nokia,xg-040g-md-ubi", "airoha,an7581", + "airoha,en7581"; + + chosen { + rootdisk = <&ubi_fit>; + }; +}; + +&partitions { + partition@0_all { + label = "all_flash"; + reg = <0x0 0x10000000>; + read-only; + }; + + partition@0 { + label = "bl2"; + reg = <0x0 0x20000>; + read-only; + }; + + partition@20000 { + label = "ubi"; + reg = <0x20000 0xffe0000>; + compatible = "linux,ubi"; + + volumes { + ubi-volume-bosa { + volname = "bosa"; + }; + + ubi-volume-factory { + volname = "ri"; + + nvmem-layout { + compatible = "fixed-layout"; + + #address-cells = <1>; + #size-cells = <1>; + + macaddr_factory_3e: macaddr@3e { + compatible = "mac-base"; + reg = <0x3e 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + + ubi_fit: ubi-volume-fit { + volname = "fit"; + }; + + ubi-volume-fip { + volname = "fip"; + }; + + ubi_env: ubi-volume-ubootenv { + volname = "ubootenv"; + }; + + ubi_env2: ubi-volume-ubootenv2 { + volname = "ubootenv2"; + }; + }; + }; +}; + +&ubi_env { + nvmem-layout { + compatible = "u-boot,env-redundant-bool-layout"; + }; +}; + +&ubi_env2 { + nvmem-layout { + compatible = "u-boot,env-redundant-bool-layout"; + }; +}; diff --git a/target/linux/airoha/dts/an7581-nokia_xg-040g-md.dts b/target/linux/airoha/dts/an7581-nokia_xg-040g-md.dts new file mode 100644 index 0000000000..5676c78ab6 --- /dev/null +++ b/target/linux/airoha/dts/an7581-nokia_xg-040g-md.dts @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT + +#include "an7581-nokia_xg-040g-md-common.dtsi" + +/ { + model = "Nokia XG-040G-MD"; + compatible = "nokia,xg-040g-md", "airoha,an7581", "airoha,en7581"; + + virtual_flash { + compatible = "mtd-concat"; + devices = <&ubi4 &ubi1 &ubi2 &ubi3 &ubi5 &ubi6>; + + partitions { + compatible = "fixed-partitions"; + + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "ubi"; + reg = <0x0 0x0>; + }; + }; + }; +}; + +&partitions { + partition@0_all { + label = "all_flash"; + reg = <0x0 0xeba0000>; + read-only; + }; + + partition@0 { + label = "bootloader"; + reg = <0x0 0x80000>; + read-only; + }; + + partition@60000 { + label = "u-boot-env"; + reg = <0x60000 0x20000>; + }; + + partition@80000 { + label = "romfile"; + reg = <0x80000 0x40000>; + read-only; + }; + + partition@c0000 { + label = "nsb_1"; + reg = <0xc0000 0x2880000>; + + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "kernel"; + reg = <0x0 0x800000>; + }; + + ubi1: partition@800000 { + label = "rootfs_1"; + reg = <0x800000 0x2080000>; + }; + }; + + ubi2: partition@2940000 { + label = "nsb_2"; + reg = <0x2940000 0x2880000>; + }; + + partition@51c0000 { + label = "bosa"; + reg = <0x51c0000 0x40000>; + read-only; + }; + + partition@5200000 { + label = "ri"; + reg = <0x5200000 0x40000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + + #address-cells = <1>; + #size-cells = <1>; + + macaddr_factory_3e: macaddr@3e { + compatible = "mac-base"; + reg = <0x3e 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + + partition@5240000 { + label = "flag"; + reg = <0x5240000 0x40000>; + read-only; + }; + + partition@5280000 { + label = "flagback"; + reg = <0x5280000 0x40000>; + read-only; + }; + + ubi3: partition@52c0000 { + label = "config"; + reg = <0x52c0000 0xa00000>; + }; + + ubi4: partition@5cc0000 { + label = "data"; + reg = <0x5cc0000 0x80e0000>; + }; + + ubi5: partition@dda0000 { + label = "oopsfs"; + reg = <0xdda0000 0x400000>; + }; + + partition@e1a0000 { + label = "log"; + reg = <0xe1a0000 0xa00000>; + + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + ubi6: partition@0 { + label = "log_truncated"; + reg = <0x0 0x9c0000>; + }; + + /* + * Must be excluded from ubi. Otherwise the data + * will be broken after U-Boot 'bootflag swap' + * command call. This command writes bootflag at + * 0xeb60000 (boot_flag_addr). + */ + partition@9c0000 { + label = "bootflag"; + reg = <0x9c0000 0x40000>; + read-only; + }; + }; +}; diff --git a/target/linux/airoha/dts/an7581-w1700k-ubi.dts b/target/linux/airoha/dts/an7581-w1700k-ubi.dts index 4aa281c79d..d306f8f8e6 100644 --- a/target/linux/airoha/dts/an7581-w1700k-ubi.dts +++ b/target/linux/airoha/dts/an7581-w1700k-ubi.dts @@ -123,25 +123,6 @@ }; }; - /* W1700K does not use the built-in LED controller. Instead, it uses GPIO. - * The driver fails to probe without gswpX_led0_pins defined, so put a dummy - * here. - */ - - gswp1_led0_pins: gswp1-led0-pins { - mux { - function = "phy1_led0"; - pins = "gpio33"; - }; - }; - - gswp2_led0_pins: gswp2-led0-pins { - mux { - function = "phy2_led0"; - pins = "gpio34"; - }; - }; - uart2_pins: uart2-pins { mux { function = "uart"; @@ -387,8 +368,6 @@ &gsw_phy1 { status = "okay"; interrupts = <1>; - pinctrl-names = "gbe-led"; - pinctrl-0 = <&gswp1_led0_pins>; }; &gsw_port1 { @@ -399,8 +378,6 @@ &gsw_phy2 { status = "okay"; interrupts = <2>; - pinctrl-names = "gbe-led"; - pinctrl-0 = <&gswp2_led0_pins>; }; &gsw_port2 { diff --git a/target/linux/airoha/dts/an7581.dtsi b/target/linux/airoha/dts/an7581.dtsi index efbb4ca54e..e7bfd69165 100644 --- a/target/linux/airoha/dts/an7581.dtsi +++ b/target/linux/airoha/dts/an7581.dtsi @@ -632,14 +632,14 @@ #phy-cells = <1>; }; - crypto@1e004000 { + crypto@1fb70000 { compatible = "inside-secure,safexcel-eip93ies"; reg = <0x0 0x1fb70000 0x0 0x1000>; interrupts = ; }; - thermal: thermal-sensor@1efbd800 { + thermal: thermal-sensor@1efbd000 { compatible = "airoha,en7581-thermal"; reg = <0x0 0x1efbd000 0x0 0xd5c>; interrupts = ; diff --git a/target/linux/airoha/dts/an7583.dtsi b/target/linux/airoha/dts/an7583.dtsi index 743eeb7cec..33ac571ca3 100644 --- a/target/linux/airoha/dts/an7583.dtsi +++ b/target/linux/airoha/dts/an7583.dtsi @@ -539,7 +539,7 @@ status = "disabled"; }; - crypto@1e004000 { + crypto@1fb70000 { compatible = "inside-secure,safexcel-eip93ies"; reg = <0x0 0x1fb70000 0x0 0x1000>; @@ -751,7 +751,7 @@ #address-cells = <1>; #size-cells = <0>; - gsw_phy1: ethernet-phy@1 { + gsw_phy1: ethernet-phy@9 { compatible = "ethernet-phy-ieee802.3-c22"; reg = <9>; phy-mode = "internal"; @@ -774,7 +774,7 @@ }; }; - gsw_phy2: ethernet-phy@2 { + gsw_phy2: ethernet-phy@a { compatible = "ethernet-phy-ieee802.3-c22"; reg = <10>; phy-mode = "internal"; @@ -797,7 +797,7 @@ }; }; - gsw_phy3: ethernet-phy@3 { + gsw_phy3: ethernet-phy@b { compatible = "ethernet-phy-ieee802.3-c22"; reg = <11>; phy-mode = "internal"; @@ -820,7 +820,7 @@ }; }; - gsw_phy4: ethernet-phy@4 { + gsw_phy4: ethernet-phy@c { compatible = "ethernet-phy-ieee802.3-c22"; reg = <12>; phy-mode = "internal"; diff --git a/target/linux/airoha/en7523/config-6.18 b/target/linux/airoha/en7523/config-6.18 index eefe1353a4..3e60f19b7c 100644 --- a/target/linux/airoha/en7523/config-6.18 +++ b/target/linux/airoha/en7523/config-6.18 @@ -221,8 +221,8 @@ CONFIG_OLD_SIGSUSPEND3=y CONFIG_OUTER_CACHE=y CONFIG_OUTER_CACHE_SYNC=y CONFIG_PADATA=y -CONFIG_PAGE_OFFSET=0xC0000000 CONFIG_PAGE_BLOCK_MAX_ORDER=10 +CONFIG_PAGE_OFFSET=0xC0000000 CONFIG_PAGE_POOL=y CONFIG_PAGE_SIZE_LESS_THAN_256KB=y CONFIG_PAGE_SIZE_LESS_THAN_64KB=y diff --git a/target/linux/airoha/image/an7581.mk b/target/linux/airoha/image/an7581.mk index bf7fcd97dc..cdadfb78aa 100644 --- a/target/linux/airoha/image/an7581.mk +++ b/target/linux/airoha/image/an7581.mk @@ -134,3 +134,49 @@ define Device/nokia_valyrian ARTIFACTS := preloader.bin bl31-uboot.fip endef TARGET_DEVICES += nokia_valyrian + +define Device/nokia_xg-040g-md-common + $(call Device/FitImageLzma) + DEVICE_VENDOR := Nokia + DEVICE_MODEL := XG-040G-MD + BLOCKSIZE := 128k + PAGESIZE := 2048 + UBINIZE_OPTS := -E 5 + DEVICE_PACKAGES := kmod-gpio-button-hotplug kmod-leds-gpio \ + kmod-phy-airoha-en8811h kmod-regulator-userspace-consumer \ + kmod-usb-ledtrig-usbport kmod-usb3 +endef + +define Device/nokia_xg-040g-md + $(call Device/nokia_xg-040g-md-common) + DEVICE_DTS := an7581-nokia_xg-040g-md + DEVICE_DTS_CONFIG := config@1 + IMAGE_SIZE := 131968k + KERNEL_SIZE := 8192k + IMAGES += factory-kernel.bin factory-rootfs.bin + IMAGE/factory-kernel.bin := append-kernel + IMAGE/factory-rootfs.bin := append-ubi | check-size + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata +endef +TARGET_DEVICES += nokia_xg-040g-md + +define Device/nokia_xg-040g-md-ubi + $(call Device/nokia_xg-040g-md-common) + DEVICE_VARIANT := (UBI) + DEVICE_DTS := an7581-nokia_xg-040g-md-ubi + UBOOTENV_IN_UBI := 1 + KERNEL_IN_UBI := 1 + KERNEL := kernel-bin | gzip + KERNEL_INITRAMFS := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 128k + KERNEL_INITRAMFS_SUFFIX := -recovery.itb + IMAGES := sysupgrade.itb + IMAGE/sysupgrade.itb := append-kernel | \ + fit gzip $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb external-static-with-rootfs | \ + append-metadata + DEVICE_PACKAGES += fitblk + ARTIFACT/bl31-uboot.fip := an7581-bl31-uboot nokia_xg-040g-md + ARTIFACT/preloader.bin := an7581-preloader nokia_xg-040g-md + ARTIFACTS := bl31-uboot.fip preloader.bin +endef +TARGET_DEVICES += nokia_xg-040g-md-ubi diff --git a/target/linux/airoha/patches-6.18/096-v6.19-net-airoha-Add-missing-stats-to-ethtool_eth_mac_stat.patch b/target/linux/airoha/patches-6.18/096-v6.19-net-airoha-Add-missing-stats-to-ethtool_eth_mac_stat.patch index 010b4fe6a4..0e579c4923 100644 --- a/target/linux/airoha/patches-6.18/096-v6.19-net-airoha-Add-missing-stats-to-ethtool_eth_mac_stat.patch +++ b/target/linux/airoha/patches-6.18/096-v6.19-net-airoha-Add-missing-stats-to-ethtool_eth_mac_stat.patch @@ -19,7 +19,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2160,8 +2160,12 @@ static void airoha_ethtool_get_mac_stats +@@ -2163,8 +2163,12 @@ static void airoha_ethtool_get_mac_stats airoha_update_hw_stats(port); do { start = u64_stats_fetch_begin(&port->stats.syncp); diff --git a/target/linux/airoha/patches-6.18/097-v6.19-net-airoha-Add-get_link-ethtool-callback.patch b/target/linux/airoha/patches-6.18/097-v6.19-net-airoha-Add-get_link-ethtool-callback.patch index 6ceae92cd2..f1f81fa08c 100644 --- a/target/linux/airoha/patches-6.18/097-v6.19-net-airoha-Add-get_link-ethtool-callback.patch +++ b/target/linux/airoha/patches-6.18/097-v6.19-net-airoha-Add-get_link-ethtool-callback.patch @@ -15,7 +15,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2908,6 +2908,7 @@ static const struct ethtool_ops airoha_e +@@ -2911,6 +2911,7 @@ static const struct ethtool_ops airoha_e .get_drvinfo = airoha_ethtool_get_drvinfo, .get_eth_mac_stats = airoha_ethtool_get_mac_stats, .get_rmon_stats = airoha_ethtool_get_rmon_stats, diff --git a/target/linux/airoha/patches-6.18/099-09-v6.19-net-airoha-Select-default-ppe-cpu-port-in-airoha_dev.patch b/target/linux/airoha/patches-6.18/099-09-v6.19-net-airoha-Select-default-ppe-cpu-port-in-airoha_dev.patch index 477d6e2d9d..e9a82de897 100644 --- a/target/linux/airoha/patches-6.18/099-09-v6.19-net-airoha-Select-default-ppe-cpu-port-in-airoha_dev.patch +++ b/target/linux/airoha/patches-6.18/099-09-v6.19-net-airoha-Select-default-ppe-cpu-port-in-airoha_dev.patch @@ -47,7 +47,7 @@ Signed-off-by: Paolo Abeni /* enable 1:N vlan action, init vlan table */ airoha_fe_set(eth, REG_MC_VLAN_EN, MC_VLAN_EN_MASK); -@@ -1853,8 +1834,10 @@ static int airhoha_set_gdm2_loopback(str +@@ -1856,8 +1837,10 @@ static int airhoha_set_gdm2_loopback(str static int airoha_dev_init(struct net_device *dev) { struct airoha_gdm_port *port = netdev_priv(dev); @@ -60,7 +60,7 @@ Signed-off-by: Paolo Abeni airoha_set_macaddr(port, dev->dev_addr); -@@ -1872,16 +1855,27 @@ static int airoha_dev_init(struct net_de +@@ -1875,16 +1858,27 @@ static int airoha_dev_init(struct net_de fallthrough; case AIROHA_GDM2_IDX: if (airoha_ppe_is_enabled(eth, 1)) { diff --git a/target/linux/airoha/patches-6.18/120-v7.0-net-airoha-implement-get_link_ksettings.patch b/target/linux/airoha/patches-6.18/120-v7.0-net-airoha-implement-get_link_ksettings.patch index 17e57d7c97..a15c17057e 100644 --- a/target/linux/airoha/patches-6.18/120-v7.0-net-airoha-implement-get_link_ksettings.patch +++ b/target/linux/airoha/patches-6.18/120-v7.0-net-airoha-implement-get_link_ksettings.patch @@ -16,7 +16,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2902,6 +2902,7 @@ static const struct ethtool_ops airoha_e +@@ -2905,6 +2905,7 @@ static const struct ethtool_ops airoha_e .get_drvinfo = airoha_ethtool_get_drvinfo, .get_eth_mac_stats = airoha_ethtool_get_mac_stats, .get_rmon_stats = airoha_ethtool_get_rmon_stats, diff --git a/target/linux/airoha/patches-6.18/125-v7.1-net-airoha-Rely-__field_prep-for-non-constant-masks.patch b/target/linux/airoha/patches-6.18/125-v7.1-net-airoha-Rely-__field_prep-for-non-constant-masks.patch index 91260a9794..ac7e6ebdb1 100644 --- a/target/linux/airoha/patches-6.18/125-v7.1-net-airoha-Rely-__field_prep-for-non-constant-masks.patch +++ b/target/linux/airoha/patches-6.18/125-v7.1-net-airoha-Rely-__field_prep-for-non-constant-masks.patch @@ -15,7 +15,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -1821,7 +1821,7 @@ static int airhoha_set_gdm2_loopback(str +@@ -1824,7 +1824,7 @@ static int airhoha_set_gdm2_loopback(str airoha_fe_rmw(eth, REG_SP_DFT_CPORT(src_port >> fls(SP_CPORT_DFT_MASK)), SP_CPORT_MASK(val), @@ -24,7 +24,7 @@ Signed-off-by: Jakub Kicinski if (port->id != AIROHA_GDM3_IDX && airoha_is_7581(eth)) airoha_fe_rmw(eth, REG_SRC_PORT_FC_MAP6, -@@ -1875,7 +1875,7 @@ static int airoha_dev_init(struct net_de +@@ -1878,7 +1878,7 @@ static int airoha_dev_init(struct net_de ppe_id = pse_port == FE_PSE_PORT_PPE2 ? 1 : 0; airoha_fe_rmw(eth, REG_PPE_DFT_CPORT0(ppe_id), DFT_CPORT_MASK(port->id), @@ -33,7 +33,7 @@ Signed-off-by: Jakub Kicinski return 0; } -@@ -2235,7 +2235,7 @@ static int airoha_qdma_set_chan_tx_sched +@@ -2238,7 +2238,7 @@ static int airoha_qdma_set_chan_tx_sched airoha_qdma_rmw(port->qdma, REG_CHAN_QOS_MODE(channel >> 3), CHAN_QOS_MODE_MASK(channel), diff --git a/target/linux/airoha/patches-6.18/126-v7.1-net-airoha-Make-flow-control-source-port-mapping-dep.patch b/target/linux/airoha/patches-6.18/126-v7.1-net-airoha-Make-flow-control-source-port-mapping-dep.patch index 7e078d0865..8a4479bc2c 100644 --- a/target/linux/airoha/patches-6.18/126-v7.1-net-airoha-Make-flow-control-source-port-mapping-dep.patch +++ b/target/linux/airoha/patches-6.18/126-v7.1-net-airoha-Make-flow-control-source-port-mapping-dep.patch @@ -19,7 +19,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -1823,10 +1823,12 @@ static int airhoha_set_gdm2_loopback(str +@@ -1826,10 +1826,12 @@ static int airhoha_set_gdm2_loopback(str SP_CPORT_MASK(val), __field_prep(SP_CPORT_MASK(val), FE_PSE_PORT_CDM2)); @@ -28,7 +28,7 @@ Signed-off-by: Jakub Kicinski - FC_ID_OF_SRC_PORT24_MASK, - FIELD_PREP(FC_ID_OF_SRC_PORT24_MASK, 2)); + if (port->id == AIROHA_GDM4_IDX && airoha_is_7581(eth)) { -+ u32 mask = FC_ID_OF_SRC_PORT_MASK(nbq); ++ u32 mask = FC_ID_OF_SRC_PORT_MASK(port->nbq); + + airoha_fe_rmw(eth, REG_SRC_PORT_FC_MAP6, mask, + __field_prep(mask, AIROHA_GDM2_IDX)); diff --git a/target/linux/airoha/patches-6.18/127-v7.1-net-airoha-Move-GDM-forward-port-configuration-in-nd.patch b/target/linux/airoha/patches-6.18/127-v7.1-net-airoha-Move-GDM-forward-port-configuration-in-nd.patch index 3b49e76b22..e44102acde 100644 --- a/target/linux/airoha/patches-6.18/127-v7.1-net-airoha-Move-GDM-forward-port-configuration-in-nd.patch +++ b/target/linux/airoha/patches-6.18/127-v7.1-net-airoha-Move-GDM-forward-port-configuration-in-nd.patch @@ -18,7 +18,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -1708,6 +1708,7 @@ static int airoha_dev_open(struct net_de +@@ -1711,6 +1711,7 @@ static int airoha_dev_open(struct net_de int err, len = ETH_HLEN + dev->mtu + ETH_FCS_LEN; struct airoha_gdm_port *port = netdev_priv(dev); struct airoha_qdma *qdma = port->qdma; @@ -26,7 +26,7 @@ Signed-off-by: Paolo Abeni netif_tx_start_all_queues(dev); err = airoha_set_vip_for_gdm_port(port, true); -@@ -1731,6 +1732,14 @@ static int airoha_dev_open(struct net_de +@@ -1734,6 +1735,14 @@ static int airoha_dev_open(struct net_de GLOBAL_CFG_RX_DMA_EN_MASK); atomic_inc(&qdma->users); @@ -41,7 +41,7 @@ Signed-off-by: Paolo Abeni return 0; } -@@ -1745,6 +1754,9 @@ static int airoha_dev_stop(struct net_de +@@ -1748,6 +1757,9 @@ static int airoha_dev_stop(struct net_de for (i = 0; i < dev->num_tx_queues; i++) netdev_tx_reset_subqueue(dev, i); @@ -51,7 +51,7 @@ Signed-off-by: Paolo Abeni if (atomic_dec_and_test(&qdma->users)) { airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG, GLOBAL_CFG_TX_DMA_EN_MASK | -@@ -1838,7 +1850,7 @@ static int airoha_dev_init(struct net_de +@@ -1841,7 +1853,7 @@ static int airoha_dev_init(struct net_de struct airoha_gdm_port *port = netdev_priv(dev); struct airoha_qdma *qdma = port->qdma; struct airoha_eth *eth = qdma->eth; @@ -60,7 +60,7 @@ Signed-off-by: Paolo Abeni u8 ppe_id; airoha_set_macaddr(port, dev->dev_addr); -@@ -1859,7 +1871,7 @@ static int airoha_dev_init(struct net_de +@@ -1862,7 +1874,7 @@ static int airoha_dev_init(struct net_de if (airoha_ppe_is_enabled(eth, 1)) { /* For PPE2 always use secondary cpu port. */ fe_cpu_port = FE_PSE_PORT_CDM2; @@ -69,7 +69,7 @@ Signed-off-by: Paolo Abeni break; } fallthrough; -@@ -1868,13 +1880,11 @@ static int airoha_dev_init(struct net_de +@@ -1871,13 +1883,11 @@ static int airoha_dev_init(struct net_de /* For PPE1 select cpu port according to the running QDMA. */ fe_cpu_port = qdma_id ? FE_PSE_PORT_CDM2 : FE_PSE_PORT_CDM1; diff --git a/target/linux/airoha/patches-6.18/129-v7.1-net-airoha-select-QDMA-block-according-LAN-WAN-confi.patch b/target/linux/airoha/patches-6.18/129-v7.1-net-airoha-select-QDMA-block-according-LAN-WAN-confi.patch index f8e489d9b7..2119016a60 100644 --- a/target/linux/airoha/patches-6.18/129-v7.1-net-airoha-select-QDMA-block-according-LAN-WAN-confi.patch +++ b/target/linux/airoha/patches-6.18/129-v7.1-net-airoha-select-QDMA-block-according-LAN-WAN-confi.patch @@ -39,7 +39,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -1848,11 +1848,13 @@ static int airhoha_set_gdm2_loopback(str +@@ -1851,11 +1851,13 @@ static int airhoha_set_gdm2_loopback(str static int airoha_dev_init(struct net_device *dev) { struct airoha_gdm_port *port = netdev_priv(dev); @@ -55,7 +55,7 @@ Signed-off-by: Paolo Abeni airoha_set_macaddr(port, dev->dev_addr); switch (port->id) { -@@ -1876,7 +1878,7 @@ static int airoha_dev_init(struct net_de +@@ -1879,7 +1881,7 @@ static int airoha_dev_init(struct net_de } fallthrough; default: { @@ -64,7 +64,7 @@ Signed-off-by: Paolo Abeni /* For PPE1 select cpu port according to the running QDMA. */ fe_cpu_port = qdma_id ? FE_PSE_PORT_CDM2 : FE_PSE_PORT_CDM1; -@@ -2963,11 +2965,10 @@ bool airoha_is_valid_gdm_port(struct air +@@ -2966,11 +2968,10 @@ bool airoha_is_valid_gdm_port(struct air } static int airoha_alloc_gdm_port(struct airoha_eth *eth, @@ -77,7 +77,7 @@ Signed-off-by: Paolo Abeni struct net_device *dev; int err, p; u32 id; -@@ -2998,7 +2999,6 @@ static int airoha_alloc_gdm_port(struct +@@ -3001,7 +3002,6 @@ static int airoha_alloc_gdm_port(struct return -ENOMEM; } @@ -85,7 +85,7 @@ Signed-off-by: Paolo Abeni dev->netdev_ops = &airoha_netdev_ops; dev->ethtool_ops = &airoha_ethtool_ops; dev->max_mtu = AIROHA_MAX_MTU; -@@ -3010,7 +3010,6 @@ static int airoha_alloc_gdm_port(struct +@@ -3013,7 +3013,6 @@ static int airoha_alloc_gdm_port(struct dev->features |= dev->hw_features; dev->vlan_features = dev->hw_features; dev->dev.of_node = np; @@ -93,7 +93,7 @@ Signed-off-by: Paolo Abeni SET_NETDEV_DEV(dev, eth->dev); /* reserve hw queues for HTB offloading */ -@@ -3031,7 +3030,7 @@ static int airoha_alloc_gdm_port(struct +@@ -3034,7 +3033,7 @@ static int airoha_alloc_gdm_port(struct port = netdev_priv(dev); u64_stats_init(&port->stats.syncp); spin_lock_init(&port->stats.lock); @@ -102,7 +102,7 @@ Signed-off-by: Paolo Abeni port->dev = dev; port->id = id; /* XXX: Read nbq from DTS */ -@@ -3133,7 +3132,6 @@ static int airoha_probe(struct platform_ +@@ -3136,7 +3135,6 @@ static int airoha_probe(struct platform_ for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) airoha_qdma_start_napi(ð->qdma[i]); @@ -110,7 +110,7 @@ Signed-off-by: Paolo Abeni for_each_child_of_node(pdev->dev.of_node, np) { if (!of_device_is_compatible(np, "airoha,eth-mac")) continue; -@@ -3141,7 +3139,7 @@ static int airoha_probe(struct platform_ +@@ -3144,7 +3142,7 @@ static int airoha_probe(struct platform_ if (!of_device_is_available(np)) continue; diff --git a/target/linux/airoha/patches-6.18/132-v7.1-net-airoha-Reset-PPE-default-cput-port-in-airoha_ppe.patch b/target/linux/airoha/patches-6.18/132-v7.1-net-airoha-Reset-PPE-default-cput-port-in-airoha_ppe.patch index 7262c7f3c7..6b28275fb4 100644 --- a/target/linux/airoha/patches-6.18/132-v7.1-net-airoha-Reset-PPE-default-cput-port-in-airoha_ppe.patch +++ b/target/linux/airoha/patches-6.18/132-v7.1-net-airoha-Reset-PPE-default-cput-port-in-airoha_ppe.patch @@ -32,7 +32,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -1849,8 +1849,7 @@ static int airoha_dev_init(struct net_de +@@ -1852,8 +1852,7 @@ static int airoha_dev_init(struct net_de { struct airoha_gdm_port *port = netdev_priv(dev); struct airoha_eth *eth = port->eth; @@ -42,7 +42,7 @@ Signed-off-by: Lorenzo Bianconi /* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */ port->qdma = ð->qdma[!airoha_is_lan_gdm_port(port)]; -@@ -1868,28 +1867,13 @@ static int airoha_dev_init(struct net_de +@@ -1871,28 +1870,13 @@ static int airoha_dev_init(struct net_de if (err) return err; } @@ -75,7 +75,7 @@ Signed-off-by: Lorenzo Bianconi return 0; } -@@ -1992,7 +1976,7 @@ static u32 airoha_get_dsa_tag(struct sk_ +@@ -1995,7 +1979,7 @@ static u32 airoha_get_dsa_tag(struct sk_ #endif } diff --git a/target/linux/airoha/patches-6.18/134-v7.1-net-airoha-Delay-offloading-until-all-net_devices-ar.patch b/target/linux/airoha/patches-6.18/134-v7.1-net-airoha-Delay-offloading-until-all-net_devices-ar.patch index b0112a08ba..cc7ae728da 100644 --- a/target/linux/airoha/patches-6.18/134-v7.1-net-airoha-Delay-offloading-until-all-net_devices-ar.patch +++ b/target/linux/airoha/patches-6.18/134-v7.1-net-airoha-Delay-offloading-until-all-net_devices-ar.patch @@ -26,7 +26,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -3040,6 +3040,8 @@ static int airoha_register_gdm_devices(s +@@ -3043,6 +3043,8 @@ static int airoha_register_gdm_devices(s return err; } diff --git a/target/linux/airoha/patches-6.18/142-01-v7.1-net-airoha-Rely-on-net_device-pointer-in-airoha_dev_.patch b/target/linux/airoha/patches-6.18/142-01-v7.1-net-airoha-Rely-on-net_device-pointer-in-airoha_dev_.patch index a66538984f..f00ec63915 100644 --- a/target/linux/airoha/patches-6.18/142-01-v7.1-net-airoha-Rely-on-net_device-pointer-in-airoha_dev_.patch +++ b/target/linux/airoha/patches-6.18/142-01-v7.1-net-airoha-Rely-on-net_device-pointer-in-airoha_dev_.patch @@ -20,7 +20,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2752,7 +2752,7 @@ static int airoha_dev_setup_tc_block_cb( +@@ -2755,7 +2755,7 @@ static int airoha_dev_setup_tc_block_cb( } } @@ -29,7 +29,7 @@ Signed-off-by: Jakub Kicinski struct flow_block_offload *f) { flow_setup_cb_t *cb = airoha_dev_setup_tc_block_cb; -@@ -2765,12 +2765,12 @@ static int airoha_dev_setup_tc_block(str +@@ -2768,12 +2768,12 @@ static int airoha_dev_setup_tc_block(str f->driver_block_list = &block_cb_list; switch (f->command) { case FLOW_BLOCK_BIND: @@ -44,7 +44,7 @@ Signed-off-by: Jakub Kicinski if (IS_ERR(block_cb)) return PTR_ERR(block_cb); -@@ -2779,7 +2779,7 @@ static int airoha_dev_setup_tc_block(str +@@ -2782,7 +2782,7 @@ static int airoha_dev_setup_tc_block(str list_add_tail(&block_cb->driver_list, &block_cb_list); return 0; case FLOW_BLOCK_UNBIND: @@ -53,7 +53,7 @@ Signed-off-by: Jakub Kicinski if (!block_cb) return -ENOENT; -@@ -2878,7 +2878,7 @@ static int airoha_dev_tc_setup(struct ne +@@ -2881,7 +2881,7 @@ static int airoha_dev_tc_setup(struct ne return airoha_tc_setup_qdisc_htb(port, type_data); case TC_SETUP_BLOCK: case TC_SETUP_FT: diff --git a/target/linux/airoha/patches-6.18/142-02-v7.1-net-airoha-Rely-on-net_device-pointer-in-HTB-callbac.patch b/target/linux/airoha/patches-6.18/142-02-v7.1-net-airoha-Rely-on-net_device-pointer-in-HTB-callbac.patch index faad31a588..6f64a8c35b 100644 --- a/target/linux/airoha/patches-6.18/142-02-v7.1-net-airoha-Rely-on-net_device-pointer-in-HTB-callbac.patch +++ b/target/linux/airoha/patches-6.18/142-02-v7.1-net-airoha-Rely-on-net_device-pointer-in-HTB-callbac.patch @@ -19,7 +19,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2557,10 +2557,11 @@ static int airoha_qdma_set_trtcm_token_b +@@ -2560,10 +2560,11 @@ static int airoha_qdma_set_trtcm_token_b mode, val); } @@ -32,7 +32,7 @@ Signed-off-by: Jakub Kicinski int i, err; for (i = 0; i <= TRTCM_PEAK_MODE; i++) { -@@ -2580,21 +2581,20 @@ static int airoha_qdma_set_tx_rate_limit +@@ -2583,21 +2584,20 @@ static int airoha_qdma_set_tx_rate_limit return 0; } @@ -58,7 +58,7 @@ Signed-off-by: Jakub Kicinski if (err) { NL_SET_ERR_MSG_MOD(opt->extack, "failed configuring htb offload"); -@@ -2606,7 +2606,7 @@ static int airoha_tc_htb_alloc_leaf_queu +@@ -2609,7 +2609,7 @@ static int airoha_tc_htb_alloc_leaf_queu err = netif_set_real_num_tx_queues(dev, num_tx_queues + 1); if (err) { @@ -67,7 +67,7 @@ Signed-off-by: Jakub Kicinski NL_SET_ERR_MSG_MOD(opt->extack, "failed setting real_num_tx_queues"); return err; -@@ -2793,44 +2793,47 @@ static int airoha_dev_setup_tc_block(str +@@ -2796,44 +2796,47 @@ static int airoha_dev_setup_tc_block(str } } @@ -123,7 +123,7 @@ Signed-off-by: Jakub Kicinski if (!test_bit(channel, port->qos_sq_bmap)) { NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id"); -@@ -2842,23 +2845,23 @@ static int airoha_tc_get_htb_get_leaf_qu +@@ -2845,23 +2848,23 @@ static int airoha_tc_get_htb_get_leaf_qu return 0; } @@ -152,7 +152,7 @@ Signed-off-by: Jakub Kicinski default: return -EOPNOTSUPP; } -@@ -2875,7 +2878,7 @@ static int airoha_dev_tc_setup(struct ne +@@ -2878,7 +2881,7 @@ static int airoha_dev_tc_setup(struct ne case TC_SETUP_QDISC_ETS: return airoha_tc_setup_qdisc_ets(port, type_data); case TC_SETUP_QDISC_HTB: diff --git a/target/linux/airoha/patches-6.18/142-03-v7.1-net-airoha-Rely-on-net_device-pointer-in-ETS-callbac.patch b/target/linux/airoha/patches-6.18/142-03-v7.1-net-airoha-Rely-on-net_device-pointer-in-ETS-callbac.patch index a9400d1fb8..8c3cdb49a5 100644 --- a/target/linux/airoha/patches-6.18/142-03-v7.1-net-airoha-Rely-on-net_device-pointer-in-ETS-callbac.patch +++ b/target/linux/airoha/patches-6.18/142-03-v7.1-net-airoha-Rely-on-net_device-pointer-in-ETS-callbac.patch @@ -19,7 +19,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2203,10 +2203,11 @@ airoha_ethtool_get_rmon_stats(struct net +@@ -2206,10 +2206,11 @@ airoha_ethtool_get_rmon_stats(struct net } while (u64_stats_fetch_retry(&port->stats.syncp, start)); } @@ -32,7 +32,7 @@ Signed-off-by: Jakub Kicinski int i; for (i = 0; i < AIROHA_NUM_TX_RING; i++) -@@ -2238,17 +2239,15 @@ static int airoha_qdma_set_chan_tx_sched +@@ -2241,17 +2242,15 @@ static int airoha_qdma_set_chan_tx_sched return 0; } @@ -53,7 +53,7 @@ Signed-off-by: Jakub Kicinski struct tc_ets_qopt_offload *opt) { struct tc_ets_qopt_offload_replace_params *p = &opt->replace_params; -@@ -2289,20 +2288,21 @@ static int airoha_qdma_set_tx_ets_sched( +@@ -2292,20 +2291,21 @@ static int airoha_qdma_set_tx_ets_sched( else if (nstrict < AIROHA_NUM_QOS_QUEUES - 1) mode = nstrict + 1; @@ -78,7 +78,7 @@ Signed-off-by: Jakub Kicinski _bstats_update(opt->stats.bstats, 0, tx_packets); port->cpu_tx_packets = cpu_tx_packets; -@@ -2311,7 +2311,7 @@ static int airoha_qdma_get_tx_ets_stats( +@@ -2314,7 +2314,7 @@ static int airoha_qdma_get_tx_ets_stats( return 0; } @@ -87,7 +87,7 @@ Signed-off-by: Jakub Kicinski struct tc_ets_qopt_offload *opt) { int channel; -@@ -2324,12 +2324,12 @@ static int airoha_tc_setup_qdisc_ets(str +@@ -2327,12 +2327,12 @@ static int airoha_tc_setup_qdisc_ets(str switch (opt->command) { case TC_ETS_REPLACE: @@ -103,7 +103,7 @@ Signed-off-by: Jakub Kicinski default: return -EOPNOTSUPP; } -@@ -2872,11 +2872,9 @@ static int airoha_tc_setup_qdisc_htb(str +@@ -2875,11 +2875,9 @@ static int airoha_tc_setup_qdisc_htb(str static int airoha_dev_tc_setup(struct net_device *dev, enum tc_setup_type type, void *type_data) { diff --git a/target/linux/airoha/patches-6.18/143-v7.1-net-airoha-Fix-typo-in-airoha_set_gdm2_loopback-rout.patch b/target/linux/airoha/patches-6.18/143-v7.1-net-airoha-Fix-typo-in-airoha_set_gdm2_loopback-rout.patch index 5a491bd59e..572f9cd0fb 100644 --- a/target/linux/airoha/patches-6.18/143-v7.1-net-airoha-Fix-typo-in-airoha_set_gdm2_loopback-rout.patch +++ b/target/linux/airoha/patches-6.18/143-v7.1-net-airoha-Fix-typo-in-airoha_set_gdm2_loopback-rout.patch @@ -15,7 +15,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -1786,7 +1786,7 @@ static int airoha_dev_set_macaddr(struct +@@ -1789,7 +1789,7 @@ static int airoha_dev_set_macaddr(struct return 0; } @@ -24,7 +24,7 @@ Signed-off-by: Jakub Kicinski { struct airoha_eth *eth = port->qdma->eth; u32 val, pse_port, chan; -@@ -1862,7 +1862,7 @@ static int airoha_dev_init(struct net_de +@@ -1865,7 +1865,7 @@ static int airoha_dev_init(struct net_de if (!eth->ports[1]) { int err; diff --git a/target/linux/airoha/patches-6.18/147-v7.1-net-airoha-Fix-PPE-cpu-port-configuration-for-GDM2-l.patch b/target/linux/airoha/patches-6.18/147-v7.1-net-airoha-Fix-PPE-cpu-port-configuration-for-GDM2-l.patch index 417adfd7db..4d82199c07 100644 --- a/target/linux/airoha/patches-6.18/147-v7.1-net-airoha-Fix-PPE-cpu-port-configuration-for-GDM2-l.patch +++ b/target/linux/airoha/patches-6.18/147-v7.1-net-airoha-Fix-PPE-cpu-port-configuration-for-GDM2-l.patch @@ -24,7 +24,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -1791,7 +1791,7 @@ static int airoha_set_gdm2_loopback(stru +@@ -1794,7 +1794,7 @@ static int airoha_set_gdm2_loopback(stru { struct airoha_eth *eth = port->qdma->eth; u32 val, pse_port, chan; @@ -33,7 +33,7 @@ Signed-off-by: Paolo Abeni airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX), FE_PSE_PORT_DROP); -@@ -1835,6 +1835,9 @@ static int airoha_set_gdm2_loopback(stru +@@ -1838,6 +1838,9 @@ static int airoha_set_gdm2_loopback(stru SP_CPORT_MASK(val), __field_prep(SP_CPORT_MASK(val), FE_PSE_PORT_CDM2)); @@ -41,9 +41,9 @@ Signed-off-by: Paolo Abeni + airoha_ppe_set_cpu_port(port, i, AIROHA_GDM2_IDX); + if (port->id == AIROHA_GDM4_IDX && airoha_is_7581(eth)) { - u32 mask = FC_ID_OF_SRC_PORT_MASK(nbq); + u32 mask = FC_ID_OF_SRC_PORT_MASK(port->nbq); -@@ -1873,7 +1876,8 @@ static int airoha_dev_init(struct net_de +@@ -1876,7 +1879,8 @@ static int airoha_dev_init(struct net_de } for (i = 0; i < eth->soc->num_ppe; i++) diff --git a/target/linux/airoha/patches-6.18/155-v7.2-net-airoha-Rename-get_src_port_id-callback-in-get_sp.patch b/target/linux/airoha/patches-6.18/155-v7.2-net-airoha-Rename-get_src_port_id-callback-in-get_sp.patch index 65e0a597e0..fba30f3206 100644 --- a/target/linux/airoha/patches-6.18/155-v7.2-net-airoha-Rename-get_src_port_id-callback-in-get_sp.patch +++ b/target/linux/airoha/patches-6.18/155-v7.2-net-airoha-Rename-get_src_port_id-callback-in-get_sp.patch @@ -17,7 +17,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -1822,7 +1822,7 @@ static int airoha_set_gdm2_loopback(stru +@@ -1825,7 +1825,7 @@ static int airoha_set_gdm2_loopback(stru airoha_fe_clear(eth, REG_FE_VIP_PORT_EN, BIT(AIROHA_GDM2_IDX)); airoha_fe_clear(eth, REG_FE_IFC_PORT_EN, BIT(AIROHA_GDM2_IDX)); @@ -26,7 +26,7 @@ Signed-off-by: Jakub Kicinski if (src_port < 0) return src_port; -@@ -3196,7 +3196,7 @@ static const char * const en7581_xsi_rst +@@ -3199,7 +3199,7 @@ static const char * const en7581_xsi_rst "xfp-mac", }; @@ -35,7 +35,7 @@ Signed-off-by: Jakub Kicinski { switch (port->id) { case AIROHA_GDM3_IDX: -@@ -3249,7 +3249,7 @@ static const char * const an7583_xsi_rst +@@ -3252,7 +3252,7 @@ static const char * const an7583_xsi_rst "xfp-mac", }; @@ -44,7 +44,7 @@ Signed-off-by: Jakub Kicinski { switch (port->id) { case AIROHA_GDM3_IDX: -@@ -3297,7 +3297,7 @@ static const struct airoha_eth_soc_data +@@ -3300,7 +3300,7 @@ static const struct airoha_eth_soc_data .num_xsi_rsts = ARRAY_SIZE(en7581_xsi_rsts_names), .num_ppe = 2, .ops = { @@ -53,7 +53,7 @@ Signed-off-by: Jakub Kicinski .get_vip_port = airoha_en7581_get_vip_port, }, }; -@@ -3308,7 +3308,7 @@ static const struct airoha_eth_soc_data +@@ -3311,7 +3311,7 @@ static const struct airoha_eth_soc_data .num_xsi_rsts = ARRAY_SIZE(an7583_xsi_rsts_names), .num_ppe = 1, .ops = { diff --git a/target/linux/airoha/patches-6.18/920-01-net-airoha-Introduce-airoha_gdm_dev-struct.patch b/target/linux/airoha/patches-6.18/161-01-v7.2-net-airoha-Introduce-airoha_gdm_dev-struct.patch similarity index 70% rename from target/linux/airoha/patches-6.18/920-01-net-airoha-Introduce-airoha_gdm_dev-struct.patch rename to target/linux/airoha/patches-6.18/161-01-v7.2-net-airoha-Introduce-airoha_gdm_dev-struct.patch index 6d2eee0446..c095e00cfc 100644 --- a/target/linux/airoha/patches-6.18/920-01-net-airoha-Introduce-airoha_gdm_dev-struct.patch +++ b/target/linux/airoha/patches-6.18/161-01-v7.2-net-airoha-Introduce-airoha_gdm_dev-struct.patch @@ -1,8 +1,7 @@ -From e15783f7c987e199ecf80b3d858ed5a86d33c508 Mon Sep 17 00:00:00 2001 -Message-ID: +From ec6c391bcca748bca041d5db92ff3bc4c99b3572 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi -Date: Sat, 1 Nov 2025 11:25:52 +0100 -Subject: [PATCH 01/13] net: airoha: Introduce airoha_gdm_dev struct +Date: Wed, 27 May 2026 12:21:15 +0200 +Subject: [PATCH 1/6] net: airoha: Introduce airoha_gdm_dev struct EN7581 and AN7583 SoCs support connecting multiple external SerDes to GDM3 or GDM4 ports via a hw arbiter that manages the traffic in a TDM manner. @@ -17,6 +16,8 @@ connected to the same GDM port. Tested-by: Xuegang Lu Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260527-airoha-eth-multi-serdes-preliminary-v1-1-ec6ed73ef7fc@kernel.org +Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/airoha/airoha_eth.c | 312 ++++++++++++++--------- drivers/net/ethernet/airoha/airoha_eth.h | 13 +- @@ -25,7 +26,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -738,6 +738,7 @@ static int airoha_qdma_rx_process(struct +@@ -600,6 +600,7 @@ static int airoha_qdma_rx_process(struct struct airoha_qdma_desc *desc = &q->desc[q->tail]; u32 hash, reason, msg1, desc_ctrl; struct airoha_gdm_port *port; @@ -33,7 +34,7 @@ Signed-off-by: Lorenzo Bianconi int data_len, len, p; struct page *page; -@@ -764,6 +765,10 @@ static int airoha_qdma_rx_process(struct +@@ -626,6 +627,10 @@ static int airoha_qdma_rx_process(struct goto free_frag; port = eth->ports[p]; @@ -44,24 +45,18 @@ Signed-off-by: Lorenzo Bianconi if (!q->skb) { /* first buffer */ q->skb = napi_build_skb(e->buf - AIROHA_RX_HEADROOM, q->buf_size); -@@ -772,14 +777,14 @@ static int airoha_qdma_rx_process(struct - +@@ -635,8 +640,8 @@ static int airoha_qdma_rx_process(struct skb_reserve(q->skb, AIROHA_RX_HEADROOM); __skb_put(q->skb, len); + skb_mark_for_recycle(q->skb); - q->skb->dev = port->dev; +- q->skb->protocol = eth_type_trans(q->skb, port->dev); + q->skb->dev = netdev; ++ q->skb->protocol = eth_type_trans(q->skb, netdev); q->skb->ip_summed = CHECKSUM_UNNECESSARY; skb_record_rx_queue(q->skb, qid); - - if (airoha_qdma_lro_rx_process(q, desc) < 0) - goto free_frag; - -- q->skb->protocol = eth_type_trans(q->skb, port->dev); -+ q->skb->protocol = eth_type_trans(q->skb, netdev); - skb_mark_for_recycle(q->skb); } else { /* scattered frame */ - struct skb_shared_info *shinfo = skb_shinfo(q->skb); -@@ -796,7 +801,7 @@ static int airoha_qdma_rx_process(struct +@@ -654,7 +659,7 @@ static int airoha_qdma_rx_process(struct if (FIELD_GET(QDMA_DESC_MORE_MASK, desc_ctrl)) continue; @@ -70,7 +65,7 @@ Signed-off-by: Lorenzo Bianconi /* PPE module requires untagged packets to work * properly and it provides DSA port index via the * DMA descriptor. Report DSA tag to the DSA stack -@@ -993,6 +998,7 @@ static void airoha_qdma_wake_netdev_txqs +@@ -848,6 +853,7 @@ static void airoha_qdma_wake_netdev_txqs for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; @@ -78,7 +73,7 @@ Signed-off-by: Lorenzo Bianconi int j; if (!port) -@@ -1001,11 +1007,12 @@ static void airoha_qdma_wake_netdev_txqs +@@ -856,11 +862,12 @@ static void airoha_qdma_wake_netdev_txqs if (port->qdma != qdma) continue; @@ -93,7 +88,7 @@ Signed-off-by: Lorenzo Bianconi } } q->txq_stopped = false; -@@ -1849,33 +1856,34 @@ static void airoha_update_hw_stats(struc +@@ -1703,19 +1710,20 @@ static void airoha_update_hw_stats(struc spin_unlock(&port->stats.lock); } @@ -108,35 +103,18 @@ Signed-off-by: Lorenzo Bianconi struct airoha_qdma *qdma = port->qdma; u32 pse_port = FE_PSE_PORT_PPE1; - #if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) { -- err = phylink_of_phy_connect(port->phylink, dev->dev.of_node, 0); -+ err = phylink_of_phy_connect(dev->phylink, netdev->dev.of_node, 0); - if (err) { -- netdev_err(dev, "%s: could not attach PHY: %d\n", __func__, -+ netdev_err(netdev, "%s: could not attach PHY: %d\n", __func__, - err); - return err; - } - -- phylink_start(port->phylink); -+ phylink_start(dev->phylink); - } - #endif - - netif_tx_start_all_queues(dev); + netif_tx_start_all_queues(netdev); err = airoha_set_vip_for_gdm_port(port, true); if (err) return err; - /* It seems GDM3 and GDM4 needs SPORT enabled to correctly work */ -- if (netdev_uses_dsa(dev) || port->id > 2) -+ if (netdev_uses_dsa(netdev) || port->id > 2) +- if (netdev_uses_dsa(dev)) ++ if (netdev_uses_dsa(netdev)) airoha_fe_set(qdma->eth, REG_GDM_INGRESS_CFG(port->id), GDM_STAG_EN_MASK); else -@@ -1903,16 +1911,17 @@ static int airoha_dev_open(struct net_de +@@ -1743,16 +1751,17 @@ static int airoha_dev_open(struct net_de return 0; } @@ -159,17 +137,7 @@ Signed-off-by: Lorenzo Bianconi airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id), FE_PSE_PORT_DROP); -@@ -1932,24 +1941,25 @@ static int airoha_dev_stop(struct net_de - - #if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) { -- phylink_stop(port->phylink); -- phylink_disconnect_phy(port->phylink); -+ phylink_stop(dev->phylink); -+ phylink_disconnect_phy(dev->phylink); - } - #endif - +@@ -1773,16 +1782,17 @@ static int airoha_dev_stop(struct net_de return 0; } @@ -191,7 +159,7 @@ Signed-off-by: Lorenzo Bianconi return 0; } -@@ -2015,16 +2025,17 @@ static int airoha_set_gdm2_loopback(stru +@@ -1848,16 +1858,17 @@ static int airoha_set_gdm2_loopback(stru return 0; } @@ -214,7 +182,7 @@ Signed-off-by: Lorenzo Bianconi switch (port->id) { case AIROHA_GDM3_IDX: -@@ -2049,10 +2060,11 @@ static int airoha_dev_init(struct net_de +@@ -1882,10 +1893,11 @@ static int airoha_dev_init(struct net_de return 0; } @@ -228,7 +196,7 @@ Signed-off-by: Lorenzo Bianconi unsigned int start; airoha_update_hw_stats(port); -@@ -2071,36 +2083,39 @@ static void airoha_dev_get_stats64(struc +@@ -1904,36 +1916,39 @@ static void airoha_dev_get_stats64(struc } while (u64_stats_fetch_retry(&port->stats.syncp, start)); } @@ -275,54 +243,7 @@ Signed-off-by: Lorenzo Bianconi } static u32 airoha_get_dsa_tag(struct sk_buff *skb, struct net_device *dev) -@@ -2163,11 +2178,12 @@ int airoha_get_fe_port(struct airoha_gdm - } - } - --static int airoha_dev_set_features(struct net_device *dev, -+static int airoha_dev_set_features(struct net_device *netdev, - netdev_features_t features) - { -- netdev_features_t diff = dev->features ^ features; -- struct airoha_gdm_port *port = netdev_priv(dev); -+ netdev_features_t diff = netdev->features ^ features; -+ struct airoha_gdm_dev *dev = netdev_priv(netdev); -+ struct airoha_gdm_port *port = dev->port; - struct airoha_qdma *qdma = port->qdma; - struct airoha_eth *eth = qdma->eth; - int qdma_id = qdma - ð->qdma[0]; -@@ -2176,7 +2192,7 @@ static int airoha_dev_set_features(struc - if (!(diff & NETIF_F_LRO)) - return 0; - -- if (netif_running(dev)) -+ if (netif_running(netdev)) - return -EBUSY; - - /* reset LRO configuration */ -@@ -2205,6 +2221,7 @@ static int airoha_dev_set_features(struc - } else { - for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { - struct airoha_gdm_port *p = eth->ports[i]; -+ struct airoha_gdm_dev *d; - - if (!p) - continue; -@@ -2212,10 +2229,11 @@ static int airoha_dev_set_features(struc - if (p->qdma != qdma) - continue; - -- if (p->dev == dev) -+ d = p->dev; -+ if (d->dev == netdev) - continue; - -- if (p->dev->features & NETIF_F_LRO) -+ if (d->dev->features & NETIF_F_LRO) - return 0; - } - airoha_fe_lro_disable(eth, qdma_id); -@@ -2225,9 +2243,10 @@ static int airoha_dev_set_features(struc +@@ -1997,9 +2012,10 @@ int airoha_get_fe_port(struct airoha_gdm } static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb, @@ -335,7 +256,7 @@ Signed-off-by: Lorenzo Bianconi struct airoha_qdma *qdma = port->qdma; u32 nr_frags, tag, msg0, msg1, len; struct airoha_queue_entry *e; -@@ -2240,7 +2259,7 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2012,7 +2028,7 @@ static netdev_tx_t airoha_dev_xmit(struc u8 fport; qid = airoha_qdma_get_txq(qdma, skb_get_queue_mapping(skb)); @@ -344,7 +265,7 @@ Signed-off-by: Lorenzo Bianconi msg0 = FIELD_PREP(QDMA_ETH_TXMSG_CHAN_MASK, qid / AIROHA_NUM_QOS_QUEUES) | -@@ -2276,7 +2295,7 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2048,7 +2064,7 @@ static netdev_tx_t airoha_dev_xmit(struc spin_lock_bh(&q->lock); @@ -353,7 +274,7 @@ Signed-off-by: Lorenzo Bianconi nr_frags = 1 + skb_shinfo(skb)->nr_frags; if (q->queued + nr_frags >= q->ndesc) { -@@ -2300,9 +2319,9 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2072,9 +2088,9 @@ static netdev_tx_t airoha_dev_xmit(struc dma_addr_t addr; u32 val; @@ -365,7 +286,7 @@ Signed-off-by: Lorenzo Bianconi goto error_unmap; list_move_tail(&e->list, &tx_list); -@@ -2351,7 +2370,7 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2123,7 +2139,7 @@ static netdev_tx_t airoha_dev_xmit(struc error_unmap: list_for_each_entry(e, &tx_list, list) { @@ -374,7 +295,7 @@ Signed-off-by: Lorenzo Bianconi DMA_TO_DEVICE); e->dma_addr = 0; } -@@ -2360,25 +2379,27 @@ error_unmap: +@@ -2132,25 +2148,27 @@ error_unmap: spin_unlock_bh(&q->lock); error: dev_kfree_skb_any(skb); @@ -407,7 +328,7 @@ Signed-off-by: Lorenzo Bianconi unsigned int start; airoha_update_hw_stats(port); -@@ -2406,11 +2427,12 @@ static const struct ethtool_rmon_hist_ra +@@ -2178,11 +2196,12 @@ static const struct ethtool_rmon_hist_ra }; static void @@ -422,7 +343,7 @@ Signed-off-by: Lorenzo Bianconi struct airoha_hw_stats *hw_stats = &port->stats; unsigned int start; -@@ -2435,11 +2457,12 @@ airoha_ethtool_get_rmon_stats(struct net +@@ -2207,11 +2226,12 @@ airoha_ethtool_get_rmon_stats(struct net } while (u64_stats_fetch_retry(&port->stats.syncp, start)); } @@ -437,7 +358,7 @@ Signed-off-by: Lorenzo Bianconi int i; for (i = 0; i < AIROHA_NUM_TX_RING; i++) -@@ -2524,10 +2547,12 @@ static int airoha_qdma_set_tx_ets_sched( +@@ -2296,10 +2316,12 @@ static int airoha_qdma_set_tx_ets_sched( ARRAY_SIZE(w)); } @@ -452,7 +373,7 @@ Signed-off-by: Lorenzo Bianconi u64 cpu_tx_packets = airoha_qdma_rr(port->qdma, REG_CNTR_VAL(channel << 1)); u64 fwd_tx_packets = airoha_qdma_rr(port->qdma, -@@ -2789,11 +2814,12 @@ static int airoha_qdma_set_trtcm_token_b +@@ -2561,11 +2583,12 @@ static int airoha_qdma_set_trtcm_token_b mode, val); } @@ -467,7 +388,7 @@ Signed-off-by: Lorenzo Bianconi int i, err; for (i = 0; i <= TRTCM_PEAK_MODE; i++) { -@@ -2813,20 +2839,22 @@ static int airoha_qdma_set_tx_rate_limit +@@ -2585,20 +2608,22 @@ static int airoha_qdma_set_tx_rate_limit return 0; } @@ -494,7 +415,7 @@ Signed-off-by: Lorenzo Bianconi if (err) { NL_SET_ERR_MSG_MOD(opt->extack, "failed configuring htb offload"); -@@ -2836,9 +2864,10 @@ static int airoha_tc_htb_alloc_leaf_queu +@@ -2608,9 +2633,10 @@ static int airoha_tc_htb_alloc_leaf_queu if (opt->command == TC_HTB_NODE_MODIFY) return 0; @@ -507,7 +428,7 @@ Signed-off-by: Lorenzo Bianconi NL_SET_ERR_MSG_MOD(opt->extack, "failed setting real_num_tx_queues"); return err; -@@ -2928,11 +2957,12 @@ static int airoha_tc_matchall_act_valida +@@ -2700,11 +2726,12 @@ static int airoha_tc_matchall_act_valida return 0; } @@ -522,7 +443,7 @@ Signed-off-by: Lorenzo Bianconi u32 rate = 0, bucket_size = 0; switch (f->command) { -@@ -2967,18 +2997,19 @@ static int airoha_dev_tc_matchall(struct +@@ -2739,18 +2766,19 @@ static int airoha_dev_tc_matchall(struct static int airoha_dev_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv) { @@ -546,7 +467,7 @@ Signed-off-by: Lorenzo Bianconi default: return -EOPNOTSUPP; } -@@ -3025,47 +3056,51 @@ static int airoha_dev_setup_tc_block(str +@@ -2797,47 +2825,51 @@ static int airoha_dev_setup_tc_block(str } } @@ -610,7 +531,7 @@ Signed-off-by: Lorenzo Bianconi if (!test_bit(channel, port->qos_sq_bmap)) { NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id"); -@@ -3101,8 +3136,8 @@ static int airoha_tc_setup_qdisc_htb(str +@@ -2873,8 +2905,8 @@ static int airoha_tc_setup_qdisc_htb(str return 0; } @@ -621,7 +542,7 @@ Signed-off-by: Lorenzo Bianconi { switch (type) { case TC_SETUP_QDISC_ETS: -@@ -3174,13 +3209,18 @@ static void airoha_metadata_dst_free(str +@@ -2940,25 +2972,81 @@ static void airoha_metadata_dst_free(str } } @@ -643,96 +564,9 @@ Signed-off-by: Lorenzo Bianconi return true; } -@@ -3192,8 +3232,9 @@ static void airoha_mac_link_up(struct ph - unsigned int mode, phy_interface_t interface, - int speed, int duplex, bool tx_pause, bool rx_pause) - { -- struct airoha_gdm_port *port = container_of(config, struct airoha_gdm_port, -- phylink_config); -+ struct airoha_gdm_dev *dev = container_of(config, struct airoha_gdm_dev, -+ phylink_config); -+ struct airoha_gdm_port *port = dev->port; - struct airoha_qdma *qdma = port->qdma; - struct airoha_eth *eth = qdma->eth; - u32 frag_size_tx, frag_size_rx; -@@ -3249,65 +3290,122 @@ static int airoha_fill_available_pcs(str - &num_available_pcs); + return false; } --static int airoha_setup_phylink(struct net_device *dev) -+static int airoha_setup_phylink(struct net_device *netdev) - { -- struct airoha_gdm_port *port = netdev_priv(dev); -- struct device_node *np = dev->dev.of_node; -+ struct airoha_gdm_dev *dev = netdev_priv(netdev); -+ struct device_node *np = netdev->dev.of_node; - phy_interface_t phy_mode; - struct phylink *phylink; - int err; - - err = of_get_phy_mode(np, &phy_mode); - if (err) { -- dev_err(&dev->dev, "incorrect phy-mode\n"); -+ dev_err(&netdev->dev, "incorrect phy-mode\n"); - return err; - } - -- port->phylink_config.dev = &dev->dev; -- port->phylink_config.type = PHYLINK_NETDEV; -- port->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | -- MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD | -- MAC_5000FD | MAC_10000FD; -+ dev->phylink_config.dev = &netdev->dev; -+ dev->phylink_config.type = PHYLINK_NETDEV; -+ dev->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | -+ MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD | -+ MAC_5000FD | MAC_10000FD; - -- err = fwnode_phylink_pcs_parse(dev_fwnode(&dev->dev), NULL, -- &port->phylink_config.num_available_pcs); -+ err = fwnode_phylink_pcs_parse(dev_fwnode(&netdev->dev), NULL, -+ &dev->phylink_config.num_available_pcs); - if (err) - return err; - -- port->phylink_config.fill_available_pcs = airoha_fill_available_pcs; -+ dev->phylink_config.fill_available_pcs = airoha_fill_available_pcs; - - __set_bit(PHY_INTERFACE_MODE_SGMII, -- port->phylink_config.supported_interfaces); -+ dev->phylink_config.supported_interfaces); - __set_bit(PHY_INTERFACE_MODE_1000BASEX, -- port->phylink_config.supported_interfaces); -+ dev->phylink_config.supported_interfaces); - __set_bit(PHY_INTERFACE_MODE_2500BASEX, -- port->phylink_config.supported_interfaces); -+ dev->phylink_config.supported_interfaces); - __set_bit(PHY_INTERFACE_MODE_10GBASER, -- port->phylink_config.supported_interfaces); -+ dev->phylink_config.supported_interfaces); - __set_bit(PHY_INTERFACE_MODE_USXGMII, -- port->phylink_config.supported_interfaces); -+ dev->phylink_config.supported_interfaces); - -- phy_interface_copy(port->phylink_config.pcs_interfaces, -- port->phylink_config.supported_interfaces); -+ phy_interface_copy(dev->phylink_config.pcs_interfaces, -+ dev->phylink_config.supported_interfaces); - -- phylink = phylink_create(&port->phylink_config, -+ phylink = phylink_create(&dev->phylink_config, - of_fwnode_handle(np), - phy_mode, &airoha_phylink_ops); - if (IS_ERR(phylink)) - return PTR_ERR(phylink); - -- port->phylink = phylink; -+ dev->phylink = phylink; - - return err; - } - #endif - +static int airoha_alloc_gdm_device(struct airoha_eth *eth, + struct airoha_gdm_port *port, + struct device_node *np) @@ -753,9 +587,11 @@ Signed-off-by: Lorenzo Bianconi + netdev->ethtool_ops = &airoha_ethtool_ops; + netdev->max_mtu = AIROHA_MAX_MTU; + netdev->watchdog_timeo = 5 * HZ; -+ netdev->hw_features = AIROHA_HW_FEATURES | NETIF_F_LRO; -+ netdev->features |= AIROHA_HW_FEATURES; -+ netdev->vlan_features = AIROHA_HW_FEATURES; ++ netdev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | NETIF_F_TSO6 | ++ NETIF_F_IPV6_CSUM | NETIF_F_SG | NETIF_F_TSO | ++ NETIF_F_HW_TC; ++ netdev->features |= netdev->hw_features; ++ netdev->vlan_features = netdev->hw_features; + netdev->dev.of_node = np; + SET_NETDEV_DEV(netdev, eth->dev); + @@ -780,14 +616,6 @@ Signed-off-by: Lorenzo Bianconi + port->dev = dev; + dev->eth = eth; + -+#if defined(CONFIG_PCS_AIROHA) -+ if (airhoa_is_phy_external(port)) { -+ err = airoha_setup_phylink(netdev); -+ if (err) -+ return err; -+ } -+#endif -+ + return 0; +} + @@ -800,7 +628,7 @@ Signed-off-by: Lorenzo Bianconi int err, p; u32 id; -@@ -3329,58 +3427,22 @@ static int airoha_alloc_gdm_port(struct +@@ -2980,53 +3068,22 @@ static int airoha_alloc_gdm_port(struct return -EINVAL; } @@ -818,17 +646,20 @@ Signed-off-by: Lorenzo Bianconi - dev->ethtool_ops = &airoha_ethtool_ops; - dev->max_mtu = AIROHA_MAX_MTU; - dev->watchdog_timeo = 5 * HZ; -- dev->hw_features = AIROHA_HW_FEATURES | NETIF_F_LRO; -- dev->features |= AIROHA_HW_FEATURES; -- dev->vlan_features = AIROHA_HW_FEATURES; +- dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | +- NETIF_F_TSO6 | NETIF_F_IPV6_CSUM | +- NETIF_F_SG | NETIF_F_TSO | +- NETIF_F_HW_TC; +- dev->features |= dev->hw_features; +- dev->vlan_features = dev->hw_features; - dev->dev.of_node = np; - SET_NETDEV_DEV(dev, eth->dev); -- + - /* reserve hw queues for HTB offloading */ - err = netif_set_real_num_tx_queues(dev, AIROHA_NUM_TX_RING); - if (err) - return err; - +- - err = of_get_ethdev_address(np, dev); - if (err) { - if (err == -EPROBE_DEFER) @@ -849,23 +680,16 @@ Signed-off-by: Lorenzo Bianconi port->nbq = id == AIROHA_GDM3_IDX && airoha_is_7581(eth) ? 4 : 0; eth->ports[p] = port; --#if defined(CONFIG_PCS_AIROHA) -- if (airhoa_is_phy_external(port)) { -- err = airoha_setup_phylink(dev); -- if (err) -- return err; -- } --#endif +- return airoha_metadata_dst_alloc(port); + err = airoha_metadata_dst_alloc(port); + if (err) + return err; - -- return airoha_metadata_dst_alloc(port); ++ + return airoha_alloc_gdm_device(eth, port, np); } static int airoha_register_gdm_devices(struct airoha_eth *eth) -@@ -3394,7 +3456,7 @@ static int airoha_register_gdm_devices(s +@@ -3040,7 +3097,7 @@ static int airoha_register_gdm_devices(s if (!port) continue; @@ -874,7 +698,7 @@ Signed-off-by: Lorenzo Bianconi if (err) return err; } -@@ -3503,16 +3565,18 @@ error_napi_stop: +@@ -3149,12 +3206,14 @@ error_napi_stop: for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; @@ -883,20 +707,15 @@ Signed-off-by: Lorenzo Bianconi if (!port) continue; -- if (port->dev->reg_state == NETREG_REGISTERED) { -+ dev = port->dev; -+ if (dev && dev->dev->reg_state == NETREG_REGISTERED) { - #if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) -- phylink_destroy(port->phylink); -+ phylink_destroy(dev->phylink); - #endif +- if (port->dev->reg_state == NETREG_REGISTERED) - unregister_netdev(port->dev); ++ dev = port->dev; ++ if (dev && dev->dev->reg_state == NETREG_REGISTERED) + unregister_netdev(dev->dev); - } airoha_metadata_dst_free(port); } -@@ -3534,15 +3598,19 @@ static void airoha_remove(struct platfor + airoha_hw_cleanup(eth); +@@ -3175,11 +3234,14 @@ static void airoha_remove(struct platfor for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; @@ -905,13 +724,7 @@ Signed-off-by: Lorenzo Bianconi if (!port) continue; - #if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) -- phylink_destroy(port->phylink); -+ phylink_destroy(dev->phylink); - #endif - unregister_netdev(port->dev); -+ + dev = port->dev; + if (dev) + unregister_netdev(dev->dev); @@ -920,35 +733,25 @@ Signed-off-by: Lorenzo Bianconi airoha_hw_cleanup(eth); --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -547,17 +547,22 @@ struct airoha_qdma { +@@ -535,10 +535,15 @@ struct airoha_qdma { struct airoha_queue q_rx[AIROHA_NUM_RX_RING]; }; --struct airoha_gdm_port { -- struct airoha_qdma *qdma; -- struct airoha_eth *eth; +struct airoha_gdm_dev { + struct airoha_gdm_port *port; - struct net_device *dev; -- int id; -- int nbq; ++ struct net_device *dev; + struct airoha_eth *eth; - - #if defined(CONFIG_PCS_AIROHA) - struct phylink *phylink; - struct phylink_config phylink_config; - #endif +}; + -+struct airoha_gdm_port { -+ struct airoha_qdma *qdma; + struct airoha_gdm_port { + struct airoha_qdma *qdma; +- struct airoha_eth *eth; +- struct net_device *dev; + struct airoha_gdm_dev *dev; -+ int id; -+ int nbq; + int id; + int nbq; - struct airoha_hw_stats stats; - -@@ -691,8 +696,8 @@ static inline bool airoha_qdma_is_lro_qu +@@ -662,8 +667,8 @@ static inline bool airoha_is_7583(struct } int airoha_get_fe_port(struct airoha_gdm_port *port); @@ -961,14 +764,14 @@ Signed-off-by: Lorenzo Bianconi u8 fport); --- a/drivers/net/ethernet/airoha/airoha_ppe.c +++ b/drivers/net/ethernet/airoha/airoha_ppe.c -@@ -299,12 +299,12 @@ static void airoha_ppe_foe_set_bridge_ad +@@ -298,12 +298,12 @@ static void airoha_ppe_foe_set_bridge_ad static int airoha_ppe_foe_entry_prepare(struct airoha_eth *eth, struct airoha_foe_entry *hwe, - struct net_device *dev, int type, + struct net_device *netdev, int type, struct airoha_flow_data *data, - int l4proto, u8 dsfield) + int l4proto) { u32 qdata = FIELD_PREP(AIROHA_FOE_SHAPER_ID, 0x7f), ports_pad, val; - int wlan_etype = -EINVAL, dsa_port = airoha_get_dsa_port(&dev); @@ -976,7 +779,7 @@ Signed-off-by: Lorenzo Bianconi struct airoha_foe_mac_info_common *l2; u8 smac_id = 0xf; -@@ -320,10 +320,11 @@ static int airoha_ppe_foe_entry_prepare( +@@ -319,10 +319,11 @@ static int airoha_ppe_foe_entry_prepare( hwe->ib1 = val; val = FIELD_PREP(AIROHA_FOE_IB2_PORT_AG, 0x1f); @@ -990,14 +793,14 @@ Signed-off-by: Lorenzo Bianconi val |= FIELD_PREP(AIROHA_FOE_IB2_NBQ, info.idx) | FIELD_PREP(AIROHA_FOE_IB2_PSE_PORT, FE_PSE_PORT_CDM4); -@@ -333,12 +334,14 @@ static int airoha_ppe_foe_entry_prepare( +@@ -332,12 +333,14 @@ static int airoha_ppe_foe_entry_prepare( FIELD_PREP(AIROHA_FOE_MAC_WDMA_WCID, info.wcid); } else { - struct airoha_gdm_port *port = netdev_priv(dev); + struct airoha_gdm_dev *dev = netdev_priv(netdev); - u8 pse_port, channel, priority; + struct airoha_gdm_port *port; + u8 pse_port, channel; - if (!airoha_is_valid_gdm_port(eth, port)) + if (!airoha_is_valid_gdm_dev(eth, dev)) @@ -1007,7 +810,7 @@ Signed-off-by: Lorenzo Bianconi if (dsa_port >= 0 || eth->ports[1]) pse_port = port->id == 4 ? FE_PSE_PORT_GDM4 : port->id; -@@ -1485,7 +1488,7 @@ void airoha_ppe_check_skb(struct airoha_ +@@ -1473,7 +1476,7 @@ void airoha_ppe_check_skb(struct airoha_ void airoha_ppe_init_upd_mem(struct airoha_gdm_port *port) { struct airoha_eth *eth = port->qdma->eth; diff --git a/target/linux/airoha/patches-6.18/920-02-net-airoha-Move-airoha_qdma-pointer-in-airoha_gdm_de.patch b/target/linux/airoha/patches-6.18/161-02-v7.2-net-airoha-Move-airoha_qdma-pointer-in-airoha_gdm_de.patch similarity index 77% rename from target/linux/airoha/patches-6.18/920-02-net-airoha-Move-airoha_qdma-pointer-in-airoha_gdm_de.patch rename to target/linux/airoha/patches-6.18/161-02-v7.2-net-airoha-Move-airoha_qdma-pointer-in-airoha_gdm_de.patch index 8f3dd2d1d1..bca63f5ec6 100644 --- a/target/linux/airoha/patches-6.18/920-02-net-airoha-Move-airoha_qdma-pointer-in-airoha_gdm_de.patch +++ b/target/linux/airoha/patches-6.18/161-02-v7.2-net-airoha-Move-airoha_qdma-pointer-in-airoha_gdm_de.patch @@ -1,10 +1,7 @@ -From f62cea6483cc55360863d66300790a5fb9de5f7c Mon Sep 17 00:00:00 2001 -Message-ID: -In-Reply-To: -References: +From 528c5153a557f69482d91609a2a002ded22a3441 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi -Date: Tue, 24 Feb 2026 18:43:05 +0100 -Subject: [PATCH 02/13] net: airoha: Move airoha_qdma pointer in airoha_gdm_dev +Date: Wed, 27 May 2026 12:21:16 +0200 +Subject: [PATCH 2/6] net: airoha: Move airoha_qdma pointer in airoha_gdm_dev struct Move airoha_qdma pointer from airoha_gdm_port struct to airoha_gdm_dev @@ -16,6 +13,8 @@ to the same GDM{3,4} port via an external hw arbiter. Tested-by: Xuegang Lu Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260527-airoha-eth-multi-serdes-preliminary-v1-2-ec6ed73ef7fc@kernel.org +Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/airoha/airoha_eth.c | 105 +++++++++++------------ drivers/net/ethernet/airoha/airoha_eth.h | 9 +- @@ -24,9 +23,9 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -80,9 +80,10 @@ static bool airhoa_is_phy_external(struc +@@ -71,9 +71,10 @@ static void airoha_qdma_irq_disable(stru + airoha_qdma_set_irqmask(irq_bank, index, mask, 0); } - #endif -static void airoha_set_macaddr(struct airoha_gdm_port *port, const u8 *addr) +static void airoha_set_macaddr(struct airoha_gdm_dev *dev, const u8 *addr) @@ -37,7 +36,7 @@ Signed-off-by: Lorenzo Bianconi u32 val, reg; reg = airoha_is_lan_gdm_port(port) ? REG_FE_LAN_MAC_H -@@ -94,7 +95,7 @@ static void airoha_set_macaddr(struct ai +@@ -85,7 +86,7 @@ static void airoha_set_macaddr(struct ai airoha_fe_wr(eth, REG_FE_MAC_LMIN(reg), val); airoha_fe_wr(eth, REG_FE_MAC_LMAX(reg), val); @@ -46,7 +45,7 @@ Signed-off-by: Lorenzo Bianconi } static void airoha_set_gdm_port_fwd_cfg(struct airoha_eth *eth, u32 addr, -@@ -110,10 +111,10 @@ static void airoha_set_gdm_port_fwd_cfg( +@@ -101,10 +102,10 @@ static void airoha_set_gdm_port_fwd_cfg( FIELD_PREP(GDM_UCFQ_MASK, val)); } @@ -60,7 +59,7 @@ Signed-off-by: Lorenzo Bianconi u32 vip_port; vip_port = eth->soc->ops.get_vip_port(port, port->nbq); -@@ -1004,10 +1005,13 @@ static void airoha_qdma_wake_netdev_txqs +@@ -859,10 +860,13 @@ static void airoha_qdma_wake_netdev_txqs if (!port) continue; @@ -76,7 +75,7 @@ Signed-off-by: Lorenzo Bianconi for (j = 0; j < dev->dev->num_tx_queues; j++) { if (airoha_qdma_get_txq(qdma, j) != qid) continue; -@@ -1712,9 +1716,10 @@ static void airoha_qdma_stop_napi(struct +@@ -1566,9 +1570,10 @@ static void airoha_qdma_stop_napi(struct } } @@ -89,7 +88,7 @@ Signed-off-by: Lorenzo Bianconi u32 val, i = 0; spin_lock(&port->stats.lock); -@@ -1861,7 +1866,7 @@ static int airoha_dev_open(struct net_de +@@ -1715,11 +1720,11 @@ static int airoha_dev_open(struct net_de int err, len = ETH_HLEN + netdev->mtu + ETH_FCS_LEN; struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; @@ -97,17 +96,13 @@ Signed-off-by: Lorenzo Bianconi + struct airoha_qdma *qdma = dev->qdma; u32 pse_port = FE_PSE_PORT_PPE1; - #if defined(CONFIG_PCS_AIROHA) -@@ -1878,7 +1883,7 @@ static int airoha_dev_open(struct net_de - #endif - netif_tx_start_all_queues(netdev); - err = airoha_set_vip_for_gdm_port(port, true); + err = airoha_set_vip_for_gdm_port(dev, true); if (err) return err; -@@ -1915,11 +1920,11 @@ static int airoha_dev_stop(struct net_de +@@ -1755,11 +1760,11 @@ static int airoha_dev_stop(struct net_de { struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; @@ -121,7 +116,7 @@ Signed-off-by: Lorenzo Bianconi for (i = 0; i < netdev->num_tx_queues; i++) netdev_tx_reset_subqueue(netdev, i); -@@ -1952,21 +1957,21 @@ static int airoha_dev_stop(struct net_de +@@ -1785,21 +1790,21 @@ static int airoha_dev_stop(struct net_de static int airoha_dev_set_macaddr(struct net_device *netdev, void *p) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -147,7 +142,7 @@ Signed-off-by: Lorenzo Bianconi u32 val, pse_port, chan; int i, src_port; -@@ -2013,7 +2018,7 @@ static int airoha_set_gdm2_loopback(stru +@@ -1846,7 +1851,7 @@ static int airoha_set_gdm2_loopback(stru __field_prep(SP_CPORT_MASK(val), FE_PSE_PORT_CDM2)); for (i = 0; i < eth->soc->num_ppe; i++) @@ -155,8 +150,8 @@ Signed-off-by: Lorenzo Bianconi + airoha_ppe_set_cpu_port(dev, i, AIROHA_GDM2_IDX); if (port->id == AIROHA_GDM4_IDX && airoha_is_7581(eth)) { - u32 mask = FC_ID_OF_SRC_PORT_MASK(nbq); -@@ -2033,9 +2038,9 @@ static int airoha_dev_init(struct net_de + u32 mask = FC_ID_OF_SRC_PORT_MASK(port->nbq); +@@ -1866,9 +1871,9 @@ static int airoha_dev_init(struct net_de int i; /* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */ @@ -169,7 +164,7 @@ Signed-off-by: Lorenzo Bianconi switch (port->id) { case AIROHA_GDM3_IDX: -@@ -2044,7 +2049,7 @@ static int airoha_dev_init(struct net_de +@@ -1877,7 +1882,7 @@ static int airoha_dev_init(struct net_de if (!eth->ports[1]) { int err; @@ -178,7 +173,7 @@ Signed-off-by: Lorenzo Bianconi if (err) return err; } -@@ -2054,8 +2059,7 @@ static int airoha_dev_init(struct net_de +@@ -1887,8 +1892,7 @@ static int airoha_dev_init(struct net_de } for (i = 0; i < eth->soc->num_ppe; i++) @@ -188,7 +183,7 @@ Signed-off-by: Lorenzo Bianconi return 0; } -@@ -2067,7 +2071,7 @@ static void airoha_dev_get_stats64(struc +@@ -1900,7 +1904,7 @@ static void airoha_dev_get_stats64(struc struct airoha_gdm_port *port = dev->port; unsigned int start; @@ -197,7 +192,7 @@ Signed-off-by: Lorenzo Bianconi do { start = u64_stats_fetch_begin(&port->stats.syncp); storage->rx_packets = port->stats.rx_ok_pkts; -@@ -2087,8 +2091,8 @@ static int airoha_dev_change_mtu(struct +@@ -1920,8 +1924,8 @@ static int airoha_dev_change_mtu(struct { struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; @@ -207,7 +202,7 @@ Signed-off-by: Lorenzo Bianconi airoha_fe_rmw(eth, REG_GDM_LEN_CFG(port->id), GDM_LONG_LEN_MASK, -@@ -2162,10 +2166,10 @@ static u32 airoha_get_dsa_tag(struct sk_ +@@ -1995,10 +1999,10 @@ static u32 airoha_get_dsa_tag(struct sk_ #endif } @@ -221,30 +216,7 @@ Signed-off-by: Lorenzo Bianconi switch (eth->soc->version) { case 0x7583: -@@ -2183,8 +2187,7 @@ static int airoha_dev_set_features(struc - { - netdev_features_t diff = netdev->features ^ features; - struct airoha_gdm_dev *dev = netdev_priv(netdev); -- struct airoha_gdm_port *port = dev->port; -- struct airoha_qdma *qdma = port->qdma; -+ struct airoha_qdma *qdma = dev->qdma; - struct airoha_eth *eth = qdma->eth; - int qdma_id = qdma - ð->qdma[0]; - int i; -@@ -2226,10 +2229,10 @@ static int airoha_dev_set_features(struc - if (!p) - continue; - -- if (p->qdma != qdma) -+ d = p->dev; -+ if (d->qdma != qdma) - continue; - -- d = p->dev; - if (d->dev == netdev) - continue; - -@@ -2246,8 +2249,7 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2015,8 +2019,7 @@ static netdev_tx_t airoha_dev_xmit(struc struct net_device *netdev) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -254,7 +226,7 @@ Signed-off-by: Lorenzo Bianconi u32 nr_frags, tag, msg0, msg1, len; struct airoha_queue_entry *e; struct netdev_queue *txq; -@@ -2285,7 +2287,7 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2054,7 +2057,7 @@ static netdev_tx_t airoha_dev_xmit(struc } } @@ -263,7 +235,7 @@ Signed-off-by: Lorenzo Bianconi msg1 = FIELD_PREP(QDMA_ETH_TXMSG_FPORT_MASK, fport) | FIELD_PREP(QDMA_ETH_TXMSG_METER_MASK, 0x7f); -@@ -2388,8 +2390,7 @@ static void airoha_ethtool_get_drvinfo(s +@@ -2157,8 +2160,7 @@ static void airoha_ethtool_get_drvinfo(s struct ethtool_drvinfo *info) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -273,7 +245,7 @@ Signed-off-by: Lorenzo Bianconi strscpy(info->driver, eth->dev->driver->name, sizeof(info->driver)); strscpy(info->bus_info, dev_name(eth->dev), sizeof(info->bus_info)); -@@ -2402,7 +2403,7 @@ static void airoha_ethtool_get_mac_stats +@@ -2171,7 +2173,7 @@ static void airoha_ethtool_get_mac_stats struct airoha_gdm_port *port = dev->port; unsigned int start; @@ -282,7 +254,7 @@ Signed-off-by: Lorenzo Bianconi do { start = u64_stats_fetch_begin(&port->stats.syncp); stats->FramesTransmittedOK = port->stats.tx_ok_pkts; -@@ -2442,7 +2443,7 @@ airoha_ethtool_get_rmon_stats(struct net +@@ -2211,7 +2213,7 @@ airoha_ethtool_get_rmon_stats(struct net ARRAY_SIZE(hw_stats->rx_len) + 1); *ranges = airoha_ethtool_rmon_ranges; @@ -291,7 +263,7 @@ Signed-off-by: Lorenzo Bianconi do { int i; -@@ -2462,18 +2463,17 @@ static int airoha_qdma_set_chan_tx_sched +@@ -2231,18 +2233,17 @@ static int airoha_qdma_set_chan_tx_sched const u16 *weights, u8 n_weights) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -312,7 +284,7 @@ Signed-off-by: Lorenzo Bianconi TWRR_RW_CMD_MASK | FIELD_PREP(TWRR_CHAN_IDX_MASK, channel) | FIELD_PREP(TWRR_QUEUE_IDX_MASK, i) | -@@ -2481,13 +2481,12 @@ static int airoha_qdma_set_chan_tx_sched +@@ -2250,13 +2251,12 @@ static int airoha_qdma_set_chan_tx_sched err = read_poll_timeout(airoha_qdma_rr, status, status & TWRR_RW_CMD_DONE, USEC_PER_MSEC, 10 * USEC_PER_MSEC, @@ -328,7 +300,7 @@ Signed-off-by: Lorenzo Bianconi CHAN_QOS_MODE_MASK(channel), __field_prep(CHAN_QOS_MODE_MASK(channel), mode)); -@@ -2553,9 +2552,9 @@ static int airoha_qdma_get_tx_ets_stats( +@@ -2322,9 +2322,9 @@ static int airoha_qdma_get_tx_ets_stats( struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; @@ -340,7 +312,7 @@ Signed-off-by: Lorenzo Bianconi REG_CNTR_VAL((channel << 1) + 1)); u64 tx_packets = (cpu_tx_packets - port->cpu_tx_packets) + (fwd_tx_packets - port->fwd_tx_packets); -@@ -2819,17 +2818,16 @@ static int airoha_qdma_set_tx_rate_limit +@@ -2588,17 +2588,16 @@ static int airoha_qdma_set_tx_rate_limit u32 bucket_size) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -360,7 +332,7 @@ Signed-off-by: Lorenzo Bianconi REG_EGRESS_TRTCM_CFG, i, rate, bucket_size); if (err) -@@ -2879,11 +2877,11 @@ static int airoha_tc_htb_alloc_leaf_queu +@@ -2648,11 +2647,11 @@ static int airoha_tc_htb_alloc_leaf_queu return 0; } @@ -374,7 +346,7 @@ Signed-off-by: Lorenzo Bianconi int i; for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { -@@ -2962,7 +2960,6 @@ static int airoha_dev_tc_matchall(struct +@@ -2731,7 +2730,6 @@ static int airoha_dev_tc_matchall(struct { enum trtcm_unit_type unit_type = TRTCM_BYTE_UNIT; struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -382,7 +354,7 @@ Signed-off-by: Lorenzo Bianconi u32 rate = 0, bucket_size = 0; switch (f->command) { -@@ -2987,7 +2984,7 @@ static int airoha_dev_tc_matchall(struct +@@ -2756,7 +2754,7 @@ static int airoha_dev_tc_matchall(struct fallthrough; } case TC_CLSMATCHALL_DESTROY: @@ -391,7 +363,7 @@ Signed-off-by: Lorenzo Bianconi unit_type); default: return -EOPNOTSUPP; -@@ -2999,8 +2996,7 @@ static int airoha_dev_setup_tc_block_cb( +@@ -2768,8 +2766,7 @@ static int airoha_dev_setup_tc_block_cb( { struct net_device *netdev = cb_priv; struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -401,26 +373,15 @@ Signed-off-by: Lorenzo Bianconi if (!tc_can_offload(netdev)) return -EOPNOTSUPP; -@@ -3235,7 +3231,7 @@ static void airoha_mac_link_up(struct ph - struct airoha_gdm_dev *dev = container_of(config, struct airoha_gdm_dev, - phylink_config); - struct airoha_gdm_port *port = dev->port; -- struct airoha_qdma *qdma = port->qdma; -+ struct airoha_qdma *qdma = dev->qdma; - struct airoha_eth *eth = qdma->eth; - u32 frag_size_tx, frag_size_rx; - --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -549,6 +549,7 @@ struct airoha_qdma { +@@ -537,12 +537,12 @@ struct airoha_qdma { struct airoha_gdm_dev { struct airoha_gdm_port *port; + struct airoha_qdma *qdma; struct net_device *dev; struct airoha_eth *eth; - -@@ -559,7 +560,6 @@ struct airoha_gdm_dev { }; struct airoha_gdm_port { @@ -428,8 +389,8 @@ Signed-off-by: Lorenzo Bianconi struct airoha_gdm_dev *dev; int id; int nbq; -@@ -695,19 +695,18 @@ static inline bool airoha_qdma_is_lro_qu - return !!(AIROHA_RXQ_LRO_EN_MASK & BIT(qid)); +@@ -666,19 +666,18 @@ static inline bool airoha_is_7583(struct + return eth->soc->version == 0x7583; } -int airoha_get_fe_port(struct airoha_gdm_port *port); @@ -453,7 +414,7 @@ Signed-off-by: Lorenzo Bianconi u32 hash); --- a/drivers/net/ethernet/airoha/airoha_ppe.c +++ b/drivers/net/ethernet/airoha/airoha_ppe.c -@@ -85,9 +85,9 @@ static u32 airoha_ppe_get_timestamp(stru +@@ -84,9 +84,9 @@ static u32 airoha_ppe_get_timestamp(stru AIROHA_FOE_IB1_BIND_TIMESTAMP); } @@ -465,7 +426,7 @@ Signed-off-by: Lorenzo Bianconi struct airoha_eth *eth = qdma->eth; u8 qdma_id = qdma - ð->qdma[0]; u32 fe_cpu_port; -@@ -181,8 +181,8 @@ static void airoha_ppe_hw_init(struct ai +@@ -180,8 +180,8 @@ static void airoha_ppe_hw_init(struct ai if (!port) continue; @@ -476,7 +437,7 @@ Signed-off-by: Lorenzo Bianconi } } } -@@ -1485,11 +1485,12 @@ void airoha_ppe_check_skb(struct airoha_ +@@ -1473,11 +1473,12 @@ void airoha_ppe_check_skb(struct airoha_ airoha_ppe_foe_insert_entry(ppe, skb, hash, rx_wlan); } diff --git a/target/linux/airoha/patches-6.18/920-03-net-airoha-Rely-on-airoha_gdm_dev-pointer-in-airoha_.patch b/target/linux/airoha/patches-6.18/161-03-v7.2-net-airoha-Rely-on-airoha_gdm_dev-pointer-in-airoha_.patch similarity index 77% rename from target/linux/airoha/patches-6.18/920-03-net-airoha-Rely-on-airoha_gdm_dev-pointer-in-airoha_.patch rename to target/linux/airoha/patches-6.18/161-03-v7.2-net-airoha-Rely-on-airoha_gdm_dev-pointer-in-airoha_.patch index 3ae068204b..8aeede07f3 100644 --- a/target/linux/airoha/patches-6.18/920-03-net-airoha-Rely-on-airoha_gdm_dev-pointer-in-airoha_.patch +++ b/target/linux/airoha/patches-6.18/161-03-v7.2-net-airoha-Rely-on-airoha_gdm_dev-pointer-in-airoha_.patch @@ -1,10 +1,7 @@ -From 32bfd008c19f9ad55514181d8cd02e14bf384475 Mon Sep 17 00:00:00 2001 -Message-ID: <32bfd008c19f9ad55514181d8cd02e14bf384475.1779348625.git.lorenzo@kernel.org> -In-Reply-To: -References: +From eca4f59b536780a56bd22db03fe5465e8e978f36 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi -Date: Sat, 13 Dec 2025 10:06:45 +0100 -Subject: [PATCH 03/13] net: airoha: Rely on airoha_gdm_dev pointer in +Date: Wed, 27 May 2026 12:21:17 +0200 +Subject: [PATCH 3/6] net: airoha: Rely on airoha_gdm_dev pointer in airoha_is_lan_gdm_port() Rename airoha_is_lan_gdm_port in airoha_is_lan_gdm_dev. Moreover, rely @@ -15,6 +12,8 @@ the same GDM{3,4} port via an external hw arbiter. Tested-by: Xuegang Lu Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260527-airoha-eth-multi-serdes-preliminary-v1-3-ec6ed73ef7fc@kernel.org +Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/airoha/airoha_eth.c | 6 ++---- drivers/net/ethernet/airoha/airoha_eth.h | 4 +++- @@ -23,7 +22,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -82,12 +82,10 @@ static bool airhoa_is_phy_external(struc +@@ -73,12 +73,10 @@ static void airoha_qdma_irq_disable(stru static void airoha_set_macaddr(struct airoha_gdm_dev *dev, const u8 *addr) { @@ -37,7 +36,7 @@ Signed-off-by: Lorenzo Bianconi val = (addr[0] << 16) | (addr[1] << 8) | addr[2]; airoha_fe_wr(eth, reg, val); -@@ -2038,7 +2036,7 @@ static int airoha_dev_init(struct net_de +@@ -1871,7 +1869,7 @@ static int airoha_dev_init(struct net_de int i; /* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */ @@ -48,7 +47,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -664,8 +664,10 @@ static inline u16 airoha_qdma_get_txq(st +@@ -647,8 +647,10 @@ static inline u16 airoha_qdma_get_txq(st return qid % ARRAY_SIZE(qdma->q_tx); } @@ -62,7 +61,7 @@ Signed-off-by: Lorenzo Bianconi * phy module. --- a/drivers/net/ethernet/airoha/airoha_ppe.c +++ b/drivers/net/ethernet/airoha/airoha_ppe.c -@@ -367,7 +367,7 @@ static int airoha_ppe_foe_entry_prepare( +@@ -362,7 +362,7 @@ static int airoha_ppe_foe_entry_prepare( /* For downlink traffic consume SRAM memory for hw * forwarding descriptors queue. */ diff --git a/target/linux/airoha/patches-6.18/920-04-net-airoha-Move-qos_sq_bmap-in-airoha_gdm_dev-struct.patch b/target/linux/airoha/patches-6.18/161-04-v7.2-net-airoha-Move-qos_sq_bmap-in-airoha_gdm_dev-struct.patch similarity index 82% rename from target/linux/airoha/patches-6.18/920-04-net-airoha-Move-qos_sq_bmap-in-airoha_gdm_dev-struct.patch rename to target/linux/airoha/patches-6.18/161-04-v7.2-net-airoha-Move-qos_sq_bmap-in-airoha_gdm_dev-struct.patch index 7e0077124a..f87c99a35f 100644 --- a/target/linux/airoha/patches-6.18/920-04-net-airoha-Move-qos_sq_bmap-in-airoha_gdm_dev-struct.patch +++ b/target/linux/airoha/patches-6.18/161-04-v7.2-net-airoha-Move-qos_sq_bmap-in-airoha_gdm_dev-struct.patch @@ -1,10 +1,7 @@ -From 634d75285db77f3385aa85a1bf2b185396225100 Mon Sep 17 00:00:00 2001 -Message-ID: <634d75285db77f3385aa85a1bf2b185396225100.1779348625.git.lorenzo@kernel.org> -In-Reply-To: -References: +From 069626af6dfaa26b82119900f4aff1fec38d5983 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi -Date: Fri, 10 Apr 2026 14:35:32 +0200 -Subject: [PATCH 04/13] net: airoha: Move qos_sq_bmap in airoha_gdm_dev struct +Date: Wed, 27 May 2026 12:21:18 +0200 +Subject: [PATCH 4/6] net: airoha: Move qos_sq_bmap in airoha_gdm_dev struct Since now multiple net_devices connected to different QDMA blocks can share the same GDM port, qos_sq_bmap field can be overwritten with the @@ -14,7 +11,10 @@ airoha_gdm_port struct to airoha_gdm_dev one. Add qos_channel_map bitmap in airoha_qdma struct to track if a shared QDMA channel is already in use by another net_device. +Tested-by: Xuegang Lu Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260527-airoha-eth-multi-serdes-preliminary-v1-4-ec6ed73ef7fc@kernel.org +Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/airoha/airoha_eth.c | 58 +++++++++++++++--------- drivers/net/ethernet/airoha/airoha_eth.h | 6 ++- @@ -22,7 +22,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2835,30 +2835,40 @@ static int airoha_qdma_set_tx_rate_limit +@@ -2605,30 +2605,40 @@ static int airoha_qdma_set_tx_rate_limit return 0; } @@ -75,7 +75,7 @@ Signed-off-by: Lorenzo Bianconi err = netif_set_real_num_tx_queues(netdev, num_tx_queues + 1); if (err) { -@@ -2866,13 +2876,17 @@ static int airoha_tc_htb_alloc_leaf_queu +@@ -2636,13 +2646,17 @@ static int airoha_tc_htb_alloc_leaf_queu opt->quantum); NL_SET_ERR_MSG_MOD(opt->extack, "failed setting real_num_tx_queues"); @@ -95,7 +95,7 @@ Signed-off-by: Lorenzo Bianconi } static int airoha_qdma_set_rx_meter(struct airoha_gdm_dev *dev, -@@ -3053,11 +3067,13 @@ static int airoha_dev_setup_tc_block(str +@@ -2823,11 +2837,13 @@ static int airoha_dev_setup_tc_block(str static void airoha_tc_remove_htb_queue(struct net_device *netdev, int queue) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -111,7 +111,7 @@ Signed-off-by: Lorenzo Bianconi } static int airoha_tc_htb_delete_leaf_queue(struct net_device *netdev, -@@ -3065,9 +3081,8 @@ static int airoha_tc_htb_delete_leaf_que +@@ -2835,9 +2851,8 @@ static int airoha_tc_htb_delete_leaf_que { u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -122,7 +122,7 @@ Signed-off-by: Lorenzo Bianconi NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id"); return -EINVAL; } -@@ -3080,10 +3095,9 @@ static int airoha_tc_htb_delete_leaf_que +@@ -2850,10 +2865,9 @@ static int airoha_tc_htb_delete_leaf_que static int airoha_tc_htb_destroy(struct net_device *netdev) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -134,7 +134,7 @@ Signed-off-by: Lorenzo Bianconi airoha_tc_remove_htb_queue(netdev, q); return 0; -@@ -3094,9 +3108,8 @@ static int airoha_tc_get_htb_get_leaf_qu +@@ -2864,9 +2878,8 @@ static int airoha_tc_get_htb_get_leaf_qu { u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -145,7 +145,7 @@ Signed-off-by: Lorenzo Bianconi NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id"); return -EINVAL; } -@@ -3115,6 +3128,7 @@ static int airoha_tc_setup_qdisc_htb(str +@@ -2885,6 +2898,7 @@ static int airoha_tc_setup_qdisc_htb(str case TC_HTB_DESTROY: return airoha_tc_htb_destroy(dev); case TC_HTB_NODE_MODIFY: @@ -155,7 +155,7 @@ Signed-off-by: Lorenzo Bianconi case TC_HTB_LEAF_DEL: --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -545,6 +545,8 @@ struct airoha_qdma { +@@ -533,6 +533,8 @@ struct airoha_qdma { struct airoha_queue q_tx[AIROHA_NUM_TX_RING]; struct airoha_queue q_rx[AIROHA_NUM_RX_RING]; @@ -164,16 +164,16 @@ Signed-off-by: Lorenzo Bianconi }; struct airoha_gdm_dev { -@@ -557,6 +559,8 @@ struct airoha_gdm_dev { - struct phylink *phylink; - struct phylink_config phylink_config; - #endif +@@ -540,6 +542,8 @@ struct airoha_gdm_dev { + struct airoha_qdma *qdma; + struct net_device *dev; + struct airoha_eth *eth; + + DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS); }; struct airoha_gdm_port { -@@ -566,8 +570,6 @@ struct airoha_gdm_port { +@@ -549,8 +553,6 @@ struct airoha_gdm_port { struct airoha_hw_stats stats; diff --git a/target/linux/airoha/patches-6.18/920-05-net-airoha-Move-cpu-fwd-_tx_packets-in-airoha_gdm_de.patch b/target/linux/airoha/patches-6.18/161-05-v7.2-net-airoha-Move-cpu-fwd-_tx_packets-in-airoha_gdm_de.patch similarity index 76% rename from target/linux/airoha/patches-6.18/920-05-net-airoha-Move-cpu-fwd-_tx_packets-in-airoha_gdm_de.patch rename to target/linux/airoha/patches-6.18/161-05-v7.2-net-airoha-Move-cpu-fwd-_tx_packets-in-airoha_gdm_de.patch index 9522e36b71..df6ca1ca1c 100644 --- a/target/linux/airoha/patches-6.18/920-05-net-airoha-Move-cpu-fwd-_tx_packets-in-airoha_gdm_de.patch +++ b/target/linux/airoha/patches-6.18/161-05-v7.2-net-airoha-Move-cpu-fwd-_tx_packets-in-airoha_gdm_de.patch @@ -1,11 +1,8 @@ -From 00272dbf6a52241a21145631f22dc5f03891078b Mon Sep 17 00:00:00 2001 -Message-ID: <00272dbf6a52241a21145631f22dc5f03891078b.1779348625.git.lorenzo@kernel.org> -In-Reply-To: -References: +From 962c17dd287887aa87a6f30d64239d7e1e4e05fa Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi -Date: Fri, 10 Apr 2026 14:47:08 +0200 -Subject: [PATCH 05/13] net: airoha: Move {cpu,fwd}_tx_packets in - airoha_gdm_dev struct +Date: Wed, 27 May 2026 12:21:19 +0200 +Subject: [PATCH 5/6] net: airoha: Move {cpu,fwd}_tx_packets in airoha_gdm_dev + struct Since now multiple net_devices connected to different QDMA blocks can share the same GDM port, cpu_tx_packets and fwd_tx_packets fields can @@ -13,7 +10,10 @@ be overwritten with the value from a different QDMA block. In order to fix the issue move cpu_tx_packets and fwd_tx_packets fields from airoha_gdm_port struct to airoha_gdm_dev one. +Tested-by: Xuegang Lu Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260527-airoha-eth-multi-serdes-preliminary-v1-5-ec6ed73ef7fc@kernel.org +Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/airoha/airoha_eth.c | 16 +++++++--------- drivers/net/ethernet/airoha/airoha_eth.h | 7 +++---- @@ -21,7 +21,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2548,19 +2548,17 @@ static int airoha_qdma_get_tx_ets_stats( +@@ -2318,19 +2318,17 @@ static int airoha_qdma_get_tx_ets_stats( struct tc_ets_qopt_offload *opt) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -50,8 +50,8 @@ Signed-off-by: Lorenzo Bianconi } --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -561,6 +561,9 @@ struct airoha_gdm_dev { - #endif +@@ -544,6 +544,9 @@ struct airoha_gdm_dev { + struct airoha_eth *eth; DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS); + /* qos stats counters */ @@ -60,7 +60,7 @@ Signed-off-by: Lorenzo Bianconi }; struct airoha_gdm_port { -@@ -570,10 +573,6 @@ struct airoha_gdm_port { +@@ -553,10 +556,6 @@ struct airoha_gdm_port { struct airoha_hw_stats stats; diff --git a/target/linux/airoha/patches-6.18/161-06-v7.2-net-airoha-Rename-airoha_set_gdm2_loopback-in-airoha.patch b/target/linux/airoha/patches-6.18/161-06-v7.2-net-airoha-Rename-airoha_set_gdm2_loopback-in-airoha.patch new file mode 100644 index 0000000000..3e84250b0f --- /dev/null +++ b/target/linux/airoha/patches-6.18/161-06-v7.2-net-airoha-Rename-airoha_set_gdm2_loopback-in-airoha.patch @@ -0,0 +1,38 @@ +From 842a7ee50d68d66afef4536bf3abdaaed2e0e5f5 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Wed, 27 May 2026 12:21:20 +0200 +Subject: [PATCH 6/6] net: airoha: Rename airoha_set_gdm2_loopback in + airoha_enable_gdm2_loopback + +This is a preliminary patch in order to allow the user to select if the +configured device will be used as hw lan or wan. +Please not this patch does not introduce any logical changes, just +cosmetic ones. + +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260527-airoha-eth-multi-serdes-preliminary-v1-6-ec6ed73ef7fc@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -1799,7 +1799,7 @@ static int airoha_dev_set_macaddr(struct + return 0; + } + +-static int airoha_set_gdm2_loopback(struct airoha_gdm_dev *dev) ++static int airoha_enable_gdm2_loopback(struct airoha_gdm_dev *dev) + { + struct airoha_gdm_port *port = dev->port; + struct airoha_eth *eth = dev->eth; +@@ -1880,7 +1880,7 @@ static int airoha_dev_init(struct net_de + if (!eth->ports[1]) { + int err; + +- err = airoha_set_gdm2_loopback(dev); ++ err = airoha_enable_gdm2_loopback(dev); + if (err) + return err; + } diff --git a/target/linux/airoha/patches-6.18/163-v7.2-net-airoha-Report-extack-error-to-the-user-if-airoha.patch b/target/linux/airoha/patches-6.18/163-v7.2-net-airoha-Report-extack-error-to-the-user-if-airoha.patch new file mode 100644 index 0000000000..3534bb72e1 --- /dev/null +++ b/target/linux/airoha/patches-6.18/163-v7.2-net-airoha-Report-extack-error-to-the-user-if-airoha.patch @@ -0,0 +1,40 @@ +From 144969cd80c5227c2b19fe5f644d6eebd61be586 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Wed, 3 Jun 2026 12:30:01 +0200 +Subject: [PATCH] net: airoha: Report extack error to the user if + airoha_tc_htb_modify_queue() fails + +Report an extack error message in airoha_tc_htb_modify_queue routine if +airoha_qdma_set_tx_rate_limit() fails. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Alexander Lobakin +Link: https://patch.msgid.link/20260603-airoha_tc_htb_modify_queue-err-message-v1-1-33ec3ab997d9@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -2608,13 +2608,19 @@ static int airoha_tc_htb_modify_queue(st + { + u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; + u32 rate = div_u64(opt->rate, 1000) << 3; /* kbps */ ++ int err; + + if (opt->parent_classid != TC_HTB_CLASSID_ROOT) { + NL_SET_ERR_MSG_MOD(opt->extack, "invalid parent classid"); + return -EINVAL; + } + +- return airoha_qdma_set_tx_rate_limit(dev, channel, rate, opt->quantum); ++ err = airoha_qdma_set_tx_rate_limit(dev, channel, rate, opt->quantum); ++ if (err) ++ NL_SET_ERR_MSG_MOD(opt->extack, ++ "failed configuring htb offload"); ++ ++ return err; + } + + static int airoha_tc_htb_alloc_leaf_queue(struct net_device *netdev, diff --git a/target/linux/airoha/patches-6.18/165-01-v7.2-net-airoha-Remove-private-net_device-pointer-in-airo.patch b/target/linux/airoha/patches-6.18/165-01-v7.2-net-airoha-Remove-private-net_device-pointer-in-airo.patch new file mode 100644 index 0000000000..f4da9bf742 --- /dev/null +++ b/target/linux/airoha/patches-6.18/165-01-v7.2-net-airoha-Remove-private-net_device-pointer-in-airo.patch @@ -0,0 +1,125 @@ +From 4408f520680990042a1e6bfdf3cef217a1abf152 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Wed, 3 Jun 2026 08:00:16 +0200 +Subject: [PATCH 1/5] net: airoha: Remove private net_device pointer in + airoha_gdm_dev struct + +Remove redundant net_device pointer inside airoha_gdm_dev struct and +rely on netdev_from_priv routine instead. Please note this patch does +not introduce any logical change, just code refactoring. + +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260603-airoha-eth-multi-serdes-v9-2-5d476bc2f426@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 23 ++++++++++++++--------- + drivers/net/ethernet/airoha/airoha_eth.h | 1 - + drivers/net/ethernet/airoha/airoha_ppe.c | 2 +- + 3 files changed, 15 insertions(+), 11 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -629,7 +629,7 @@ static int airoha_qdma_rx_process(struct + if (!port->dev) + goto free_frag; + +- netdev = port->dev->dev; ++ netdev = netdev_from_priv(port->dev); + if (!q->skb) { /* first buffer */ + q->skb = napi_build_skb(e->buf - AIROHA_RX_HEADROOM, + q->buf_size); +@@ -853,6 +853,7 @@ static void airoha_qdma_wake_netdev_txqs + for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { + struct airoha_gdm_port *port = eth->ports[i]; + struct airoha_gdm_dev *dev; ++ struct net_device *netdev; + int j; + + if (!port) +@@ -865,11 +866,12 @@ static void airoha_qdma_wake_netdev_txqs + if (dev->qdma != qdma) + continue; + +- for (j = 0; j < dev->dev->num_tx_queues; j++) { ++ netdev = netdev_from_priv(dev); ++ for (j = 0; j < netdev->num_tx_queues; j++) { + if (airoha_qdma_get_txq(qdma, j) != qid) + continue; + +- netif_wake_subqueue(dev->dev, j); ++ netif_wake_subqueue(netdev, j); + } + } + q->txq_stopped = false; +@@ -1870,7 +1872,7 @@ static int airoha_dev_init(struct net_de + + /* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */ + dev->qdma = ð->qdma[!airoha_is_lan_gdm_dev(dev)]; +- dev->dev->irq = dev->qdma->irq_banks[0].irq; ++ netdev->irq = dev->qdma->irq_banks[0].irq; + airoha_set_macaddr(dev, netdev->dev_addr); + + switch (port->id) { +@@ -3047,7 +3049,6 @@ static int airoha_alloc_gdm_device(struc + } + + dev = netdev_priv(netdev); +- dev->dev = netdev; + dev->port = port; + port->dev = dev; + dev->eth = eth; +@@ -3110,7 +3111,7 @@ static int airoha_register_gdm_devices(s + if (!port) + continue; + +- err = register_netdev(port->dev->dev); ++ err = register_netdev(netdev_from_priv(port->dev)); + if (err) + return err; + } +@@ -3225,8 +3226,12 @@ error_napi_stop: + continue; + + dev = port->dev; +- if (dev && dev->dev->reg_state == NETREG_REGISTERED) +- unregister_netdev(dev->dev); ++ if (dev) { ++ struct net_device *netdev = netdev_from_priv(dev); ++ ++ if (netdev->reg_state == NETREG_REGISTERED) ++ unregister_netdev(netdev); ++ } + airoha_metadata_dst_free(port); + } + airoha_hw_cleanup(eth); +@@ -3254,7 +3259,7 @@ static void airoha_remove(struct platfor + + dev = port->dev; + if (dev) +- unregister_netdev(dev->dev); ++ unregister_netdev(netdev_from_priv(dev)); + airoha_metadata_dst_free(port); + } + airoha_hw_cleanup(eth); +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -540,7 +540,6 @@ struct airoha_qdma { + struct airoha_gdm_dev { + struct airoha_gdm_port *port; + struct airoha_qdma *qdma; +- struct net_device *dev; + struct airoha_eth *eth; + + DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS); +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -1475,8 +1475,8 @@ void airoha_ppe_check_skb(struct airoha_ + + void airoha_ppe_init_upd_mem(struct airoha_gdm_dev *dev) + { ++ struct net_device *netdev = netdev_from_priv(dev); + struct airoha_gdm_port *port = dev->port; +- struct net_device *netdev = dev->dev; + struct airoha_eth *eth = dev->eth; + const u8 *addr = netdev->dev_addr; + u32 val; diff --git a/target/linux/airoha/patches-6.18/920-06-net-airoha-Support-multiple-net_devices-for-a-single.patch b/target/linux/airoha/patches-6.18/165-02-v7.2-net-airoha-Support-multiple-net_devices-for-a-single.patch similarity index 73% rename from target/linux/airoha/patches-6.18/920-06-net-airoha-Support-multiple-net_devices-for-a-single.patch rename to target/linux/airoha/patches-6.18/165-02-v7.2-net-airoha-Support-multiple-net_devices-for-a-single.patch index ad848a432a..922d1057f5 100644 --- a/target/linux/airoha/patches-6.18/920-06-net-airoha-Support-multiple-net_devices-for-a-single.patch +++ b/target/linux/airoha/patches-6.18/165-02-v7.2-net-airoha-Support-multiple-net_devices-for-a-single.patch @@ -1,11 +1,8 @@ -From 8eb0a71bfbe92b6fbc668c5d9ebdcbf6523a89ad Mon Sep 17 00:00:00 2001 -Message-ID: <8eb0a71bfbe92b6fbc668c5d9ebdcbf6523a89ad.1779348625.git.lorenzo@kernel.org> -In-Reply-To: -References: +From a9c2ca61fec7706574c009d8f1898ca392368f89 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi -Date: Sat, 1 Nov 2025 11:27:48 +0100 -Subject: [PATCH 06/13] net: airoha: Support multiple net_devices for a single - FE GDM port +Date: Wed, 3 Jun 2026 08:00:17 +0200 +Subject: [PATCH 2/5] net: airoha: Support multiple net_devices for a single FE + GDM port MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -48,15 +45,17 @@ logics for the net_device type connected to GDM3 or GDM4. Tested-by: Xuegang Lu Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260603-airoha-eth-multi-serdes-v9-3-5d476bc2f426@kernel.org +Signed-off-by: Jakub Kicinski --- - drivers/net/ethernet/airoha/airoha_eth.c | 274 +++++++++++++++++------ - drivers/net/ethernet/airoha/airoha_eth.h | 10 +- - drivers/net/ethernet/airoha/airoha_ppe.c | 13 +- - 3 files changed, 228 insertions(+), 69 deletions(-) + drivers/net/ethernet/airoha/airoha_eth.c | 280 +++++++++++++++++------ + drivers/net/ethernet/airoha/airoha_eth.h | 8 +- + drivers/net/ethernet/airoha/airoha_ppe.c | 26 ++- + 3 files changed, 237 insertions(+), 77 deletions(-) --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -115,7 +115,7 @@ static int airoha_set_vip_for_gdm_port(s +@@ -106,7 +106,7 @@ static int airoha_set_vip_for_gdm_port(s struct airoha_eth *eth = dev->eth; u32 vip_port; @@ -65,7 +64,7 @@ Signed-off-by: Lorenzo Bianconi if (enable) { airoha_fe_set(eth, REG_FE_VIP_PORT_EN, vip_port); airoha_fe_set(eth, REG_FE_IFC_PORT_EN, vip_port); -@@ -619,30 +619,26 @@ static int airoha_qdma_fill_rx_queue(str +@@ -566,24 +566,26 @@ static int airoha_qdma_fill_rx_queue(str return nframes; } @@ -80,14 +79,8 @@ Signed-off-by: Lorenzo Bianconi - sport = FIELD_GET(QDMA_ETH_RXMSG_SPORT_MASK, msg1); - switch (sport) { -- case 0x18: -- port = 3; /* GDM4 */ -- break; -- case 0x16: -- port = 2; /* GDM3 */ -- break; - case 0x10 ... 0x14: -- port = 0; /* GDM1 */ +- port = 0; - break; - case 0x2 ... 0x4: - port = sport - 1; @@ -97,7 +90,8 @@ Signed-off-by: Lorenzo Bianconi - } + if (eth->soc->ops.get_dev_from_sport(desc, &p, &d)) + return ERR_PTR(-ENODEV); -+ + +- return port >= ARRAY_SIZE(eth->ports) ? -EINVAL : port; + if (p >= ARRAY_SIZE(eth->ports)) + return ERR_PTR(-ENODEV); + @@ -107,75 +101,57 @@ Signed-off-by: Lorenzo Bianconi + + if (d >= ARRAY_SIZE(port->devs)) + return ERR_PTR(-ENODEV); - -- return port >= ARRAY_SIZE(eth->ports) ? -EINVAL : port; ++ + return port->devs[d] ? port->devs[d] : ERR_PTR(-ENODEV); } - static int airoha_qdma_lro_rx_process(struct airoha_queue *q, -@@ -736,9 +732,8 @@ static int airoha_qdma_rx_process(struct + static int airoha_qdma_rx_process(struct airoha_queue *q, int budget) +@@ -598,9 +600,9 @@ static int airoha_qdma_rx_process(struct struct airoha_queue_entry *e = &q->entry[q->tail]; struct airoha_qdma_desc *desc = &q->desc[q->tail]; u32 hash, reason, msg1, desc_ctrl; - struct airoha_gdm_port *port; -- struct net_device *netdev; -- int data_len, len, p; + struct airoha_gdm_dev *dev; + struct net_device *netdev; +- int data_len, len, p; + int data_len, len; struct page *page; desc_ctrl = le32_to_cpu(READ_ONCE(desc->ctrl)); -@@ -759,15 +754,10 @@ static int airoha_qdma_rx_process(struct +@@ -621,15 +623,11 @@ static int airoha_qdma_rx_process(struct if (!len || data_len < len) goto free_frag; - p = airoha_qdma_get_gdm_port(eth, desc); - if (p < 0 || !eth->ports[p]) -- goto free_frag; -- -- port = eth->ports[p]; -- if (!port->dev) + dev = airoha_qdma_get_gdm_dev(eth, desc); + if (IS_ERR(dev)) goto free_frag; -- netdev = port->dev->dev; +- port = eth->ports[p]; +- if (!port->dev) +- goto free_frag; +- +- netdev = netdev_from_priv(port->dev); ++ netdev = netdev_from_priv(dev); if (!q->skb) { /* first buffer */ q->skb = napi_build_skb(e->buf - AIROHA_RX_HEADROOM, q->buf_size); -@@ -776,14 +766,14 @@ static int airoha_qdma_rx_process(struct - - skb_reserve(q->skb, AIROHA_RX_HEADROOM); - __skb_put(q->skb, len); -- q->skb->dev = netdev; -+ q->skb->dev = dev->dev; - q->skb->ip_summed = CHECKSUM_UNNECESSARY; - skb_record_rx_queue(q->skb, qid); - - if (airoha_qdma_lro_rx_process(q, desc) < 0) - goto free_frag; - -- q->skb->protocol = eth_type_trans(q->skb, netdev); -+ q->skb->protocol = eth_type_trans(q->skb, dev->dev); - skb_mark_for_recycle(q->skb); - } else { /* scattered frame */ - struct skb_shared_info *shinfo = skb_shinfo(q->skb); -@@ -800,7 +790,9 @@ static int airoha_qdma_rx_process(struct - if (FIELD_GET(QDMA_DESC_MORE_MASK, desc_ctrl)) +@@ -659,6 +657,8 @@ static int airoha_qdma_rx_process(struct continue; -- if (netdev_uses_dsa(netdev)) { -+ if (netdev_uses_dsa(dev->dev)) { + if (netdev_uses_dsa(netdev)) { + struct airoha_gdm_port *port = dev->port; + /* PPE module requires untagged packets to work * properly and it provides DSA port index via the * DMA descriptor. Report DSA tag to the DSA stack -@@ -997,24 +989,27 @@ static void airoha_qdma_wake_netdev_txqs +@@ -852,26 +852,29 @@ static void airoha_qdma_wake_netdev_txqs for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; - struct airoha_gdm_dev *dev; +- struct net_device *netdev; - int j; + int d; @@ -187,6 +163,7 @@ Signed-off-by: Lorenzo Bianconi - continue; + for (d = 0; d < ARRAY_SIZE(port->devs); d++) { + struct airoha_gdm_dev *dev = port->devs[d]; ++ struct net_device *netdev; + int j; - if (dev->qdma != qdma) @@ -194,22 +171,24 @@ Signed-off-by: Lorenzo Bianconi + if (!dev) + continue; -- for (j = 0; j < dev->dev->num_tx_queues; j++) { +- netdev = netdev_from_priv(dev); +- for (j = 0; j < netdev->num_tx_queues; j++) { - if (airoha_qdma_get_txq(qdma, j) != qid) + if (dev->qdma != qdma) continue; -- netif_wake_subqueue(dev->dev, j); -+ for (j = 0; j < dev->dev->num_tx_queues; j++) { +- netif_wake_subqueue(netdev, j); ++ netdev = netdev_from_priv(dev); ++ for (j = 0; j < netdev->num_tx_queues; j++) { + if (airoha_qdma_get_txq(qdma, j) != qid) + continue; + -+ netif_wake_subqueue(dev->dev, j); ++ netif_wake_subqueue(netdev, j); + } } } q->txq_stopped = false; -@@ -1903,11 +1898,9 @@ static int airoha_dev_open(struct net_de +@@ -1745,11 +1748,9 @@ static int airoha_dev_open(struct net_de GLOBAL_CFG_RX_DMA_EN_MASK); atomic_inc(&qdma->users); @@ -223,7 +202,7 @@ Signed-off-by: Lorenzo Bianconi airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id), pse_port); -@@ -2002,7 +1995,7 @@ static int airoha_set_gdm2_loopback(stru +@@ -1837,7 +1838,7 @@ static int airoha_enable_gdm2_loopback(s airoha_fe_clear(eth, REG_FE_VIP_PORT_EN, BIT(AIROHA_GDM2_IDX)); airoha_fe_clear(eth, REG_FE_IFC_PORT_EN, BIT(AIROHA_GDM2_IDX)); @@ -232,16 +211,16 @@ Signed-off-by: Lorenzo Bianconi if (src_port < 0) return src_port; -@@ -2019,7 +2012,7 @@ static int airoha_set_gdm2_loopback(stru +@@ -1854,7 +1855,7 @@ static int airoha_enable_gdm2_loopback(s airoha_ppe_set_cpu_port(dev, i, AIROHA_GDM2_IDX); if (port->id == AIROHA_GDM4_IDX && airoha_is_7581(eth)) { -- u32 mask = FC_ID_OF_SRC_PORT_MASK(nbq); +- u32 mask = FC_ID_OF_SRC_PORT_MASK(port->nbq); + u32 mask = FC_ID_OF_SRC_PORT_MASK(dev->nbq); airoha_fe_rmw(eth, REG_SRC_PORT_FC_MAP6, mask, __field_prep(mask, AIROHA_GDM2_IDX)); -@@ -2033,7 +2026,7 @@ static int airoha_dev_init(struct net_de +@@ -1868,7 +1869,7 @@ static int airoha_dev_init(struct net_de struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; struct airoha_eth *eth = dev->eth; @@ -250,7 +229,7 @@ Signed-off-by: Lorenzo Bianconi /* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */ dev->qdma = ð->qdma[!airoha_is_lan_gdm_dev(dev)]; -@@ -2056,8 +2049,8 @@ static int airoha_dev_init(struct net_de +@@ -1891,8 +1892,8 @@ static int airoha_dev_init(struct net_de break; } @@ -261,42 +240,7 @@ Signed-off-by: Lorenzo Bianconi return 0; } -@@ -2222,20 +2215,26 @@ static int airoha_dev_set_features(struc - } else { - for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { - struct airoha_gdm_port *p = eth->ports[i]; -- struct airoha_gdm_dev *d; -+ int j; - - if (!p) - continue; - -- d = p->dev; -- if (d->qdma != qdma) -- continue; -+ for (j = 0; j < ARRAY_SIZE(p->devs); j++) { -+ struct airoha_gdm_dev *d = p->devs[j]; - -- if (d->dev == netdev) -- continue; -+ if (!d) -+ continue; - -- if (d->dev->features & NETIF_F_LRO) -- return 0; -+ if (d->qdma != qdma) -+ continue; -+ -+ if (d->dev == netdev) -+ continue; -+ -+ if (d->dev->features & NETIF_F_LRO) -+ return 0; -+ } - } - airoha_fe_lro_disable(eth, qdma_id); - } -@@ -2286,7 +2285,8 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2058,7 +2059,8 @@ static netdev_tx_t airoha_dev_xmit(struc } fport = airoha_get_fe_port(dev); @@ -306,7 +250,7 @@ Signed-off-by: Lorenzo Bianconi FIELD_PREP(QDMA_ETH_TXMSG_METER_MASK, 0x7f); q = &qdma->q_tx[qid]; -@@ -3222,12 +3222,15 @@ bool airoha_is_valid_gdm_dev(struct airo +@@ -2994,12 +2996,15 @@ bool airoha_is_valid_gdm_dev(struct airo for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; @@ -324,7 +268,7 @@ Signed-off-by: Lorenzo Bianconi } return false; -@@ -3351,10 +3354,11 @@ static int airoha_setup_phylink(struct n +@@ -3007,10 +3012,11 @@ bool airoha_is_valid_gdm_dev(struct airo static int airoha_alloc_gdm_device(struct airoha_eth *eth, struct airoha_gdm_port *port, @@ -338,15 +282,15 @@ Signed-off-by: Lorenzo Bianconi int err; netdev = devm_alloc_etherdev_mqs(eth->dev, sizeof(*dev), -@@ -3372,7 +3376,6 @@ static int airoha_alloc_gdm_device(struc - netdev->hw_features = AIROHA_HW_FEATURES | NETIF_F_LRO; - netdev->features |= AIROHA_HW_FEATURES; - netdev->vlan_features = AIROHA_HW_FEATURES; +@@ -3030,7 +3036,6 @@ static int airoha_alloc_gdm_device(struc + NETIF_F_HW_TC; + netdev->features |= netdev->hw_features; + netdev->vlan_features = netdev->hw_features; - netdev->dev.of_node = np; SET_NETDEV_DEV(netdev, eth->dev); /* reserve hw queues for HTB offloading */ -@@ -3390,11 +3393,25 @@ static int airoha_alloc_gdm_device(struc +@@ -3048,10 +3053,24 @@ static int airoha_alloc_gdm_device(struc netdev->dev_addr); } @@ -364,16 +308,15 @@ Signed-off-by: Lorenzo Bianconi + + netdev->dev.of_node = of_node_get(np); dev = netdev_priv(netdev); - dev->dev = netdev; dev->port = port; - port->dev = dev; dev->eth = eth; + dev->nbq = nbq; + port->devs[index] = dev; - #if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) { -@@ -3412,7 +3429,8 @@ static int airoha_alloc_gdm_port(struct + return 0; + } +@@ -3061,7 +3080,8 @@ static int airoha_alloc_gdm_port(struct { const __be32 *id_ptr = of_get_property(np, "reg", NULL); struct airoha_gdm_port *port; @@ -383,7 +326,7 @@ Signed-off-by: Lorenzo Bianconi u32 id; if (!id_ptr) { -@@ -3440,15 +3458,51 @@ static int airoha_alloc_gdm_port(struct +@@ -3089,15 +3109,51 @@ static int airoha_alloc_gdm_port(struct u64_stats_init(&port->stats.syncp); spin_lock_init(&port->stats.lock); port->id = id; @@ -438,7 +381,7 @@ Signed-off-by: Lorenzo Bianconi } static int airoha_register_gdm_devices(struct airoha_eth *eth) -@@ -3457,14 +3511,22 @@ static int airoha_register_gdm_devices(s +@@ -3106,14 +3162,22 @@ static int airoha_register_gdm_devices(s for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; @@ -448,7 +391,7 @@ Signed-off-by: Lorenzo Bianconi if (!port) continue; -- err = register_netdev(port->dev->dev); +- err = register_netdev(netdev_from_priv(port->dev)); - if (err) - return err; + for (j = 0; j < ARRAY_SIZE(port->devs); j++) { @@ -458,14 +401,14 @@ Signed-off-by: Lorenzo Bianconi + if (!dev) + continue; + -+ err = register_netdev(dev->dev); ++ err = register_netdev(netdev_from_priv(dev)); + if (err) + return err; + } } set_bit(DEV_STATE_REGISTERED, ð->state); -@@ -3571,18 +3633,27 @@ error_napi_stop: +@@ -3220,17 +3284,22 @@ error_napi_stop: for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; @@ -476,30 +419,23 @@ Signed-off-by: Lorenzo Bianconi continue; - dev = port->dev; -- if (dev && dev->dev->reg_state == NETREG_REGISTERED) { +- if (dev) { +- struct net_device *netdev = netdev_from_priv(dev); + for (j = 0; j < ARRAY_SIZE(port->devs); j++) { + struct airoha_gdm_dev *dev = port->devs[j]; + struct net_device *netdev; + + if (!dev) + continue; -+ -+ netdev = dev->dev; -+ if (netdev->reg_state == NETREG_REGISTERED) { - #if defined(CONFIG_PCS_AIROHA) -- if (airhoa_is_phy_external(port)) -- phylink_destroy(dev->phylink); -+ if (airhoa_is_phy_external(port)) -+ phylink_destroy(dev->phylink); - #endif -- unregister_netdev(dev->dev); -+ unregister_netdev(netdev); -+ } + ++ netdev = netdev_from_priv(dev); + if (netdev->reg_state == NETREG_REGISTERED) + unregister_netdev(netdev); + of_node_put(netdev->dev.of_node); } airoha_metadata_dst_free(port); } -@@ -3604,19 +3675,26 @@ static void airoha_remove(struct platfor +@@ -3252,14 +3321,22 @@ static void airoha_remove(struct platfor for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; @@ -509,6 +445,9 @@ Signed-off-by: Lorenzo Bianconi if (!port) continue; +- dev = port->dev; +- if (dev) +- unregister_netdev(netdev_from_priv(dev)); + for (j = 0; j < ARRAY_SIZE(port->devs); j++) { + struct airoha_gdm_dev *dev = port->devs[j]; + struct net_device *netdev; @@ -516,22 +455,14 @@ Signed-off-by: Lorenzo Bianconi + if (!dev) + continue; + - #if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) - phylink_destroy(dev->phylink); - #endif -- -- dev = port->dev; -- if (dev) -- unregister_netdev(dev->dev); -+ netdev = dev->dev; ++ netdev = netdev_from_priv(dev); + unregister_netdev(netdev); + of_node_put(netdev->dev.of_node); + } airoha_metadata_dst_free(port); } airoha_hw_cleanup(eth); -@@ -3678,6 +3756,39 @@ static u32 airoha_en7581_get_vip_port(st +@@ -3322,6 +3399,39 @@ static u32 airoha_en7581_get_vip_port(st return 0; } @@ -569,9 +500,9 @@ Signed-off-by: Lorenzo Bianconi +} + static const char * const an7583_xsi_rsts_names[] = { + "xsi-mac", "hsi0-mac", - "hsi1-mac", -@@ -3726,6 +3837,36 @@ static u32 airoha_an7583_get_vip_port(st +@@ -3371,6 +3481,36 @@ static u32 airoha_an7583_get_vip_port(st return 0; } @@ -608,7 +539,7 @@ Signed-off-by: Lorenzo Bianconi static const struct airoha_eth_soc_data en7581_soc_data = { .version = 0x7581, .xsi_rsts_names = en7581_xsi_rsts_names, -@@ -3734,6 +3875,7 @@ static const struct airoha_eth_soc_data +@@ -3379,6 +3519,7 @@ static const struct airoha_eth_soc_data .ops = { .get_sport = airoha_en7581_get_sport, .get_vip_port = airoha_en7581_get_vip_port, @@ -616,7 +547,7 @@ Signed-off-by: Lorenzo Bianconi }, }; -@@ -3745,6 +3887,7 @@ static const struct airoha_eth_soc_data +@@ -3390,6 +3531,7 @@ static const struct airoha_eth_soc_data .ops = { .get_sport = airoha_an7583_get_sport, .get_vip_port = airoha_an7583_get_vip_port, @@ -634,17 +565,7 @@ Signed-off-by: Lorenzo Bianconi #define AIROHA_MAX_NUM_QDMA 2 #define AIROHA_MAX_NUM_IRQ_BANKS 4 #define AIROHA_MAX_DSA_PORTS 7 -@@ -552,8 +553,8 @@ struct airoha_qdma { - struct airoha_gdm_dev { - struct airoha_gdm_port *port; - struct airoha_qdma *qdma; -- struct net_device *dev; - struct airoha_eth *eth; -+ struct net_device *dev; - - #if defined(CONFIG_PCS_AIROHA) - struct phylink *phylink; -@@ -564,12 +565,13 @@ struct airoha_gdm_dev { +@@ -546,12 +547,13 @@ struct airoha_gdm_dev { /* qos stats counters */ u64 cpu_tx_packets; u64 fwd_tx_packets; @@ -660,7 +581,7 @@ Signed-off-by: Lorenzo Bianconi struct airoha_hw_stats stats; -@@ -605,6 +607,8 @@ struct airoha_eth_soc_data { +@@ -587,6 +589,8 @@ struct airoha_eth_soc_data { struct { int (*get_sport)(struct airoha_gdm_port *port, int nbq); u32 (*get_vip_port)(struct airoha_gdm_port *port, int nbq); @@ -671,7 +592,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_ppe.c +++ b/drivers/net/ethernet/airoha/airoha_ppe.c -@@ -168,9 +168,7 @@ static void airoha_ppe_hw_init(struct ai +@@ -167,9 +167,7 @@ static void airoha_ppe_hw_init(struct ai airoha_fe_clear(eth, REG_PPE_PPE_FLOW_CFG(i), PPE_FLOW_CFG_IP6_6RD_MASK); @@ -682,7 +603,7 @@ Signed-off-by: Lorenzo Bianconi airoha_fe_rmw(eth, REG_PPE_MTU(i, p), FP0_EGRESS_MTU_MASK | FP1_EGRESS_MTU_MASK, -@@ -178,11 +176,27 @@ static void airoha_ppe_hw_init(struct ai +@@ -177,11 +175,27 @@ static void airoha_ppe_hw_init(struct ai AIROHA_MAX_MTU) | FIELD_PREP(FP1_EGRESS_MTU_MASK, AIROHA_MAX_MTU)); diff --git a/target/linux/airoha/patches-6.18/920-07-net-airoha-Do-not-stop-GDM-port-if-it-is-shared.patch b/target/linux/airoha/patches-6.18/165-03-v7.2-net-airoha-Do-not-stop-GDM-port-if-it-is-shared.patch similarity index 80% rename from target/linux/airoha/patches-6.18/920-07-net-airoha-Do-not-stop-GDM-port-if-it-is-shared.patch rename to target/linux/airoha/patches-6.18/165-03-v7.2-net-airoha-Do-not-stop-GDM-port-if-it-is-shared.patch index eafefba314..cc8627fe54 100644 --- a/target/linux/airoha/patches-6.18/920-07-net-airoha-Do-not-stop-GDM-port-if-it-is-shared.patch +++ b/target/linux/airoha/patches-6.18/165-03-v7.2-net-airoha-Do-not-stop-GDM-port-if-it-is-shared.patch @@ -1,10 +1,7 @@ -From de856a5b802cf030c8e242e98df3bc88446a4ea1 Mon Sep 17 00:00:00 2001 -Message-ID: -In-Reply-To: -References: +From 99b9d095d71e5cb84121dacce2ac217aad9b174f Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi -Date: Fri, 20 Mar 2026 11:09:40 +0100 -Subject: [PATCH 07/13] net: airoha: Do not stop GDM port if it is shared +Date: Wed, 3 Jun 2026 08:00:18 +0200 +Subject: [PATCH 3/5] net: airoha: Do not stop GDM port if it is shared Theoretically, in the current codebase, two independent net_devices can be connected to the same GDM port so we need to check the GDM port is not @@ -16,6 +13,8 @@ GDM port. Tested-by: Xuegang Lu Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260603-airoha-eth-multi-serdes-v9-4-5d476bc2f426@kernel.org +Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/airoha/airoha_eth.c | 59 +++++++++++++++++++----- drivers/net/ethernet/airoha/airoha_eth.h | 1 + @@ -23,7 +22,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -1859,8 +1859,8 @@ static int airoha_dev_open(struct net_de +@@ -1723,8 +1723,8 @@ static int airoha_dev_open(struct net_de int err, len = ETH_HLEN + netdev->mtu + ETH_FCS_LEN; struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; @@ -31,9 +30,9 @@ Signed-off-by: Lorenzo Bianconi struct airoha_qdma *qdma = dev->qdma; - u32 pse_port = FE_PSE_PORT_PPE1; - #if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) { -@@ -1888,10 +1888,20 @@ static int airoha_dev_open(struct net_de + netif_tx_start_all_queues(netdev); + err = airoha_set_vip_for_gdm_port(dev, true); +@@ -1738,10 +1738,20 @@ static int airoha_dev_open(struct net_de airoha_fe_clear(qdma->eth, REG_GDM_INGRESS_CFG(port->id), GDM_STAG_EN_MASK); @@ -58,7 +57,7 @@ Signed-off-by: Lorenzo Bianconi airoha_qdma_set(qdma, REG_QDMA_GLOBAL_CFG, GLOBAL_CFG_TX_DMA_EN_MASK | -@@ -1907,6 +1917,30 @@ static int airoha_dev_open(struct net_de +@@ -1757,6 +1767,30 @@ static int airoha_dev_open(struct net_de return 0; } @@ -75,7 +74,7 @@ Signed-off-by: Lorenzo Bianconi + if (!dev) + continue; + -+ netdev = dev->dev; ++ netdev = netdev_from_priv(dev); + if (netif_running(netdev)) + len = max_t(u32, len, netdev->mtu); + } @@ -89,7 +88,7 @@ Signed-off-by: Lorenzo Bianconi static int airoha_dev_stop(struct net_device *netdev) { struct airoha_gdm_dev *dev = netdev_priv(netdev); -@@ -1919,8 +1953,12 @@ static int airoha_dev_stop(struct net_de +@@ -1769,8 +1803,12 @@ static int airoha_dev_stop(struct net_de for (i = 0; i < netdev->num_tx_queues; i++) netdev_tx_reset_subqueue(netdev, i); @@ -104,7 +103,7 @@ Signed-off-by: Lorenzo Bianconi if (atomic_dec_and_test(&qdma->users)) { airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG, -@@ -2082,13 +2120,10 @@ static int airoha_dev_change_mtu(struct +@@ -1925,13 +1963,10 @@ static int airoha_dev_change_mtu(struct { struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; @@ -122,7 +121,7 @@ Signed-off-by: Lorenzo Bianconi } --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -572,6 +572,7 @@ struct airoha_gdm_dev { +@@ -554,6 +554,7 @@ struct airoha_gdm_dev { struct airoha_gdm_port { struct airoha_gdm_dev *devs[AIROHA_MAX_NUM_GDM_DEVS]; int id; diff --git a/target/linux/airoha/patches-6.18/920-08-net-airoha-Introduce-WAN-device-flag.patch b/target/linux/airoha/patches-6.18/165-04-v7.2-net-airoha-Introduce-WAN-device-flag.patch similarity index 82% rename from target/linux/airoha/patches-6.18/920-08-net-airoha-Introduce-WAN-device-flag.patch rename to target/linux/airoha/patches-6.18/165-04-v7.2-net-airoha-Introduce-WAN-device-flag.patch index 9451c6fcee..35e864e30d 100644 --- a/target/linux/airoha/patches-6.18/920-08-net-airoha-Introduce-WAN-device-flag.patch +++ b/target/linux/airoha/patches-6.18/165-04-v7.2-net-airoha-Introduce-WAN-device-flag.patch @@ -1,10 +1,7 @@ -From c4f3077948eda05a6b9d1a11304d82c3e0300151 Mon Sep 17 00:00:00 2001 -Message-ID: -In-Reply-To: -References: +From 7758cb462ff72b10d71e72bca8cf65179a1264e8 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi -Date: Fri, 3 Apr 2026 12:07:27 +0200 -Subject: [PATCH 08/13] net: airoha: Introduce WAN device flag +Date: Wed, 3 Jun 2026 08:00:19 +0200 +Subject: [PATCH 4/5] net: airoha: Introduce WAN device flag Introduce WAN flag to specify if a given device is used to transmit/receive WAN or LAN traffic. Current codebase supports specifying LAN/WAN device @@ -21,22 +18,26 @@ officially supported since PCS/external phy is not merged mainline yet Tested-by: Xuegang Lu Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260603-airoha-eth-multi-serdes-v9-5-5d476bc2f426@kernel.org +Signed-off-by: Jakub Kicinski --- - drivers/net/ethernet/airoha/airoha_eth.c | 72 +++++++++++++++++++----- + drivers/net/ethernet/airoha/airoha_eth.c | 73 +++++++++++++++++++----- drivers/net/ethernet/airoha/airoha_eth.h | 13 ++--- drivers/net/ethernet/airoha/airoha_ppe.c | 2 +- - 3 files changed, 65 insertions(+), 22 deletions(-) + 3 files changed, 66 insertions(+), 22 deletions(-) --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2059,36 +2059,80 @@ static int airoha_set_gdm2_loopback(stru +@@ -1902,36 +1902,81 @@ static int airoha_enable_gdm2_loopback(s return 0; } -static int airoha_dev_init(struct net_device *netdev) +static struct airoha_gdm_dev * +airoha_get_wan_gdm_dev(struct airoha_eth *eth) -+{ + { +- struct airoha_gdm_dev *dev = netdev_priv(netdev); +- struct airoha_gdm_port *port = dev->port; + int i; + + for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { @@ -58,15 +59,14 @@ Signed-off-by: Lorenzo Bianconi +} + +static void airoha_dev_set_qdma(struct airoha_gdm_dev *dev) - { -- struct airoha_gdm_dev *dev = netdev_priv(netdev); -- struct airoha_gdm_port *port = dev->port; ++{ ++ struct net_device *netdev = netdev_from_priv(dev); struct airoha_eth *eth = dev->eth; int ppe_id; /* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */ dev->qdma = ð->qdma[!airoha_is_lan_gdm_dev(dev)]; - dev->dev->irq = dev->qdma->irq_banks[0].irq; + netdev->irq = dev->qdma->irq_banks[0].irq; - airoha_set_macaddr(dev, netdev->dev_addr); + + ppe_id = !airoha_is_lan_gdm_dev(dev) && airoha_ppe_is_enabled(eth, 1); @@ -85,7 +85,7 @@ Signed-off-by: Lorenzo Bianconi - if (!eth->ports[1]) { - int err; - -- err = airoha_set_gdm2_loopback(dev); +- err = airoha_enable_gdm2_loopback(dev); - if (err) - return err; - } @@ -118,7 +118,7 @@ Signed-off-by: Lorenzo Bianconi + (port->id == AIROHA_GDM3_IDX || port->id == AIROHA_GDM4_IDX)) { + int err; + -+ err = airoha_set_gdm2_loopback(dev); ++ err = airoha_enable_gdm2_loopback(dev); + if (err) + return err; + } @@ -127,7 +127,7 @@ Signed-off-by: Lorenzo Bianconi } --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -550,6 +550,10 @@ struct airoha_qdma { +@@ -538,6 +538,10 @@ struct airoha_qdma { DECLARE_BITMAP(qos_channel_map, AIROHA_NUM_QOS_CHANNELS); }; @@ -138,7 +138,7 @@ Signed-off-by: Lorenzo Bianconi struct airoha_gdm_dev { struct airoha_gdm_port *port; struct airoha_qdma *qdma; -@@ -566,6 +570,7 @@ struct airoha_gdm_dev { +@@ -548,6 +552,7 @@ struct airoha_gdm_dev { u64 cpu_tx_packets; u64 fwd_tx_packets; @@ -146,7 +146,7 @@ Signed-off-by: Lorenzo Bianconi int nbq; }; -@@ -672,13 +677,7 @@ static inline u16 airoha_qdma_get_txq(st +@@ -654,13 +659,7 @@ static inline u16 airoha_qdma_get_txq(st static inline bool airoha_is_lan_gdm_dev(struct airoha_gdm_dev *dev) { @@ -163,7 +163,7 @@ Signed-off-by: Lorenzo Bianconi static inline bool airoha_is_7581(struct airoha_eth *eth) --- a/drivers/net/ethernet/airoha/airoha_ppe.c +++ b/drivers/net/ethernet/airoha/airoha_ppe.c -@@ -356,7 +356,7 @@ static int airoha_ppe_foe_entry_prepare( +@@ -355,7 +355,7 @@ static int airoha_ppe_foe_entry_prepare( return -EINVAL; port = dev->port; diff --git a/target/linux/airoha/patches-6.18/920-09-net-airoha-Support-multiple-LAN-WAN-interfaces-for-h.patch b/target/linux/airoha/patches-6.18/165-05-v7.2-net-airoha-Support-multiple-LAN-WAN-interfaces-for-h.patch similarity index 72% rename from target/linux/airoha/patches-6.18/920-09-net-airoha-Support-multiple-LAN-WAN-interfaces-for-h.patch rename to target/linux/airoha/patches-6.18/165-05-v7.2-net-airoha-Support-multiple-LAN-WAN-interfaces-for-h.patch index be9382c9eb..a4041bb3db 100644 --- a/target/linux/airoha/patches-6.18/920-09-net-airoha-Support-multiple-LAN-WAN-interfaces-for-h.patch +++ b/target/linux/airoha/patches-6.18/165-05-v7.2-net-airoha-Support-multiple-LAN-WAN-interfaces-for-h.patch @@ -1,38 +1,42 @@ -From 144f0e6e55896625e3411aad02399a5ebb48d8f9 Mon Sep 17 00:00:00 2001 -Message-ID: <144f0e6e55896625e3411aad02399a5ebb48d8f9.1779348625.git.lorenzo@kernel.org> -In-Reply-To: -References: +From ef2aee987174b51573645b4bdacedf610e89ce1a Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi -Date: Mon, 13 Apr 2026 17:38:51 +0200 -Subject: [PATCH 09/13] net: airoha: Support multiple LAN/WAN interfaces for hw +Date: Wed, 3 Jun 2026 08:00:20 +0200 +Subject: [PATCH 5/5] net: airoha: Support multiple LAN/WAN interfaces for hw MAC address configuration The EN7581 and AN7583 SoCs provide registers to configure hardware LAN/WAN -MAC addresses, used to determine whether received traffic is destined for -this host or should be forwarded to another device. +MAC addresses. These registers are used during FE hw acceleration to +determine whether received traffic is destined to this host (L3 traffic) +or should be switched to another device (L2 traffic). The SoC hardware design assumes all interfaces configured as LAN (or WAN) -share a common upper MAC address, which is programmed into the -REG_FE_{LAN,WAN}_MAC_H register. The lower bytes of 'local' addresses can -be expressed as a range via the REG_FE_MAC_LMIN and REG_FE_MAC_LMAX -registers. +share the MAC address MSBs, which are programmed into the +REG_FE_{LAN,WAN}_MAC_H register. The LSBs of 'local' mac addresses can be +expressed as a range via the REG_FE_MAC_LMIN and REG_FE_MAC_LMAX +registers. In order to properly accelerate the traffic, FE module requires +the user to configure the REG_FE_{LAN,WAN}_MAC_H register respecting this +limitation. Please note a misconfiguration in REG_FE_{LAN,WAN}_MAC_H +will still allow the user to log into the device for debugging. Previously, only a single interface was considered when programming these registers. Extend the logic to derive the correct minimum and maximum values for REG_FE_MAC_LMIN/REG_FE_MAC_LMAX when two or more interfaces are -configured as LAN or WAN. +configured as LAN or WAN. Since this functionality was not available +before this series, no regression is introduced. Tested-by: Madhur Agrawal Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260603-airoha-eth-multi-serdes-v9-6-5d476bc2f426@kernel.org +Signed-off-by: Jakub Kicinski --- - drivers/net/ethernet/airoha/airoha_eth.c | 77 ++++++++++++++++++++---- + drivers/net/ethernet/airoha/airoha_eth.c | 77 +++++++++++++++++++++--- drivers/net/ethernet/airoha/airoha_eth.h | 2 +- drivers/net/ethernet/airoha/airoha_ppe.c | 4 +- - 3 files changed, 68 insertions(+), 15 deletions(-) + 3 files changed, 71 insertions(+), 12 deletions(-) --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -80,20 +80,74 @@ static bool airhoa_is_phy_external(struc +@@ -71,20 +71,76 @@ static void airoha_qdma_irq_disable(stru + airoha_qdma_set_irqmask(irq_bank, index, mask, 0); } - #endif -static void airoha_set_macaddr(struct airoha_gdm_dev *dev, const u8 *addr) +static int airoha_set_macaddr(struct airoha_gdm_dev *dev, const u8 *addr) @@ -66,7 +70,7 @@ Signed-off-by: Lorenzo Bianconi + airoha_is_lan_gdm_dev(dev)) + continue; + -+ netdev = iter_dev->dev; ++ netdev = netdev_from_priv(iter_dev); + if (netdev->reg_state != NETREG_REGISTERED) + continue; + @@ -85,9 +89,11 @@ Signed-off-by: Lorenzo Bianconi + * the same for each net_device with the same LAN/WAN + * configuration. + */ ++ struct net_device *netdev = netdev_from_priv(dev); ++ + dev_warn(eth->dev, + "%s: wrong mac addr, MSBs must be %02x:%02x:%02x\n", -+ dev->dev->name, ref_addr[0], ref_addr[1], ++ netdev->name, ref_addr[0], ref_addr[1], + ref_addr[2]); + dev_warn(eth->dev, "FE hw forwarding won't work properly\n"); + @@ -111,7 +117,7 @@ Signed-off-by: Lorenzo Bianconi } static void airoha_set_gdm_port_fwd_cfg(struct airoha_eth *eth, u32 addr, -@@ -1986,13 +2040,18 @@ static int airoha_dev_stop(struct net_de +@@ -1829,13 +1885,18 @@ static int airoha_dev_stop(struct net_de static int airoha_dev_set_macaddr(struct net_device *netdev, void *p) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -134,7 +140,7 @@ Signed-off-by: Lorenzo Bianconi } --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -713,7 +713,7 @@ void airoha_ppe_check_skb(struct airoha_ +@@ -683,7 +683,7 @@ void airoha_ppe_check_skb(struct airoha_ int airoha_ppe_setup_tc_block_cb(struct airoha_ppe_dev *dev, void *type_data); int airoha_ppe_init(struct airoha_eth *eth); void airoha_ppe_deinit(struct airoha_eth *eth); @@ -145,15 +151,15 @@ Signed-off-by: Lorenzo Bianconi u32 hash); --- a/drivers/net/ethernet/airoha/airoha_ppe.c +++ b/drivers/net/ethernet/airoha/airoha_ppe.c -@@ -1499,12 +1499,10 @@ void airoha_ppe_check_skb(struct airoha_ +@@ -1487,12 +1487,10 @@ void airoha_ppe_check_skb(struct airoha_ airoha_ppe_foe_insert_entry(ppe, skb, hash, rx_wlan); } -void airoha_ppe_init_upd_mem(struct airoha_gdm_dev *dev) +void airoha_ppe_init_upd_mem(struct airoha_gdm_dev *dev, const u8 *addr) { +- struct net_device *netdev = netdev_from_priv(dev); struct airoha_gdm_port *port = dev->port; -- struct net_device *netdev = dev->dev; struct airoha_eth *eth = dev->eth; - const u8 *addr = netdev->dev_addr; u32 val; diff --git a/target/linux/airoha/patches-6.18/920-14-net-airoha-Better-handle-MIB-for-GDM-with-multiple-p.patch b/target/linux/airoha/patches-6.18/166-v7.2-net-airoha-better-handle-MIBs-for-GDM-ports-with-mul.patch similarity index 87% rename from target/linux/airoha/patches-6.18/920-14-net-airoha-Better-handle-MIB-for-GDM-with-multiple-p.patch rename to target/linux/airoha/patches-6.18/166-v7.2-net-airoha-better-handle-MIBs-for-GDM-ports-with-mul.patch index 25db5b6661..474cbe9a1b 100644 --- a/target/linux/airoha/patches-6.18/920-14-net-airoha-Better-handle-MIB-for-GDM-with-multiple-p.patch +++ b/target/linux/airoha/patches-6.18/166-v7.2-net-airoha-better-handle-MIBs-for-GDM-ports-with-mul.patch @@ -1,29 +1,31 @@ -From 9652322e0b47eacfef497828f6476a2a3169fd13 Mon Sep 17 00:00:00 2001 -Message-ID: <9652322e0b47eacfef497828f6476a2a3169fd13.1779351672.git.lorenzo@kernel.org> -From: Christian Marangi -Date: Sat, 17 Jan 2026 14:46:12 +0100 -Subject: [PATCH] net: airoha: Better handle MIB for GDM with multiple port - attached - -In the context of a GDM that can have multiple port attached (GDM3/4) -the HW counter (MIB) are global for the GDM port. This cause duplicated -stats reported to the kernel for the related interface. +From 8f4695fb67b259b2cae0be1eef55859bfc559058 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Thu, 11 Jun 2026 12:43:00 +0200 +Subject: [PATCH] net: airoha: better handle MIBs for GDM ports with multiple + devs attached +In the context of a GDM port that can have multiple net_devices attached +(GDM3 and GDM4), the HW counters (MIBs) are global for the GDM port. +This cause duplicated stats reported to the kernel for the related +net_device. The SoC supports a split MIB feature where each counter is tracked based on the relevant HW channel (NBQ) to account for this scenario and provide a way to select the related counter on accessing the MIB registers. - Enable this feature for GDM3 and GDM4 and configure the relevant HW channel before updating the HW stats to report correct HW counter to the kernel for the related interface. +Move the stats struct from port to dev since HW counter are now specific +to the network device instead of the GDM port. Refactor +airoha_update_hw_stats() to take airoha_eth and airoha_gdm_port +parameters since the function operates on the entire port. -Also move the stats struct from port to dev since HW counter are -now specific to the network interface instead of the GDM port. - -Co-developed-by: Brown Huang -Signed-off-by: Brown Huang +Co-developed-by: Christian Marangi Signed-off-by: Christian Marangi +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260611-airoha-eth-multi-serdes-stats-v1-1-42442ae42064@kernel.org +Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/airoha/airoha_eth.c | 191 +++++++++++++---------- drivers/net/ethernet/airoha/airoha_eth.h | 7 +- @@ -31,9 +33,9 @@ Signed-off-by: Christian Marangi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -612,6 +612,14 @@ static int airoha_fe_init(struct airoha_ - airoha_fe_set(eth, REG_GDM_FWD_CFG(AIROHA_GDM4_IDX), - GDM_PAD_EN_MASK | GDM_STRIP_CRC_MASK); +@@ -556,6 +556,14 @@ static int airoha_fe_init(struct airoha_ + airoha_fe_set(eth, REG_GDM_FWD_CFG(AIROHA_GDM3_IDX), GDM_PAD_EN_MASK); + airoha_fe_set(eth, REG_GDM_FWD_CFG(AIROHA_GDM4_IDX), GDM_PAD_EN_MASK); + /* Enable split for MIB counters for GDM3 and GDM4 */ + airoha_fe_set(eth, REG_FE_GDM_MIB_CFG(AIROHA_GDM3_IDX), @@ -46,7 +48,7 @@ Signed-off-by: Christian Marangi airoha_fe_crsn_qsel_init(eth); airoha_fe_clear(eth, REG_FE_CPORT_CFG, FE_CPORT_QUEUE_XFC_MASK); -@@ -1768,149 +1776,169 @@ static void airoha_qdma_stop_napi(struct +@@ -1629,149 +1637,169 @@ static void airoha_qdma_stop_napi(struct } } @@ -59,14 +61,14 @@ Signed-off-by: Christian Marangi - spin_lock(&port->stats.lock); - u64_stats_update_begin(&port->stats.syncp); -+ u64_stats_update_begin(&dev->stats.syncp); -+ + /* Read relevant MIB for GDM with multiple port attached */ + if (port->id == AIROHA_GDM3_IDX || port->id == AIROHA_GDM4_IDX) + airoha_fe_rmw(eth, REG_FE_GDM_MIB_CFG(port->id), + FE_TX_MIB_ID_MASK | FE_RX_MIB_ID_MASK, + FIELD_PREP(FE_TX_MIB_ID_MASK, dev->nbq) | + FIELD_PREP(FE_RX_MIB_ID_MASK, dev->nbq)); ++ ++ u64_stats_update_begin(&dev->stats.syncp); /* TX */ val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_PKT_CNT_H(port->id)); @@ -245,7 +247,9 @@ Signed-off-by: Christian Marangi + + u64_stats_update_end(&dev->stats.syncp); +} -+ + +- /* reset mib counters */ +- airoha_fe_set(eth, REG_FE_GDM_MIB_CLEAR(port->id), +static void airoha_update_hw_stats(struct airoha_gdm_dev *dev) +{ + struct airoha_gdm_port *port = dev->port; @@ -257,9 +261,7 @@ Signed-off-by: Christian Marangi + if (port->devs[i]) + airoha_dev_get_hw_stats(port->devs[i]); + } - -- /* reset mib counters */ -- airoha_fe_set(eth, REG_FE_GDM_MIB_CLEAR(port->id), ++ + /* Reset MIB counters */ + airoha_fe_set(dev->eth, REG_FE_GDM_MIB_CLEAR(port->id), FE_GDM_MIB_RX_CLEAR_MASK | FE_GDM_MIB_TX_CLEAR_MASK); @@ -269,8 +271,8 @@ Signed-off-by: Christian Marangi + spin_unlock(&port->stats_lock); } - static void airoha_dev_set_mtu(struct net_device *netdev) -@@ -2220,23 +2248,22 @@ static void airoha_dev_get_stats64(struc + static int airoha_dev_open(struct net_device *netdev) +@@ -2046,23 +2074,22 @@ static void airoha_dev_get_stats64(struc struct rtnl_link_stats64 *storage) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -306,7 +308,7 @@ Signed-off-by: Christian Marangi } static int airoha_dev_change_mtu(struct net_device *netdev, int mtu) -@@ -2632,20 +2659,19 @@ static void airoha_ethtool_get_mac_stats +@@ -2313,20 +2340,19 @@ static void airoha_ethtool_get_mac_stats struct ethtool_eth_mac_stats *stats) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -336,7 +338,7 @@ Signed-off-by: Christian Marangi } static const struct ethtool_rmon_hist_range airoha_ethtool_rmon_ranges[] = { -@@ -2665,8 +2691,7 @@ airoha_ethtool_get_rmon_stats(struct net +@@ -2346,8 +2372,7 @@ airoha_ethtool_get_rmon_stats(struct net const struct ethtool_rmon_hist_range **ranges) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -346,7 +348,7 @@ Signed-off-by: Christian Marangi unsigned int start; BUILD_BUG_ON(ARRAY_SIZE(airoha_ethtool_rmon_ranges) != -@@ -2679,7 +2704,7 @@ airoha_ethtool_get_rmon_stats(struct net +@@ -2360,7 +2385,7 @@ airoha_ethtool_get_rmon_stats(struct net do { int i; @@ -355,7 +357,7 @@ Signed-off-by: Christian Marangi stats->fragments = hw_stats->rx_fragment; stats->jabbers = hw_stats->rx_jabber; for (i = 0; i < ARRAY_SIZE(airoha_ethtool_rmon_ranges) - 1; -@@ -2687,7 +2712,7 @@ airoha_ethtool_get_rmon_stats(struct net +@@ -2368,7 +2393,7 @@ airoha_ethtool_get_rmon_stats(struct net stats->hist[i] = hw_stats->rx_len[i]; stats->hist_tx[i] = hw_stats->tx_len[i]; } @@ -363,16 +365,16 @@ Signed-off-by: Christian Marangi + } while (u64_stats_fetch_retry(&dev->stats.syncp, start)); } - static int airoha_ethtool_set_priv_flags(struct net_device *netdev, u32 flags) -@@ -3695,6 +3720,7 @@ static int airoha_alloc_gdm_device(struc + static int airoha_qdma_set_chan_tx_sched(struct net_device *netdev, +@@ -3208,6 +3233,7 @@ static int airoha_alloc_gdm_device(struc netdev->dev.of_node = of_node_get(np); dev = netdev_priv(netdev); + u64_stats_init(&dev->stats.syncp); - dev->dev = netdev; dev->port = port; dev->eth = eth; -@@ -3743,9 +3769,8 @@ static int airoha_alloc_gdm_port(struct + dev->nbq = nbq; +@@ -3247,9 +3273,8 @@ static int airoha_alloc_gdm_port(struct if (!port) return -ENOMEM; @@ -385,7 +387,7 @@ Signed-off-by: Christian Marangi err = airoha_metadata_dst_alloc(port); --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -228,8 +228,6 @@ struct airoha_tx_irq_queue { +@@ -215,8 +215,6 @@ struct airoha_tx_irq_queue { }; struct airoha_hw_stats { @@ -394,7 +396,7 @@ Signed-off-by: Christian Marangi struct u64_stats_sync syncp; /* get_stats64 */ -@@ -573,6 +571,8 @@ struct airoha_gdm_dev { +@@ -554,6 +552,8 @@ struct airoha_gdm_dev { u32 flags; int nbq; @@ -403,7 +405,7 @@ Signed-off-by: Christian Marangi }; struct airoha_gdm_port { -@@ -580,7 +580,8 @@ struct airoha_gdm_port { +@@ -561,7 +561,8 @@ struct airoha_gdm_port { int id; int users; diff --git a/target/linux/airoha/patches-6.18/167-v7.2-net-airoha-use-int-instead-of-atomic_t-for-qdma-user.patch b/target/linux/airoha/patches-6.18/167-v7.2-net-airoha-use-int-instead-of-atomic_t-for-qdma-user.patch new file mode 100644 index 0000000000..46c18073e5 --- /dev/null +++ b/target/linux/airoha/patches-6.18/167-v7.2-net-airoha-use-int-instead-of-atomic_t-for-qdma-user.patch @@ -0,0 +1,48 @@ +From a459b560e58be327689e9bd8c0a6be9a4f163366 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Thu, 11 Jun 2026 23:55:51 +0200 +Subject: [PATCH] net: airoha: use int instead of atomic_t for qdma users + counter + +QDMA users counter is always accessed holding RTNL lock so we do not +require atomic_t for it. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 4 ++-- + drivers/net/ethernet/airoha/airoha_eth.h | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -1840,7 +1840,7 @@ static int airoha_dev_open(struct net_de + airoha_qdma_set(qdma, REG_QDMA_GLOBAL_CFG, + GLOBAL_CFG_TX_DMA_EN_MASK | + GLOBAL_CFG_RX_DMA_EN_MASK); +- atomic_inc(&qdma->users); ++ qdma->users++; + + if (!airoha_is_lan_gdm_dev(dev) && + airoha_ppe_is_enabled(qdma->eth, 1)) +@@ -1894,7 +1894,7 @@ static int airoha_dev_stop(struct net_de + REG_GDM_FWD_CFG(port->id), + FE_PSE_PORT_DROP); + +- if (atomic_dec_and_test(&qdma->users)) { ++ if (!--qdma->users) { + airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG, + GLOBAL_CFG_TX_DMA_EN_MASK | + GLOBAL_CFG_RX_DMA_EN_MASK); +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -524,7 +524,7 @@ struct airoha_qdma { + struct airoha_eth *eth; + void __iomem *regs; + +- atomic_t users; ++ int users; + + struct airoha_irq_bank irq_banks[AIROHA_MAX_NUM_IRQ_BANKS]; + diff --git a/target/linux/airoha/patches-6.18/168-v7.2-net-airoha-move-get_sport-callback-at-the-beginning-.patch b/target/linux/airoha/patches-6.18/168-v7.2-net-airoha-move-get_sport-callback-at-the-beginning-.patch new file mode 100644 index 0000000000..da75698155 --- /dev/null +++ b/target/linux/airoha/patches-6.18/168-v7.2-net-airoha-move-get_sport-callback-at-the-beginning-.patch @@ -0,0 +1,50 @@ +From aeb62be4d3b18b76551bf7806e30d72e5c3bbade Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Mon, 8 Jun 2026 23:24:15 +0200 +Subject: [PATCH] net: airoha: move get_sport() callback at the beginning of + airoha_enable_gdm2_loopback() + +Move the get_sport() callback invocation at the beginning of +airoha_enable_gdm2_loopback() routine in order to avoid leaving the +hardware in a partially configured state if get_sport() fails. +Previously, get_sport() was called after GDM2 forwarding, loopback, +channel, length, VIP and IFC registers had already been programmed. +A failure at that point would return an error leaving GDM2 with +loopback enabled but WAN port, PPE CPU port and flow control mappings +not configured. +Performing the get_sport() lookup before any register write guarantees +the routine either completes the full configuration sequence or exits +with no side effects on the hardware. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260608-airoha_enable_gdm2_loopback-minor-change-v1-1-1787a0f42b31@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -1936,6 +1936,10 @@ static int airoha_enable_gdm2_loopback(s + u32 val, pse_port, chan; + int i, src_port; + ++ src_port = eth->soc->ops.get_sport(port, dev->nbq); ++ if (src_port < 0) ++ return src_port; ++ + airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX), + FE_PSE_PORT_DROP); + airoha_fe_clear(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX), +@@ -1965,10 +1969,6 @@ static int airoha_enable_gdm2_loopback(s + airoha_fe_clear(eth, REG_FE_VIP_PORT_EN, BIT(AIROHA_GDM2_IDX)); + airoha_fe_clear(eth, REG_FE_IFC_PORT_EN, BIT(AIROHA_GDM2_IDX)); + +- src_port = eth->soc->ops.get_sport(port, dev->nbq); +- if (src_port < 0) +- return src_port; +- + airoha_fe_rmw(eth, REG_FE_WAN_PORT, + WAN1_EN_MASK | WAN1_MASK | WAN0_MASK, + FIELD_PREP(WAN0_MASK, src_port)); diff --git a/target/linux/airoha/patches-6.18/169-v7.2-net-airoha-simplify-WAN-device-check-in-airoha_dev_i.patch b/target/linux/airoha/patches-6.18/169-v7.2-net-airoha-simplify-WAN-device-check-in-airoha_dev_i.patch new file mode 100644 index 0000000000..e2ce9978b8 --- /dev/null +++ b/target/linux/airoha/patches-6.18/169-v7.2-net-airoha-simplify-WAN-device-check-in-airoha_dev_i.patch @@ -0,0 +1,44 @@ +From 9912dfa2d46aef4cd708246aa6b39b49213f5e62 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Wed, 10 Jun 2026 15:25:13 +0200 +Subject: [PATCH] net: airoha: simplify WAN device check in airoha_dev_init() + +airoha_register_gdm_devices() iterates eth->ports[] in order, so GDM2's +netdev is always registered before GDM3/GDM4. This means the explicit +check for eth->ports[1] && eth->ports[1]->devs[0] is a redundant +special-case of what airoha_get_wan_gdm_dev() already covers, since +GDM2 is always marked as WAN during its own ndo_init. +Remove the redundant check and rely solely on airoha_get_wan_gdm_dev() +which handles both the GDM2-present and GDM2-absent cases. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Alexander Lobakin +Link: https://patch.msgid.link/20260610-airoha-eth-simplify-dev-init-v2-1-8f244e69b0d4@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 12 ++---------- + 1 file changed, 2 insertions(+), 10 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -2035,18 +2035,10 @@ static int airoha_dev_init(struct net_de + + switch (port->id) { + case AIROHA_GDM3_IDX: +- case AIROHA_GDM4_IDX: { +- struct airoha_eth *eth = dev->eth; +- +- /* GDM2 supports a single net_device */ +- if (eth->ports[1] && eth->ports[1]->devs[0]) +- break; +- +- if (airoha_get_wan_gdm_dev(eth)) ++ case AIROHA_GDM4_IDX: ++ if (airoha_get_wan_gdm_dev(dev->eth)) + break; +- + fallthrough; +- } + case AIROHA_GDM2_IDX: + /* GDM2 is always used as wan */ + dev->flags |= AIROHA_PRIV_F_WAN; diff --git a/target/linux/airoha/patches-6.18/170-v7.2-net-airoha-Fix-register-index-for-Tx-fwd-counter-con.patch b/target/linux/airoha/patches-6.18/170-v7.2-net-airoha-Fix-register-index-for-Tx-fwd-counter-con.patch new file mode 100644 index 0000000000..3059178661 --- /dev/null +++ b/target/linux/airoha/patches-6.18/170-v7.2-net-airoha-Fix-register-index-for-Tx-fwd-counter-con.patch @@ -0,0 +1,37 @@ +From 1402ecccf5630a0b7fa4749d7d2e72abc3f3d73d Mon Sep 17 00:00:00 2001 +Message-ID: <1402ecccf5630a0b7fa4749d7d2e72abc3f3d73d.1782312403.git.lorenzo@kernel.org> +From: "Wayen.Yan" +Date: Fri, 12 Jun 2026 07:09:13 +0800 +Subject: [PATCH 1/2] net: airoha: Fix register index for Tx-fwd counter + configuration + +In airoha_qdma_init_qos_stats(), the Tx-fwd counter configuration +register uses the same index (i << 1) as the Tx-cpu counter, which +overwrites the Tx-cpu configuration. The Tx-fwd counter value register +correctly uses (i << 1) + 1, so the configuration register should use +the same index. + +Fix the REG_CNTR_CFG index from (i << 1) to ((i << 1) + 1) so that +the Tx-fwd counter is properly configured instead of clobbering the +Tx-cpu counter config. + +Fixes: 20bf7d07c956 ("net: airoha: Add sched ETS offload support") +Signed-off-by: Wayen.Yan +Acked-by: Lorenzo Bianconi +Link: https://patch.msgid.link/6a2b40e7.4dd82583.3a5c46.e566@mx.google.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -1331,7 +1331,7 @@ static void airoha_qdma_init_qos_stats(s + FIELD_PREP(CNTR_CHAN_MASK, i)); + /* Tx-fwd transferred count */ + airoha_qdma_wr(qdma, REG_CNTR_VAL((i << 1) + 1), 0); +- airoha_qdma_wr(qdma, REG_CNTR_CFG(i << 1), ++ airoha_qdma_wr(qdma, REG_CNTR_CFG((i << 1) + 1), + CNTR_EN_MASK | CNTR_ALL_QUEUE_EN_MASK | + CNTR_ALL_DSCP_RING_EN_MASK | + FIELD_PREP(CNTR_SRC_MASK, 1) | diff --git a/target/linux/airoha/patches-6.18/171-v7.2-net-airoha-Fix-debugfs-new-tuple-display-for-IPv4-RO.patch b/target/linux/airoha/patches-6.18/171-v7.2-net-airoha-Fix-debugfs-new-tuple-display-for-IPv4-RO.patch new file mode 100644 index 0000000000..3a487a44c4 --- /dev/null +++ b/target/linux/airoha/patches-6.18/171-v7.2-net-airoha-Fix-debugfs-new-tuple-display-for-IPv4-RO.patch @@ -0,0 +1,44 @@ +From 1c3a77471afbb3981af28f7f7c8b2487558e4b00 Mon Sep 17 00:00:00 2001 +Message-ID: <1c3a77471afbb3981af28f7f7c8b2487558e4b00.1782312403.git.lorenzo@kernel.org> +In-Reply-To: <1402ecccf5630a0b7fa4749d7d2e72abc3f3d73d.1782312403.git.lorenzo@kernel.org> +References: <1402ecccf5630a0b7fa4749d7d2e72abc3f3d73d.1782312403.git.lorenzo@kernel.org> +From: "Wayen.Yan" +Date: Fri, 12 Jun 2026 07:09:56 +0800 +Subject: [PATCH 2/2] net: airoha: Fix debugfs new-tuple display for IPv4 ROUTE + entries +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In airoha_ppe_debugfs_foe_show(), the second switch statement falls +through from PPE_PKT_TYPE_IPV4_HNAPT/DSLITE to PPE_PKT_TYPE_IPV4_ROUTE, +accessing hwe->ipv4.new_tuple for all three types. However, IPv4 ROUTE +(3-tuple) entries do not contain a valid new_tuple — this field is only +meaningful for NATted flows (HNAPT/DSLITE). For ROUTE entries, the +memory at the new_tuple offset holds routing information, not NAT data, +so displaying "new=" produces garbage output. + +Display new_tuple only for HNAPT and DSLITE, and let IPV4_ROUTE fall +through to the default case. + +Fixes: 3fe15c640f38 ("net: airoha: Introduce PPE debugfs support") +Link: https://lore.kernel.org/6a2b40ea.4dd82583.3a5c46.e5a2@mx.google.com +Signed-off-by: Wayen.Yan +Acked-by: Lorenzo Bianconi +Link: https://patch.msgid.link/6a2be54b.ef98c1b2.3c3224.2ed8@mx.google.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_ppe_debugfs.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_ppe_debugfs.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe_debugfs.c +@@ -121,8 +121,6 @@ static int airoha_ppe_debugfs_foe_show(s + case PPE_PKT_TYPE_IPV4_DSLITE: + src_port = &hwe->ipv4.new_tuple.src_port; + dest_port = &hwe->ipv4.new_tuple.dest_port; +- fallthrough; +- case PPE_PKT_TYPE_IPV4_ROUTE: + src_addr = &hwe->ipv4.new_tuple.src_ip; + dest_addr = &hwe->ipv4.new_tuple.dest_ip; + seq_puts(m, " new="); diff --git a/target/linux/airoha/patches-6.18/172-v7.2-net-airoha-fix-foe_check_time-allocation-size.patch b/target/linux/airoha/patches-6.18/172-v7.2-net-airoha-fix-foe_check_time-allocation-size.patch new file mode 100644 index 0000000000..9851f30434 --- /dev/null +++ b/target/linux/airoha/patches-6.18/172-v7.2-net-airoha-fix-foe_check_time-allocation-size.patch @@ -0,0 +1,34 @@ +From 5c121ee635680c93d7074becf14cfbaac140f80d Mon Sep 17 00:00:00 2001 +Message-ID: <5c121ee635680c93d7074becf14cfbaac140f80d.1782312136.git.lorenzo@kernel.org> +From: Wayen Yan +Date: Tue, 16 Jun 2026 19:52:36 +0800 +Subject: [PATCH] net: airoha: fix foe_check_time allocation size + +foe_check_time is declared as u16 pointer but was allocated with +only ppe_num_entries bytes instead of ppe_num_entries * sizeof(u16). + +When airoha_ppe_foe_verify_entry() is called with hash >= ppe_num_entries/2, +it writes beyond the allocated buffer, causing heap buffer overflow and +potential kernel crash. + +Fixes: 6d5b601d52a2 ("net: airoha: ppe: Dynamically allocate foe_check_time array in airoha_ppe struct") +Signed-off-by: Wayen Yan +Acked-by: Lorenzo Bianconi +Link: https://patch.msgid.link/178161119471.2163752.14373384830691569758@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_ppe.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -1601,7 +1601,8 @@ int airoha_ppe_init(struct airoha_eth *e + return -ENOMEM; + } + +- ppe->foe_check_time = devm_kzalloc(eth->dev, ppe_num_entries, ++ ppe->foe_check_time = devm_kzalloc(eth->dev, ++ ppe_num_entries * sizeof(*ppe->foe_check_time), + GFP_KERNEL); + if (!ppe->foe_check_time) + return -ENOMEM; diff --git a/target/linux/airoha/patches-6.18/173-v7.2-net-airoha-Fix-non-standard-return-value-in-airoha_p.patch b/target/linux/airoha/patches-6.18/173-v7.2-net-airoha-Fix-non-standard-return-value-in-airoha_p.patch new file mode 100644 index 0000000000..e48937d2b4 --- /dev/null +++ b/target/linux/airoha/patches-6.18/173-v7.2-net-airoha-Fix-non-standard-return-value-in-airoha_p.patch @@ -0,0 +1,31 @@ +From 05173fa30add3787e7ab2e735c4ee00431994259 Mon Sep 17 00:00:00 2001 +Message-ID: <05173fa30add3787e7ab2e735c4ee00431994259.1782312341.git.lorenzo@kernel.org> +From: "Wayen.Yan" +Date: Sat, 13 Jun 2026 08:22:31 +0800 +Subject: [PATCH] net: airoha: Fix non-standard return value in + airoha_ppe_get_wdma_info() + +airoha_ppe_get_wdma_info() returns -1 when the last path in the +forwarding path stack is not of type DEV_PATH_MTK_WDMA. This is not +a standard kernel error code. Replace it with -EINVAL since the +input path type is invalid from the caller's perspective. + +Signed-off-by: Wayen.Yan +Acked-by: Lorenzo Bianconi +Link: https://patch.msgid.link/6a2ca3d9.ad59c0a6.147df9.2a62@mx.google.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_ppe.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -277,7 +277,7 @@ static int airoha_ppe_get_wdma_info(stru + + path = &stack.path[stack.num_paths - 1]; + if (path->type != DEV_PATH_MTK_WDMA) +- return -1; ++ return -EINVAL; + + info->idx = path->mtk_wdma.wdma_idx; + info->bss = path->mtk_wdma.bss; diff --git a/target/linux/airoha/patches-6.18/174-v7.2-net-airoha-Fix-skb-priority-underflow-in-airoha_dev_.patch b/target/linux/airoha/patches-6.18/174-v7.2-net-airoha-Fix-skb-priority-underflow-in-airoha_dev_.patch new file mode 100644 index 0000000000..4ec30e3850 --- /dev/null +++ b/target/linux/airoha/patches-6.18/174-v7.2-net-airoha-Fix-skb-priority-underflow-in-airoha_dev_.patch @@ -0,0 +1,52 @@ +From 86e51aa24686cc95bb35613059e8b94b9b81e3f0 Mon Sep 17 00:00:00 2001 +Message-ID: <86e51aa24686cc95bb35613059e8b94b9b81e3f0.1782312099.git.lorenzo@kernel.org> +From: Wayen Yan +Date: Sat, 20 Jun 2026 16:17:44 +0800 +Subject: [PATCH] net: airoha: Fix skb->priority underflow in + airoha_dev_select_queue() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In airoha_dev_select_queue(), the expression: + + queue = (skb->priority - 1) % AIROHA_NUM_QOS_QUEUES; + +implicitly converts to unsigned arithmetic: when skb->priority is 0 +(the default for unclassified traffic), (0u - 1u) wraps to UINT_MAX, +and UINT_MAX % 8 = 7, routing default best-effort packets to the +highest-priority QoS queue. This causes QoS inversion where the +majority of traffic on a PON gateway starves actual high-priority +flows (VoIP, gaming, etc.). + +The "- 1" offset was a leftover from the ETS offload implementation +that has since been removed. The correct mapping is a direct modulo: + + queue = skb->priority % AIROHA_NUM_QOS_QUEUES; + +This maps priority 0 → queue 0 (lowest), priority 7 → queue 7 +(highest), with higher priorities wrapping around. This is the +standard Linux sk_prio → HW queue mapping used by other drivers. + +Fixes: 2b288b81560b ("net: airoha: Introduce ndo_select_queue callback") +Link: https://lore.kernel.org/netdev/178185573207.2378135.3729126358670287878@gmail.com/ +Acked-by: Lorenzo Bianconi +Reviewed-by: Joe Damato +Signed-off-by: Wayen Yan +Link: https://patch.msgid.link/178194366700.2485734.5368768965976693502@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -2110,7 +2110,7 @@ static u16 airoha_dev_select_queue(struc + */ + channel = netdev_uses_dsa(netdev) ? skb_get_queue_mapping(skb) : port->id; + channel = channel % AIROHA_NUM_QOS_CHANNELS; +- queue = (skb->priority - 1) % AIROHA_NUM_QOS_QUEUES; /* QoS queue */ ++ queue = skb->priority % AIROHA_NUM_QOS_QUEUES; + queue = channel * AIROHA_NUM_QOS_QUEUES + queue; + + return queue < netdev->num_tx_queues ? queue : 0; diff --git a/target/linux/airoha/patches-6.18/175-v7.2-net-airoha-Fix-TX-scheduler-queue-mask-loop-upper-bo.patch b/target/linux/airoha/patches-6.18/175-v7.2-net-airoha-Fix-TX-scheduler-queue-mask-loop-upper-bo.patch new file mode 100644 index 0000000000..fcf47bcfe3 --- /dev/null +++ b/target/linux/airoha/patches-6.18/175-v7.2-net-airoha-Fix-TX-scheduler-queue-mask-loop-upper-bo.patch @@ -0,0 +1,50 @@ +From 245043dfc2101e7dc6268bf123b75305a91e4e00 Mon Sep 17 00:00:00 2001 +Message-ID: <245043dfc2101e7dc6268bf123b75305a91e4e00.1782312080.git.lorenzo@kernel.org> +From: Wayen Yan +Date: Fri, 19 Jun 2026 21:12:06 +0800 +Subject: [PATCH] net: airoha: Fix TX scheduler queue mask loop upper bound +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In airoha_qdma_set_chan_tx_sched(), the loop clearing queue mask was +using AIROHA_NUM_TX_RING (32) instead of AIROHA_NUM_QOS_QUEUES (8). + +Each channel has 8 queues, and TXQ_DISABLE_CHAN_QUEUE_MASK(channel, i) +computes BIT(i + (channel * 8)). With i ranging 0..31, this causes: +- channel 0: clears bit 0..31 (all 4 channels) instead of 0..7 +- channel 1: clears bit 8..31 (channels 1-3) instead of 8..15 +- channel 2: clears bit 16..31 (channels 2-3) instead of 16..23 +- channel 3: clears bit 24..31 (channel 3 only) - correct by accident + +While BIT(32+) on arm64 produces 64-bit values truncated to 0 in u32 +mask parameter, the loop still incorrectly clears queues within the +same channel beyond queue 7. + +Even though this is functionally harmless (the register resets to 0 +and is only ever cleared, never set — so clearing extra bits is a +no-op), the loop bound is semantically wrong and should be fixed for +correctness and clarity. + +Fix by using AIROHA_NUM_QOS_QUEUES (8) as the loop upper bound. + +Fixes: ef1ca9271313 ("net: airoha: Add sched HTB offload support") +Acked-by: Lorenzo Bianconi +Signed-off-by: Wayen Yan +Link: https://patch.msgid.link/178187479434.2400840.1312143943526335838@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -2395,7 +2395,7 @@ static int airoha_qdma_set_chan_tx_sched + struct airoha_gdm_dev *dev = netdev_priv(netdev); + int i; + +- for (i = 0; i < AIROHA_NUM_TX_RING; i++) ++ for (i = 0; i < AIROHA_NUM_QOS_QUEUES; i++) + airoha_qdma_clear(dev->qdma, REG_QUEUE_CLOSE_CFG(channel), + TXQ_DISABLE_CHAN_QUEUE_MASK(channel, i)); + diff --git a/target/linux/airoha/patches-6.18/176-v7.2-net-airoha-Fix-typos-in-comments-and-Kconfig.patch b/target/linux/airoha/patches-6.18/176-v7.2-net-airoha-Fix-typos-in-comments-and-Kconfig.patch new file mode 100644 index 0000000000..3b10867ea2 --- /dev/null +++ b/target/linux/airoha/patches-6.18/176-v7.2-net-airoha-Fix-typos-in-comments-and-Kconfig.patch @@ -0,0 +1,68 @@ +From a061dfb063fa03ed09cf21145ffff247cf94721a Mon Sep 17 00:00:00 2001 +Message-ID: +In-Reply-To: <05173fa30add3787e7ab2e735c4ee00431994259.1782312317.git.lorenzo@kernel.org> +References: <05173fa30add3787e7ab2e735c4ee00431994259.1782312317.git.lorenzo@kernel.org> +From: "Wayen.Yan" +Date: Sat, 13 Jun 2026 08:41:16 +0800 +Subject: [PATCH 2/2] net: airoha: Fix typos in comments and Kconfig + +Fix several typos found during code review: +- Kconfig: "Aiorha" -> "Airoha" in NET_AIROHA_FLOW_STATS help text +- Comment: "CMD1" -> "CDM1" (Central DMA, not Command) +- Comments: "GMD1/2/3/4" -> "GDM1/2/3/4" (Gigabit DMA, not GMD) + +These are pure comment and documentation fixes with no functional impact. + +Signed-off-by: Wayen.Yan +Acked-by: Lorenzo Bianconi +Link: https://patch.msgid.link/6a2ca74a.c5b1db4e.21a698.01e7@mx.google.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/Kconfig | 2 +- + drivers/net/ethernet/airoha/airoha_eth.c | 10 +++++----- + 2 files changed, 6 insertions(+), 6 deletions(-) + +--- a/drivers/net/ethernet/airoha/Kconfig ++++ b/drivers/net/ethernet/airoha/Kconfig +@@ -29,6 +29,6 @@ config NET_AIROHA_FLOW_STATS + bool "Airoha flow stats" + depends on NET_AIROHA && NET_AIROHA_NPU + help +- Enable Aiorha flowtable statistic counters. ++ Enable Airoha flowtable statistic counters. + + endif #NET_VENDOR_AIROHA +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -344,18 +344,18 @@ static void airoha_fe_pse_ports_init(str + FIELD_PREP(PSE_ALLRSV_MASK, all_rsv)); + } + +- /* CMD1 */ ++ /* CDM1 */ + for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_CDM1]; q++) + airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_CDM1, q, + PSE_QUEUE_RSV_PAGES); +- /* GMD1 */ ++ /* GDM1 */ + for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_GDM1]; q++) + airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_GDM1, q, + PSE_QUEUE_RSV_PAGES); +- /* GMD2 */ ++ /* GDM2 */ + for (q = 6; q < pse_port_num_queues[FE_PSE_PORT_GDM2]; q++) + airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_GDM2, q, 0); +- /* GMD3 */ ++ /* GDM3 */ + for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_GDM3]; q++) + airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_GDM3, q, + PSE_QUEUE_RSV_PAGES); +@@ -390,7 +390,7 @@ static void airoha_fe_pse_ports_init(str + q, 0); + } + } +- /* GMD4 */ ++ /* GDM4 */ + for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_GDM4]; q++) + airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_GDM4, q, + PSE_QUEUE_RSV_PAGES); diff --git a/target/linux/airoha/patches-6.18/177-v7.2-net-airoha-Fix-off-by-one-in-airoha_tc_remove_htb_qu.patch b/target/linux/airoha/patches-6.18/177-v7.2-net-airoha-Fix-off-by-one-in-airoha_tc_remove_htb_qu.patch new file mode 100644 index 0000000000..821fd6a930 --- /dev/null +++ b/target/linux/airoha/patches-6.18/177-v7.2-net-airoha-Fix-off-by-one-in-airoha_tc_remove_htb_qu.patch @@ -0,0 +1,34 @@ +From bfcce49c4aaab9339ef7b9a7fa4d8ac5a19cc820 Mon Sep 17 00:00:00 2001 +Message-ID: +From: Lorenzo Bianconi +Date: Fri, 19 Jun 2026 13:37:13 +0200 +Subject: [PATCH 1/2] net: airoha: Fix off-by-one in + airoha_tc_remove_htb_queue() + +airoha_tc_htb_alloc_leaf_queue() computes the HTB QoS channel index +as opt->classid % AIROHA_NUM_QOS_CHANNELS and stores it in qos_sq_bmap. +However, airoha_tc_remove_htb_queue() clears the HTB configuration +using queue + 1 as the channel index, causing an off-by-one error. +Use queue directly as the QoS channel index to match the allocation +logic. + +Fixes: ef1ca9271313b ("net: airoha: Add sched HTB offload support") +Reviewed-by: Simon Horman +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260619-airoha-qos-fixes-v2-1-5c43485038f9@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -3006,7 +3006,7 @@ static void airoha_tc_remove_htb_queue(s + struct airoha_qdma *qdma = dev->qdma; + + netif_set_real_num_tx_queues(netdev, netdev->real_num_tx_queues - 1); +- airoha_qdma_set_tx_rate_limit(netdev, queue + 1, 0, 0); ++ airoha_qdma_set_tx_rate_limit(netdev, queue, 0, 0); + + clear_bit(queue, qdma->qos_channel_map); + clear_bit(queue, dev->qos_sq_bmap); diff --git a/target/linux/airoha/patches-6.18/178-v7.2-net-airoha-fix-netif_set_real_num_tx_queues-for-spar.patch b/target/linux/airoha/patches-6.18/178-v7.2-net-airoha-fix-netif_set_real_num_tx_queues-for-spar.patch new file mode 100644 index 0000000000..532a5851a3 --- /dev/null +++ b/target/linux/airoha/patches-6.18/178-v7.2-net-airoha-fix-netif_set_real_num_tx_queues-for-spar.patch @@ -0,0 +1,84 @@ +From 788663dd28e424639318842ba5ae290672528609 Mon Sep 17 00:00:00 2001 +Message-ID: <788663dd28e424639318842ba5ae290672528609.1782366471.git.lorenzo@kernel.org> +In-Reply-To: +References: +From: Lorenzo Bianconi +Date: Fri, 19 Jun 2026 13:37:14 +0200 +Subject: [PATCH 2/2] net: airoha: fix netif_set_real_num_tx_queues for sparse + QoS channels + +airoha_tc_htb_alloc_leaf_queue() assigns queue IDs based on the channel +index (opt->qid = AIROHA_NUM_TX_RING + channel), but updates +real_num_tx_queues with a simple increment (num_tx_queues + 1). When QoS +channels are allocated sparsely (e.g., channels 0 and 3 without 1 and +2), the returned qid can exceed real_num_tx_queues, causing out-of-bounds +accesses in the networking stack. +For example, allocating channel 0 then channel 3 results in +real_num_tx_queues = 34 but qid = 35, which is out of range [0, 34). +Fix this by computing real_num_tx_queues based on the highest active +channel index rather than using a simple counter, in both the allocation +and deletion paths. + +Fixes: ef1ca9271313b ("net: airoha: Add sched HTB offload support") +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260619-airoha-qos-fixes-v2-2-5c43485038f9@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 25 +++++++++++++++--------- + 1 file changed, 16 insertions(+), 9 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -2789,7 +2789,7 @@ static int airoha_tc_htb_alloc_leaf_queu + struct tc_htb_qopt_offload *opt) + { + u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; +- int err, num_tx_queues = netdev->real_num_tx_queues; ++ int err, num_tx_queues = AIROHA_NUM_TX_RING + channel + 1; + struct airoha_gdm_dev *dev = netdev_priv(netdev); + struct airoha_qdma *qdma = dev->qdma; + +@@ -2806,13 +2806,15 @@ static int airoha_tc_htb_alloc_leaf_queu + if (err) + goto error; + +- err = netif_set_real_num_tx_queues(netdev, num_tx_queues + 1); +- if (err) { +- airoha_qdma_set_tx_rate_limit(netdev, channel, 0, +- opt->quantum); +- NL_SET_ERR_MSG_MOD(opt->extack, +- "failed setting real_num_tx_queues"); +- goto error; ++ if (num_tx_queues > netdev->real_num_tx_queues) { ++ err = netif_set_real_num_tx_queues(netdev, num_tx_queues); ++ if (err) { ++ airoha_qdma_set_tx_rate_limit(netdev, channel, 0, ++ opt->quantum); ++ NL_SET_ERR_MSG_MOD(opt->extack, ++ "failed setting real_num_tx_queues"); ++ goto error; ++ } + } + + set_bit(channel, dev->qos_sq_bmap); +@@ -3003,13 +3005,18 @@ static int airoha_dev_setup_tc_block(str + static void airoha_tc_remove_htb_queue(struct net_device *netdev, int queue) + { + struct airoha_gdm_dev *dev = netdev_priv(netdev); ++ int num_tx_queues = AIROHA_NUM_TX_RING; + struct airoha_qdma *qdma = dev->qdma; + +- netif_set_real_num_tx_queues(netdev, netdev->real_num_tx_queues - 1); + airoha_qdma_set_tx_rate_limit(netdev, queue, 0, 0); + + clear_bit(queue, qdma->qos_channel_map); + clear_bit(queue, dev->qos_sq_bmap); ++ ++ if (!bitmap_empty(dev->qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS)) ++ num_tx_queues += find_last_bit(dev->qos_sq_bmap, ++ AIROHA_NUM_QOS_CHANNELS) + 1; ++ netif_set_real_num_tx_queues(netdev, num_tx_queues); + } + + static int airoha_tc_htb_delete_leaf_queue(struct net_device *netdev, diff --git a/target/linux/airoha/patches-6.18/310-02-net-airoha-deassert-XSI-line-on-hw-init.patch b/target/linux/airoha/patches-6.18/310-02-net-airoha-deassert-XSI-line-on-hw-init.patch index a75e06f944..61cd51ca60 100644 --- a/target/linux/airoha/patches-6.18/310-02-net-airoha-deassert-XSI-line-on-hw-init.patch +++ b/target/linux/airoha/patches-6.18/310-02-net-airoha-deassert-XSI-line-on-hw-init.patch @@ -13,7 +13,7 @@ Signed-off-by: Christian Marangi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -1487,6 +1487,10 @@ static int airoha_hw_init(struct platfor +@@ -1568,6 +1568,10 @@ static int airoha_hw_init(struct platfor if (err) return err; diff --git a/target/linux/airoha/patches-6.18/310-03-net-airoha-add-reference-for-SPORT-GDM4-in-qdma_get_.patch b/target/linux/airoha/patches-6.18/310-03-net-airoha-add-reference-for-SPORT-GDM4-in-qdma_get_.patch deleted file mode 100644 index d5a2ba9d1a..0000000000 --- a/target/linux/airoha/patches-6.18/310-03-net-airoha-add-reference-for-SPORT-GDM4-in-qdma_get_.patch +++ /dev/null @@ -1,31 +0,0 @@ -From ad29054f9b0e96e30a5d0bb6967d1204b8ea8bd1 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Fri, 17 Jan 2025 10:12:02 +0100 -Subject: [PATCH 3/9] net: airoha: add reference for SPORT GDM4 in - qdma_get_gdm_port - -Add SPORT reference in get gdm port as the on receive the SPORT 0x18 is -assigned for the GDM4 port. - -While at it also add comments to better identify GDM1 ports. - -Signed-off-by: Christian Marangi ---- - drivers/net/ethernet/airoha/airoha_eth.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/airoha/airoha_eth.c -+++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -574,8 +574,11 @@ static int airoha_qdma_get_gdm_port(stru - - sport = FIELD_GET(QDMA_ETH_RXMSG_SPORT_MASK, msg1); - switch (sport) { -+ case 0x18: -+ port = 3; /* GDM4 */ -+ break; - case 0x10 ... 0x14: -- port = 0; -+ port = 0; /* GDM1 */ - break; - case 0x2 ... 0x4: - port = sport - 1; diff --git a/target/linux/airoha/patches-6.18/310-06-net-airoha-add-initial-fixup-for-GDM3-4-port-support.patch b/target/linux/airoha/patches-6.18/310-06-net-airoha-add-initial-fixup-for-GDM3-4-port-support.patch index cd774e11ea..2de3c8d1a8 100644 --- a/target/linux/airoha/patches-6.18/310-06-net-airoha-add-initial-fixup-for-GDM3-4-port-support.patch +++ b/target/linux/airoha/patches-6.18/310-06-net-airoha-add-initial-fixup-for-GDM3-4-port-support.patch @@ -15,7 +15,7 @@ Signed-off-by: Christian Marangi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -498,8 +498,10 @@ static int airoha_fe_init(struct airoha_ +@@ -553,8 +553,10 @@ static int airoha_fe_init(struct airoha_ FIELD_PREP(IP_ASSEMBLE_PORT_MASK, 0) | FIELD_PREP(IP_ASSEMBLE_NBQ_MASK, 22)); @@ -26,15 +26,15 @@ Signed-off-by: Christian Marangi + airoha_fe_set(eth, REG_GDM_FWD_CFG(AIROHA_GDM4_IDX), + GDM_PAD_EN_MASK | GDM_STRIP_CRC_MASK); - airoha_fe_crsn_qsel_init(eth); - -@@ -1719,7 +1721,8 @@ static int airoha_dev_open(struct net_de + /* Enable split for MIB counters for GDM3 and GDM4 */ + airoha_fe_set(eth, REG_FE_GDM_MIB_CFG(AIROHA_GDM3_IDX), +@@ -1819,7 +1821,8 @@ static int airoha_dev_open(struct net_de if (err) return err; -- if (netdev_uses_dsa(dev)) +- if (netdev_uses_dsa(netdev)) + /* It seems GDM3 and GDM4 needs SPORT enabled to correctly work */ -+ if (netdev_uses_dsa(dev) || port->id > 2) ++ if (netdev_uses_dsa(netdev) || port->id > 2) airoha_fe_set(qdma->eth, REG_GDM_INGRESS_CFG(port->id), GDM_STAG_EN_MASK); else diff --git a/target/linux/airoha/patches-6.18/310-07-airoha-ethernet-drop-xsi-mac-reset.patch b/target/linux/airoha/patches-6.18/310-07-airoha-ethernet-drop-xsi-mac-reset.patch index 0ecba241d8..2af0f1f9ab 100644 --- a/target/linux/airoha/patches-6.18/310-07-airoha-ethernet-drop-xsi-mac-reset.patch +++ b/target/linux/airoha/patches-6.18/310-07-airoha-ethernet-drop-xsi-mac-reset.patch @@ -15,7 +15,7 @@ Signed-off-by: Christian Marangi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -3196,7 +3196,6 @@ static void airoha_remove(struct platfor +@@ -3518,7 +3518,6 @@ static void airoha_remove(struct platfor } static const char * const en7581_xsi_rsts_names[] = { @@ -23,7 +23,7 @@ Signed-off-by: Christian Marangi "hsi0-mac", "hsi1-mac", "hsi-mac", -@@ -3250,7 +3249,6 @@ static u32 airoha_en7581_get_vip_port(st +@@ -3605,7 +3604,6 @@ static int airoha_en7581_get_dev_from_sp } static const char * const an7583_xsi_rsts_names[] = { diff --git a/target/linux/airoha/patches-6.18/310-09-net-pcs-airoha-add-PCS-driver-for-Airoha-AN7581-SoC.patch b/target/linux/airoha/patches-6.18/310-09-net-pcs-airoha-add-PCS-driver-for-Airoha-AN7581-SoC.patch index 7c6c687b30..3bd81271c0 100644 --- a/target/linux/airoha/patches-6.18/310-09-net-pcs-airoha-add-PCS-driver-for-Airoha-AN7581-SoC.patch +++ b/target/linux/airoha/patches-6.18/310-09-net-pcs-airoha-add-PCS-driver-for-Airoha-AN7581-SoC.patch @@ -2717,8 +2717,8 @@ Signed-off-by: Christian Marangi + AN7581_PCS_JCPLL_SPARE_L, + AN7581_PCS_JCPLL_RST_DLY, + AN7581_PCS_JCPLL_PLL_RSTB, -+ AN7581_PCS_JCPLL_SDM_DI_LS, + AN7581_PCS_JCPLL_SDM_DI_EN, ++ AN7581_PCS_JCPLL_SDM_DI_LS, + + AN7581_PCS_JCPLL_SDM_OUT, + AN7581_PCS_JCPLL_SDM_ORD, @@ -2879,8 +2879,8 @@ Signed-off-by: Christian Marangi + + [AN7581_PCS_JCPLL_RST_DLY] = REG_FIELD(AIROHA_PCS_ANA_PXP_JCPLL_RST_DLY, 0, 2), + [AN7581_PCS_JCPLL_PLL_RSTB] = REG_FIELD(AIROHA_PCS_ANA_PXP_JCPLL_RST_DLY, 8, 8), -+ [AN7581_PCS_JCPLL_SDM_DI_LS] = REG_FIELD(AIROHA_PCS_ANA_PXP_JCPLL_RST_DLY, 16, 16), -+ [AN7581_PCS_JCPLL_SDM_DI_EN] = REG_FIELD(AIROHA_PCS_ANA_PXP_JCPLL_RST_DLY, 24, 25), ++ [AN7581_PCS_JCPLL_SDM_DI_EN] = REG_FIELD(AIROHA_PCS_ANA_PXP_JCPLL_RST_DLY, 16, 16), ++ [AN7581_PCS_JCPLL_SDM_DI_LS] = REG_FIELD(AIROHA_PCS_ANA_PXP_JCPLL_RST_DLY, 24, 25), + + [AN7581_PCS_JCPLL_SDM_OUT] = REG_FIELD(AIROHA_PCS_ANA_PXP_JCPLL_SDM_IFM, 24, 24), + [AN7581_PCS_JCPLL_SDM_ORD] = REG_FIELD(AIROHA_PCS_ANA_PXP_JCPLL_SDM_IFM, 16, 17), @@ -3045,8 +3045,8 @@ Signed-off-by: Christian Marangi + + [AN7581_PCS_JCPLL_RST_DLY] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_RST_DLY, 0, 2), + [AN7581_PCS_JCPLL_PLL_RSTB] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_RST_DLY, 8, 8), -+ [AN7581_PCS_JCPLL_SDM_DI_LS] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_RST_DLY, 16, 16), -+ [AN7581_PCS_JCPLL_SDM_DI_EN] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_RST_DLY, 24, 25), ++ [AN7581_PCS_JCPLL_SDM_DI_EN] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_RST_DLY, 16, 16), ++ [AN7581_PCS_JCPLL_SDM_DI_LS] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_RST_DLY, 24, 25), + + [AN7581_PCS_JCPLL_SDM_OUT] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_SDM_IFM, 24, 24), + [AN7581_PCS_JCPLL_SDM_ORD] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_SDM_IFM, 16, 17), @@ -3211,8 +3211,8 @@ Signed-off-by: Christian Marangi + + [AN7581_PCS_JCPLL_RST_DLY] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_RST_DLY, 0, 2), + [AN7581_PCS_JCPLL_PLL_RSTB] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_RST_DLY, 8, 8), -+ [AN7581_PCS_JCPLL_SDM_DI_LS] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_RST_DLY, 16, 16), -+ [AN7581_PCS_JCPLL_SDM_DI_EN] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_RST_DLY, 24, 25), ++ [AN7581_PCS_JCPLL_SDM_DI_EN] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_RST_DLY, 16, 16), ++ [AN7581_PCS_JCPLL_SDM_DI_LS] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_RST_DLY, 24, 25), + + [AN7581_PCS_JCPLL_SDM_OUT] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_SDM_IFM, 24, 24), + [AN7581_PCS_JCPLL_SDM_ORD] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_SDM_IFM, 16, 17), diff --git a/target/linux/airoha/patches-6.18/310-10-net-airoha-add-phylink-support-for-GDM2-3-4.patch b/target/linux/airoha/patches-6.18/310-10-net-airoha-add-phylink-support-for-GDM2-3-4.patch deleted file mode 100644 index 7421c01c06..0000000000 --- a/target/linux/airoha/patches-6.18/310-10-net-airoha-add-phylink-support-for-GDM2-3-4.patch +++ /dev/null @@ -1,281 +0,0 @@ -From ee93671d30d7741a39026c2aaaa6a7729929c347 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Fri, 17 Jan 2025 13:23:13 +0100 -Subject: [PATCH 2/2] net: airoha: add phylink support for GDM2/3/4 - -Add phylink support for GDM2/3/4 port that require configuration of the -PCS to make the external PHY or attached SFP cage work. - -These needs to be defined in the GDM port node using the pcs-handle -property. - -Signed-off-by: Christian Marangi ---- - drivers/net/ethernet/airoha/Kconfig | 1 + - drivers/net/ethernet/airoha/airoha_eth.c | 146 +++++++++++++++++++++- - drivers/net/ethernet/airoha/airoha_eth.h | 3 + - drivers/net/ethernet/airoha/airoha_regs.h | 12 ++ - 4 files changed, 161 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/airoha/Kconfig -+++ b/drivers/net/ethernet/airoha/Kconfig -@@ -20,6 +20,7 @@ config NET_AIROHA - depends on NET_DSA || !NET_DSA - select NET_AIROHA_NPU - select PAGE_POOL -+ select PHYLINK - help - This driver supports the gigabit ethernet MACs in the - Airoha SoC family. ---- a/drivers/net/ethernet/airoha/airoha_eth.c -+++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -8,6 +8,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -71,6 +72,11 @@ static void airoha_qdma_irq_disable(stru - airoha_qdma_set_irqmask(irq_bank, index, mask, 0); - } - -+static bool airhoa_is_phy_external(struct airoha_gdm_port *port) -+{ -+ return port->id != 1; -+} -+ - static void airoha_set_macaddr(struct airoha_gdm_port *port, const u8 *addr) - { - struct airoha_eth *eth = port->qdma->eth; -@@ -1716,6 +1722,17 @@ static int airoha_dev_open(struct net_de - struct airoha_qdma *qdma = port->qdma; - u32 pse_port = FE_PSE_PORT_PPE1; - -+ if (airhoa_is_phy_external(port)) { -+ err = phylink_of_phy_connect(port->phylink, dev->dev.of_node, 0); -+ if (err) { -+ netdev_err(dev, "%s: could not attach PHY: %d\n", __func__, -+ err); -+ return err; -+ } -+ -+ phylink_start(port->phylink); -+ } -+ - netif_tx_start_all_queues(dev); - err = airoha_set_vip_for_gdm_port(port, true); - if (err) -@@ -1777,6 +1794,11 @@ static int airoha_dev_stop(struct net_de - } - } - -+ if (airhoa_is_phy_external(port)) { -+ phylink_stop(port->phylink); -+ phylink_disconnect_phy(port->phylink); -+ } -+ - return 0; - } - -@@ -2916,6 +2938,11 @@ static const struct ethtool_ops airoha_e - .get_link = ethtool_op_get_link, - }; - -+static void airoha_mac_config(struct phylink_config *config, unsigned int mode, -+ const struct phylink_link_state *state) -+{ -+} -+ - static int airoha_metadata_dst_alloc(struct airoha_gdm_port *port) - { - int i; -@@ -2960,6 +2987,119 @@ bool airoha_is_valid_gdm_port(struct air - return false; - } - -+static void airoha_mac_link_up(struct phylink_config *config, struct phy_device *phy, -+ unsigned int mode, phy_interface_t interface, -+ int speed, int duplex, bool tx_pause, bool rx_pause) -+{ -+ struct airoha_gdm_port *port = container_of(config, struct airoha_gdm_port, -+ phylink_config); -+ struct airoha_qdma *qdma = port->qdma; -+ struct airoha_eth *eth = qdma->eth; -+ u32 frag_size_tx, frag_size_rx; -+ -+ if (port->id != 4) -+ return; -+ -+ switch (speed) { -+ case SPEED_10000: -+ case SPEED_5000: -+ frag_size_tx = 8; -+ frag_size_rx = 8; -+ break; -+ case SPEED_2500: -+ frag_size_tx = 2; -+ frag_size_rx = 1; -+ break; -+ default: -+ frag_size_tx = 1; -+ frag_size_rx = 0; -+ } -+ -+ /* Configure TX/RX frag based on speed */ -+ airoha_fe_rmw(eth, REG_GDMA4_TMBI_FRAG, -+ GDMA4_SGMII0_TX_FRAG_SIZE_MASK, -+ FIELD_PREP(GDMA4_SGMII0_TX_FRAG_SIZE_MASK, -+ frag_size_tx)); -+ -+ airoha_fe_rmw(eth, REG_GDMA4_RMBI_FRAG, -+ GDMA4_SGMII0_RX_FRAG_SIZE_MASK, -+ FIELD_PREP(GDMA4_SGMII0_RX_FRAG_SIZE_MASK, -+ frag_size_rx)); -+} -+ -+static void airoha_mac_link_down(struct phylink_config *config, unsigned int mode, -+ phy_interface_t interface) -+{ -+} -+ -+static const struct phylink_mac_ops airoha_phylink_ops = { -+ .mac_config = airoha_mac_config, -+ .mac_link_up = airoha_mac_link_up, -+ .mac_link_down = airoha_mac_link_down, -+}; -+ -+static int airoha_fill_available_pcs(struct phylink_config *config, -+ struct phylink_pcs **available_pcs, -+ unsigned int num_available_pcs) -+{ -+ struct device *dev = config->dev; -+ -+ return fwnode_phylink_pcs_parse(dev_fwnode(dev), available_pcs, -+ &num_available_pcs); -+} -+ -+static int airoha_setup_phylink(struct net_device *dev) -+{ -+ struct airoha_gdm_port *port = netdev_priv(dev); -+ struct device_node *np = dev->dev.of_node; -+ phy_interface_t phy_mode; -+ struct phylink *phylink; -+ int err; -+ -+ err = of_get_phy_mode(np, &phy_mode); -+ if (err) { -+ dev_err(&dev->dev, "incorrect phy-mode\n"); -+ return err; -+ } -+ -+ port->phylink_config.dev = &dev->dev; -+ port->phylink_config.type = PHYLINK_NETDEV; -+ port->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | -+ MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD | -+ MAC_5000FD | MAC_10000FD; -+ -+ err = fwnode_phylink_pcs_parse(dev_fwnode(&dev->dev), NULL, -+ &port->phylink_config.num_available_pcs); -+ if (err) -+ return err; -+ -+ port->phylink_config.fill_available_pcs = airoha_fill_available_pcs; -+ -+ __set_bit(PHY_INTERFACE_MODE_SGMII, -+ port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_1000BASEX, -+ port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_2500BASEX, -+ port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_10GBASER, -+ port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_USXGMII, -+ port->phylink_config.supported_interfaces); -+ -+ phy_interface_copy(port->phylink_config.pcs_interfaces, -+ port->phylink_config.supported_interfaces); -+ -+ phylink = phylink_create(&port->phylink_config, -+ of_fwnode_handle(np), -+ phy_mode, &airoha_phylink_ops); -+ if (IS_ERR(phylink)) -+ return PTR_ERR(phylink); -+ -+ port->phylink = phylink; -+ -+ return err; -+} -+ - static int airoha_alloc_gdm_port(struct airoha_eth *eth, - struct device_node *np) - { -@@ -3033,6 +3173,12 @@ static int airoha_alloc_gdm_port(struct - port->nbq = id == AIROHA_GDM3_IDX && airoha_is_7581(eth) ? 4 : 0; - eth->ports[p] = port; - -+ if (airhoa_is_phy_external(port)) { -+ err = airoha_setup_phylink(dev); -+ if (err) -+ return err; -+ } -+ - return airoha_metadata_dst_alloc(port); - } - -@@ -3160,8 +3306,11 @@ error_napi_stop: - if (!port) - continue; - -- if (port->dev->reg_state == NETREG_REGISTERED) -+ if (port->dev->reg_state == NETREG_REGISTERED) { -+ if (airhoa_is_phy_external(port)) -+ phylink_destroy(port->phylink); - unregister_netdev(port->dev); -+ } - airoha_metadata_dst_free(port); - } - airoha_hw_cleanup(eth); -@@ -3186,6 +3335,8 @@ static void airoha_remove(struct platfor - if (!port) - continue; - -+ if (airhoa_is_phy_external(port)) -+ phylink_destroy(port->phylink); - unregister_netdev(port->dev); - airoha_metadata_dst_free(port); - } ---- a/drivers/net/ethernet/airoha/airoha_eth.h -+++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -542,6 +542,9 @@ struct airoha_gdm_port { - int id; - int nbq; - -+ struct phylink *phylink; -+ struct phylink_config phylink_config; -+ - struct airoha_hw_stats stats; - - DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS); ---- a/drivers/net/ethernet/airoha/airoha_regs.h -+++ b/drivers/net/ethernet/airoha/airoha_regs.h -@@ -358,6 +358,18 @@ - #define IP_FRAGMENT_PORT_MASK GENMASK(8, 5) - #define IP_FRAGMENT_NBQ_MASK GENMASK(4, 0) - -+#define REG_GDMA4_TMBI_FRAG 0x2028 -+#define GDMA4_SGMII1_TX_WEIGHT_MASK GENMASK(31, 26) -+#define GDMA4_SGMII1_TX_FRAG_SIZE_MASK GENMASK(25, 16) -+#define GDMA4_SGMII0_TX_WEIGHT_MASK GENMASK(15, 10) -+#define GDMA4_SGMII0_TX_FRAG_SIZE_MASK GENMASK(9, 0) -+ -+#define REG_GDMA4_RMBI_FRAG 0x202c -+#define GDMA4_SGMII1_RX_WEIGHT_MASK GENMASK(31, 26) -+#define GDMA4_SGMII1_RX_FRAG_SIZE_MASK GENMASK(25, 16) -+#define GDMA4_SGMII0_RX_WEIGHT_MASK GENMASK(15, 10) -+#define GDMA4_SGMII0_RX_FRAG_SIZE_MASK GENMASK(9, 0) -+ - #define REG_MC_VLAN_EN 0x2100 - #define MC_VLAN_EN_MASK BIT(0) - diff --git a/target/linux/airoha/patches-6.18/310-10-net-airoha-add-phylink-support.patch b/target/linux/airoha/patches-6.18/310-10-net-airoha-add-phylink-support.patch new file mode 100644 index 0000000000..6d6c08b9b2 --- /dev/null +++ b/target/linux/airoha/patches-6.18/310-10-net-airoha-add-phylink-support.patch @@ -0,0 +1,361 @@ +From beb56181a370b003b12f657239b510435cae2c9d Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 17 Jan 2025 13:23:13 +0100 +Subject: [PATCH] net: airoha: add phylink support + +Add phylink support for each GDM port. For GDM1 add the internal interface +mode as the only supported mode. For GDM2/3/4 add the required +configuration of the PCS to make the external PHY or attached SFP cage +work. + +These needs to be defined in the GDM port node using the pcs-handle +property. + +Update and provide a .get/set_link_ksettings function that use phylink +for ethtool OPs now that we fully support phylink. + +Signed-off-by: Christian Marangi +--- + drivers/net/ethernet/airoha/Kconfig | 1 + + drivers/net/ethernet/airoha/airoha_eth.c | 193 +++++++++++++++++++++- + drivers/net/ethernet/airoha/airoha_eth.h | 7 +- + drivers/net/ethernet/airoha/airoha_regs.h | 12 ++ + 4 files changed, 206 insertions(+), 7 deletions(-) + +--- a/drivers/net/ethernet/airoha/Kconfig ++++ b/drivers/net/ethernet/airoha/Kconfig +@@ -20,6 +20,7 @@ config NET_AIROHA + depends on NET_DSA || !NET_DSA + select NET_AIROHA_NPU + select PAGE_POOL ++ select PHYLINK + help + This driver supports the gigabit ethernet MACs in the + Airoha SoC family. +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1794,7 +1795,7 @@ static void airoha_update_hw_stats(struc + struct airoha_gdm_port *port = dev->port; + int i; + +- spin_lock(&port->stats_lock); ++ spin_lock(&port->lock); + + for (i = 0; i < ARRAY_SIZE(port->devs); i++) { + if (port->devs[i]) +@@ -1805,7 +1806,7 @@ static void airoha_update_hw_stats(struc + airoha_fe_set(dev->eth, REG_FE_GDM_MIB_CLEAR(port->id), + FE_GDM_MIB_RX_CLEAR_MASK | FE_GDM_MIB_TX_CLEAR_MASK); + +- spin_unlock(&port->stats_lock); ++ spin_unlock(&port->lock); + } + + static int airoha_dev_open(struct net_device *netdev) +@@ -1816,6 +1817,14 @@ static int airoha_dev_open(struct net_de + u32 cur_len, pse_port = FE_PSE_PORT_PPE1; + struct airoha_qdma *qdma = dev->qdma; + ++ err = phylink_of_phy_connect(dev->phylink, netdev->dev.of_node, 0); ++ if (err) { ++ netdev_err(netdev, "could not attach PHY: %d\n", err); ++ return err; ++ } ++ ++ phylink_start(dev->phylink); ++ + netif_tx_start_all_queues(netdev); + err = airoha_set_vip_for_gdm_port(dev, true); + if (err) +@@ -1914,6 +1923,9 @@ static int airoha_dev_stop(struct net_de + } + } + ++ phylink_stop(dev->phylink); ++ phylink_disconnect_phy(dev->phylink); ++ + return 0; + } + +@@ -2395,6 +2407,24 @@ airoha_ethtool_get_rmon_stats(struct net + } while (u64_stats_fetch_retry(&dev->stats.syncp, start)); + } + ++static int ++airoha_ethtool_get_link_ksettings(struct net_device *netdev, ++ struct ethtool_link_ksettings *cmd) ++{ ++ struct airoha_gdm_dev *dev = netdev_priv(netdev); ++ ++ return phylink_ethtool_ksettings_get(dev->phylink, cmd); ++} ++ ++static int ++airoha_ethtool_set_link_ksettings(struct net_device *netdev, ++ const struct ethtool_link_ksettings *cmd) ++{ ++ struct airoha_gdm_dev *dev = netdev_priv(netdev); ++ ++ return phylink_ethtool_ksettings_set(dev->phylink, cmd); ++} ++ + static int airoha_qdma_set_chan_tx_sched(struct net_device *netdev, + int channel, enum tx_sched_mode mode, + const u16 *weights, u8 n_weights) +@@ -3126,7 +3156,8 @@ static const struct ethtool_ops airoha_e + .get_drvinfo = airoha_ethtool_get_drvinfo, + .get_eth_mac_stats = airoha_ethtool_get_mac_stats, + .get_rmon_stats = airoha_ethtool_get_rmon_stats, +- .get_link_ksettings = phy_ethtool_get_link_ksettings, ++ .get_link_ksettings = airoha_ethtool_get_link_ksettings, ++ .set_link_ksettings = airoha_ethtool_set_link_ksettings, + .get_link = ethtool_op_get_link, + }; + +@@ -3182,6 +3213,159 @@ bool airoha_is_valid_gdm_dev(struct airo + return false; + } + ++/* Nothing to do in MAC, everything is handled in PCS */ ++static void airoha_mac_config(struct phylink_config *config, unsigned int mode, ++ const struct phylink_link_state *state) ++{ ++} ++ ++static void airoha_mac_link_up(struct phylink_config *config, struct phy_device *phy, ++ unsigned int mode, phy_interface_t interface, ++ int speed, int duplex, bool tx_pause, bool rx_pause) ++{ ++ struct airoha_gdm_dev *dev = container_of(config, struct airoha_gdm_dev, ++ phylink_config); ++ struct airoha_gdm_port *port = dev->port; ++ struct airoha_eth *eth = dev->eth; ++ u32 frag_size_tx, frag_size_rx; ++ u32 mask, val; ++ ++ /* TX/RX frag is configured only for GDM4 */ ++ if (port->id != AIROHA_GDM4_IDX) ++ return; ++ ++ switch (speed) { ++ case SPEED_10000: ++ case SPEED_5000: ++ frag_size_tx = 8; ++ frag_size_rx = 8; ++ break; ++ case SPEED_2500: ++ frag_size_tx = 2; ++ frag_size_rx = 1; ++ break; ++ default: ++ frag_size_tx = 1; ++ frag_size_rx = 0; ++ } ++ ++ spin_lock(&port->lock); ++ ++ /* Configure TX/RX frag based on speed */ ++ if (dev->nbq == 1) { ++ mask = GDM4_SGMII1_TX_FRAG_SIZE_MASK; ++ val = FIELD_PREP(GDM4_SGMII1_TX_FRAG_SIZE_MASK, ++ frag_size_tx); ++ } else { ++ mask = GDM4_SGMII0_TX_FRAG_SIZE_MASK; ++ val = FIELD_PREP(GDM4_SGMII0_TX_FRAG_SIZE_MASK, ++ frag_size_tx); ++ } ++ airoha_fe_rmw(eth, REG_FE_GDM4_TMBI_FRAG, mask, val); ++ ++ if (dev->nbq == 1) { ++ mask = GDM4_SGMII1_RX_FRAG_SIZE_MASK; ++ val = FIELD_PREP(GDM4_SGMII1_RX_FRAG_SIZE_MASK, ++ frag_size_rx); ++ } else { ++ mask = GDM4_SGMII0_RX_FRAG_SIZE_MASK; ++ val = FIELD_PREP(GDM4_SGMII0_RX_FRAG_SIZE_MASK, ++ frag_size_rx); ++ } ++ airoha_fe_rmw(eth, REG_FE_GDM4_RMBI_FRAG, mask, val); ++ ++ spin_unlock(&port->lock); ++} ++ ++/* Nothing to do in MAC, everything is handled in PCS */ ++static void airoha_mac_link_down(struct phylink_config *config, unsigned int mode, ++ phy_interface_t interface) ++{ ++} ++ ++static const struct phylink_mac_ops airoha_phylink_ops = { ++ .mac_config = airoha_mac_config, ++ .mac_link_up = airoha_mac_link_up, ++ .mac_link_down = airoha_mac_link_down, ++}; ++ ++static int airoha_fill_available_pcs(struct phylink_config *config, ++ struct phylink_pcs **available_pcs, ++ unsigned int num_possible_pcs) ++{ ++ struct device *dev = config->dev; ++ ++ return fwnode_phylink_pcs_parse(dev_fwnode(dev), available_pcs, ++ &num_possible_pcs); ++} ++ ++static int airoha_setup_phylink(struct net_device *netdev) ++{ ++ struct airoha_gdm_dev *dev = netdev_priv(netdev); ++ struct device_node *np = netdev->dev.of_node; ++ struct airoha_gdm_port *port = dev->port; ++ struct phylink_config *config; ++ phy_interface_t phy_mode; ++ struct phylink *phylink; ++ int err; ++ ++ err = of_get_phy_mode(np, &phy_mode); ++ if (err) { ++ dev_err(&netdev->dev, "incorrect phy-mode\n"); ++ return err; ++ } ++ ++ config = &dev->phylink_config; ++ config->dev = &netdev->dev; ++ config->type = PHYLINK_NETDEV; ++ ++ /* ++ * GDM1 only supports internal for Embedded Switch ++ * and doesn't require a PCS. ++ */ ++ if (port->id == AIROHA_GDM1_IDX) { ++ config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | ++ MAC_10000FD; ++ ++ __set_bit(PHY_INTERFACE_MODE_INTERNAL, ++ config->supported_interfaces); ++ } else { ++ config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | ++ MAC_10 | MAC_100 | MAC_1000 | ++ MAC_2500FD | MAC_5000FD | MAC_10000FD; ++ ++ err = fwnode_phylink_pcs_parse(dev_fwnode(config->dev), NULL, ++ &dev->phylink_config.num_available_pcs); ++ if (err) ++ return err; ++ ++ config->fill_available_pcs = airoha_fill_available_pcs; ++ ++ __set_bit(PHY_INTERFACE_MODE_SGMII, ++ config->supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_1000BASEX, ++ config->supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_2500BASEX, ++ config->supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_10GBASER, ++ config->supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_USXGMII, ++ config->supported_interfaces); ++ ++ phy_interface_copy(config->pcs_interfaces, ++ config->supported_interfaces); ++ } ++ ++ phylink = phylink_create(config, of_fwnode_handle(np), ++ phy_mode, &airoha_phylink_ops); ++ if (IS_ERR(phylink)) ++ return PTR_ERR(phylink); ++ ++ dev->phylink = phylink; ++ ++ return 0; ++} ++ + static int airoha_alloc_gdm_device(struct airoha_eth *eth, + struct airoha_gdm_port *port, + int nbq, struct device_node *np) +@@ -3245,7 +3429,7 @@ static int airoha_alloc_gdm_device(struc + dev->nbq = nbq; + port->devs[index] = dev; + +- return 0; ++ return airoha_setup_phylink(netdev); + } + + static int airoha_alloc_gdm_port(struct airoha_eth *eth, +@@ -3280,7 +3464,7 @@ static int airoha_alloc_gdm_port(struct + return -ENOMEM; + + port->id = id; +- spin_lock_init(&port->stats_lock); ++ spin_lock_init(&port->lock); + eth->ports[p] = port; + + err = airoha_metadata_dst_alloc(port); +@@ -3471,6 +3655,8 @@ error_napi_stop: + netdev = netdev_from_priv(dev); + if (netdev->reg_state == NETREG_REGISTERED) + unregister_netdev(netdev); ++ if (dev->phylink) ++ phylink_destroy(dev->phylink); + of_node_put(netdev->dev.of_node); + } + airoha_metadata_dst_free(port); +@@ -3507,6 +3693,7 @@ static void airoha_remove(struct platfor + + netdev = netdev_from_priv(dev); + unregister_netdev(netdev); ++ phylink_destroy(dev->phylink); + of_node_put(netdev->dev.of_node); + } + airoha_metadata_dst_free(port); +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -554,6 +554,9 @@ struct airoha_gdm_dev { + int nbq; + + struct airoha_hw_stats stats; ++ ++ struct phylink *phylink; ++ struct phylink_config phylink_config; + }; + + struct airoha_gdm_port { +@@ -561,8 +564,8 @@ struct airoha_gdm_port { + int id; + int users; + +- /* protect concurrent hw_stats accesses */ +- spinlock_t stats_lock; ++ /* protect concurrent hw_stats and frag register accesses */ ++ spinlock_t lock; + + struct metadata_dst *dsa_meta[AIROHA_MAX_DSA_PORTS]; + }; +--- a/drivers/net/ethernet/airoha/airoha_regs.h ++++ b/drivers/net/ethernet/airoha/airoha_regs.h +@@ -358,6 +358,18 @@ + #define IP_FRAGMENT_PORT_MASK GENMASK(8, 5) + #define IP_FRAGMENT_NBQ_MASK GENMASK(4, 0) + ++#define REG_FE_GDM4_TMBI_FRAG 0x2028 ++#define GDM4_SGMII1_TX_WEIGHT_MASK GENMASK(31, 26) ++#define GDM4_SGMII1_TX_FRAG_SIZE_MASK GENMASK(25, 16) ++#define GDM4_SGMII0_TX_WEIGHT_MASK GENMASK(15, 10) ++#define GDM4_SGMII0_TX_FRAG_SIZE_MASK GENMASK(9, 0) ++ ++#define REG_FE_GDM4_RMBI_FRAG 0x202c ++#define GDM4_SGMII1_RX_WEIGHT_MASK GENMASK(31, 26) ++#define GDM4_SGMII1_RX_FRAG_SIZE_MASK GENMASK(25, 16) ++#define GDM4_SGMII0_RX_WEIGHT_MASK GENMASK(15, 10) ++#define GDM4_SGMII0_RX_FRAG_SIZE_MASK GENMASK(9, 0) ++ + #define REG_MC_VLAN_EN 0x2100 + #define MC_VLAN_EN_MASK BIT(0) + diff --git a/target/linux/airoha/patches-6.18/402-01-thermal-airoha-convert-to-regmap-API.patch b/target/linux/airoha/patches-6.18/402-01-thermal-airoha-convert-to-regmap-API.patch index 9414bef9cb..6b6cbc3dd0 100644 --- a/target/linux/airoha/patches-6.18/402-01-thermal-airoha-convert-to-regmap-API.patch +++ b/target/linux/airoha/patches-6.18/402-01-thermal-airoha-convert-to-regmap-API.patch @@ -41,7 +41,7 @@ Signed-off-by: Christian Marangi - writel(TEMP_TO_RAW(priv, low) >> 4, - priv->base + EN7581_TEMPOFFSETL); + regmap_write(priv->map, EN7581_TEMPOFFSETL, -+ TEMP_TO_RAW(priv, high) >> 4); ++ TEMP_TO_RAW(priv, low) >> 4); enable_monitor = true; } diff --git a/target/linux/airoha/patches-6.18/402-05-thermal-drivers-airoha-Add-support-for-AN7583.patch b/target/linux/airoha/patches-6.18/402-05-thermal-drivers-airoha-Add-support-for-AN7583.patch index 51332350ef..dd7912259c 100644 --- a/target/linux/airoha/patches-6.18/402-05-thermal-drivers-airoha-Add-support-for-AN7583.patch +++ b/target/linux/airoha/patches-6.18/402-05-thermal-drivers-airoha-Add-support-for-AN7583.patch @@ -231,8 +231,8 @@ Signed-off-by: Christian Marangi + int i; + + priv->chip_scu = device_node_to_regmap(dev->parent->of_node); -+ if (IS_ERR(priv->map)) -+ return PTR_ERR(priv->map); ++ if (IS_ERR(priv->chip_scu)) ++ return PTR_ERR(priv->chip_scu); + + for (i = 0; i < AIROHA_THERMAL_FIELD_MAX; i++) { + struct regmap_field *field; diff --git a/target/linux/airoha/patches-6.18/604-02-net-ethernet-airoha-define-sport-value-for-GDM3.patch b/target/linux/airoha/patches-6.18/604-02-net-ethernet-airoha-define-sport-value-for-GDM3.patch deleted file mode 100644 index b78cc3455f..0000000000 --- a/target/linux/airoha/patches-6.18/604-02-net-ethernet-airoha-define-sport-value-for-GDM3.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 6548e580509397a622b7c504a79de93414771459 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Wed, 25 Jun 2025 00:04:36 +0200 -Subject: [PATCH 6/6] net: ethernet: airoha: define sport value for GDM3 - -On Airoha AN7583, the Serdes Ethernet goes through the GDM3 port. -To correctly receive packet for QDMA, add the sport value to identify -packet from GDM3 port. - -Signed-off-by: Christian Marangi ---- - drivers/net/ethernet/airoha/airoha_eth.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/drivers/net/ethernet/airoha/airoha_eth.c -+++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -585,6 +585,9 @@ static int airoha_qdma_get_gdm_port(stru - case 0x18: - port = 3; /* GDM4 */ - break; -+ case 0x16: -+ port = 2; /* GDM3 */ -+ break; - case 0x10 ... 0x14: - port = 0; /* GDM1 */ - break; diff --git a/target/linux/airoha/patches-6.18/606-net-airoha-disable-external-phy-code-if-PCS_AIROHA-i.patch b/target/linux/airoha/patches-6.18/606-net-airoha-disable-external-phy-code-if-PCS_AIROHA-i.patch deleted file mode 100644 index d43d3303a0..0000000000 --- a/target/linux/airoha/patches-6.18/606-net-airoha-disable-external-phy-code-if-PCS_AIROHA-i.patch +++ /dev/null @@ -1,124 +0,0 @@ -From 843e2892f2d9353bf039e0dfb5442a600e75009e Mon Sep 17 00:00:00 2001 -From: Mikhail Kshevetskiy -Date: Thu, 9 Oct 2025 23:46:08 +0300 -Subject: [PATCH] net: airoha: disable external phy code if PCS_AIROHA is not - enabled - -External phy code breaks building for EN7523, so disable it if -PCS_AIROHA is not selected. - -Signed-off-by: Mikhail Kshevetskiy ---- - drivers/net/ethernet/airoha/airoha_eth.c | 16 ++++++++++++++++ - drivers/net/ethernet/airoha/airoha_eth.h | 2 ++ - 2 files changed, 18 insertions(+) - ---- a/drivers/net/ethernet/airoha/airoha_eth.c -+++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -72,10 +72,12 @@ static void airoha_qdma_irq_disable(stru - airoha_qdma_set_irqmask(irq_bank, index, mask, 0); - } - -+#if defined(CONFIG_PCS_AIROHA) - static bool airhoa_is_phy_external(struct airoha_gdm_port *port) - { - return port->id != 1; - } -+#endif - - static void airoha_set_macaddr(struct airoha_gdm_port *port, const u8 *addr) - { -@@ -1725,6 +1727,7 @@ static int airoha_dev_open(struct net_de - struct airoha_qdma *qdma = port->qdma; - u32 pse_port = FE_PSE_PORT_PPE1; - -+#if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) { - err = phylink_of_phy_connect(port->phylink, dev->dev.of_node, 0); - if (err) { -@@ -1735,6 +1738,7 @@ static int airoha_dev_open(struct net_de - - phylink_start(port->phylink); - } -+#endif - - netif_tx_start_all_queues(dev); - err = airoha_set_vip_for_gdm_port(port, true); -@@ -1797,10 +1801,12 @@ static int airoha_dev_stop(struct net_de - } - } - -+#if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) { - phylink_stop(port->phylink); - phylink_disconnect_phy(port->phylink); - } -+#endif - - return 0; - } -@@ -2990,6 +2996,7 @@ bool airoha_is_valid_gdm_port(struct air - return false; - } - -+#if defined(CONFIG_PCS_AIROHA) - static void airoha_mac_link_up(struct phylink_config *config, struct phy_device *phy, - unsigned int mode, phy_interface_t interface, - int speed, int duplex, bool tx_pause, bool rx_pause) -@@ -3102,6 +3109,7 @@ static int airoha_setup_phylink(struct n - - return err; - } -+#endif - - static int airoha_alloc_gdm_port(struct airoha_eth *eth, - struct device_node *np) -@@ -3176,11 +3184,13 @@ static int airoha_alloc_gdm_port(struct - port->nbq = id == AIROHA_GDM3_IDX && airoha_is_7581(eth) ? 4 : 0; - eth->ports[p] = port; - -+#if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) { - err = airoha_setup_phylink(dev); - if (err) - return err; - } -+#endif - - return airoha_metadata_dst_alloc(port); - } -@@ -3310,8 +3320,10 @@ error_napi_stop: - continue; - - if (port->dev->reg_state == NETREG_REGISTERED) { -+#if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) - phylink_destroy(port->phylink); -+#endif - unregister_netdev(port->dev); - } - airoha_metadata_dst_free(port); -@@ -3338,8 +3350,10 @@ static void airoha_remove(struct platfor - if (!port) - continue; - -+#if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) - phylink_destroy(port->phylink); -+#endif - unregister_netdev(port->dev); - airoha_metadata_dst_free(port); - } ---- a/drivers/net/ethernet/airoha/airoha_eth.h -+++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -542,8 +542,10 @@ struct airoha_gdm_port { - int id; - int nbq; - -+#if defined(CONFIG_PCS_AIROHA) - struct phylink *phylink; - struct phylink_config phylink_config; -+#endif - - struct airoha_hw_stats stats; - diff --git a/target/linux/airoha/patches-6.18/801-01-net-phy-add-PHY_DETACH_NO_HW_RESET-PHY-flag.patch b/target/linux/airoha/patches-6.18/801-01-net-phy-add-PHY_DETACH_NO_HW_RESET-PHY-flag.patch index 2b978e1160..cc710daead 100644 --- a/target/linux/airoha/patches-6.18/801-01-net-phy-add-PHY_DETACH_NO_HW_RESET-PHY-flag.patch +++ b/target/linux/airoha/patches-6.18/801-01-net-phy-add-PHY_DETACH_NO_HW_RESET-PHY-flag.patch @@ -107,7 +107,7 @@ Signed-off-by: Christian Marangi module_phy_driver(as21xxx_drivers); --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c -@@ -1882,7 +1882,8 @@ void phy_detach(struct phy_device *phyde +@@ -1885,7 +1885,8 @@ void phy_detach(struct phy_device *phyde } /* Assert the reset signal */ diff --git a/target/linux/airoha/patches-6.18/886-uart-add-en7523-support.patch b/target/linux/airoha/patches-6.18/886-uart-add-en7523-support.patch index 4a94fb4945..1118066013 100644 --- a/target/linux/airoha/patches-6.18/886-uart-add-en7523-support.patch +++ b/target/linux/airoha/patches-6.18/886-uart-add-en7523-support.patch @@ -1,6 +1,6 @@ --- /dev/null +++ b/drivers/tty/serial/8250/8250_en7523.c -@@ -0,0 +1,94 @@ +@@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Airoha EN7523 driver. @@ -84,6 +84,8 @@ + xyd_x = ((nom/denom) << 4); + if (xyd_x < XYD_Y) break; + } ++ if (i >= CLOCK_DIV_TAB_ELEMS) ++ i = CLOCK_DIV_TAB_ELEMS - 1; + + serial_port_out(port, UART_XINCLKDR, clock_div_reg[i]); + serial_port_out(port, UART_XYD, (xyd_x<<16) | XYD_Y); diff --git a/target/linux/airoha/patches-6.18/915-02-net-airoha-Set-hw-QoS-parameter-according-to-the-pac.patch b/target/linux/airoha/patches-6.18/915-02-net-airoha-Set-hw-QoS-parameter-according-to-the-pac.patch index 6acc99da3e..7670611c01 100644 --- a/target/linux/airoha/patches-6.18/915-02-net-airoha-Set-hw-QoS-parameter-according-to-the-pac.patch +++ b/target/linux/airoha/patches-6.18/915-02-net-airoha-Set-hw-QoS-parameter-according-to-the-pac.patch @@ -25,25 +25,25 @@ Signed-off-by: Lorenzo Bianconi #include "airoha_regs.h" #include "airoha_eth.h" -@@ -300,7 +301,7 @@ static int airoha_ppe_foe_entry_prepare( +@@ -314,7 +315,7 @@ static int airoha_ppe_foe_entry_prepare( struct airoha_foe_entry *hwe, - struct net_device *dev, int type, + struct net_device *netdev, int type, struct airoha_flow_data *data, - int l4proto) + int l4proto, u8 dsfield) { u32 qdata = FIELD_PREP(AIROHA_FOE_SHAPER_ID, 0x7f), ports_pad, val; - int wlan_etype = -EINVAL, dsa_port = airoha_get_dsa_port(&dev); -@@ -333,7 +334,7 @@ static int airoha_ppe_foe_entry_prepare( - info.wcid); + int wlan_etype = -EINVAL, dsa_port = airoha_get_dsa_port(&netdev); +@@ -349,7 +350,7 @@ static int airoha_ppe_foe_entry_prepare( } else { - struct airoha_gdm_port *port = netdev_priv(dev); + struct airoha_gdm_dev *dev = netdev_priv(netdev); + struct airoha_gdm_port *port; - u8 pse_port, channel; + u8 pse_port, channel, priority; - if (!airoha_is_valid_gdm_port(eth, port)) + if (!airoha_is_valid_gdm_dev(eth, dev)) return -EINVAL; -@@ -352,9 +353,13 @@ static int airoha_ppe_foe_entry_prepare( +@@ -369,9 +370,13 @@ static int airoha_ppe_foe_entry_prepare( */ channel = dsa_port >= 0 ? dsa_port : port->id; channel = channel % AIROHA_NUM_QOS_CHANNELS; @@ -58,7 +58,7 @@ Signed-off-by: Lorenzo Bianconi AIROHA_FOE_IB2_PSE_QOS; /* For downlink traffic consume SRAM memory for hw * forwarding descriptors queue. -@@ -1046,9 +1051,9 @@ static int airoha_ppe_flow_offload_repla +@@ -1063,9 +1068,9 @@ static int airoha_ppe_flow_offload_repla struct net_device *odev = NULL; struct flow_action_entry *act; struct airoha_foe_entry hwe; @@ -69,7 +69,7 @@ Signed-off-by: Lorenzo Bianconi if (rhashtable_lookup(ð->flow_table, &f->cookie, airoha_flow_table_params)) -@@ -1078,6 +1083,13 @@ static int airoha_ppe_flow_offload_repla +@@ -1095,6 +1100,13 @@ static int airoha_ppe_flow_offload_repla return -EOPNOTSUPP; } @@ -83,7 +83,7 @@ Signed-off-by: Lorenzo Bianconi switch (addr_type) { case 0: offload_type = PPE_PKT_TYPE_BRIDGE; -@@ -1143,7 +1155,7 @@ static int airoha_ppe_flow_offload_repla +@@ -1160,7 +1172,7 @@ static int airoha_ppe_flow_offload_repla return -EINVAL; err = airoha_ppe_foe_entry_prepare(eth, &hwe, odev, offload_type, diff --git a/target/linux/airoha/patches-6.18/916-02-net-airoha-Implement-HW-GRO-TCP-support.patch b/target/linux/airoha/patches-6.18/916-02-net-airoha-Implement-HW-GRO-TCP-support.patch new file mode 100644 index 0000000000..a07062d7fd --- /dev/null +++ b/target/linux/airoha/patches-6.18/916-02-net-airoha-Implement-HW-GRO-TCP-support.patch @@ -0,0 +1,641 @@ +From 598e1ddfe85ad0f4778eeadd5d878209dd931280 Mon Sep 17 00:00:00 2001 +Message-ID: <598e1ddfe85ad0f4778eeadd5d878209dd931280.1779112628.git.lorenzo@kernel.org> +From: Lorenzo Bianconi +Date: Thu, 14 May 2026 20:25:19 +0200 +Subject: [PATCH] net: airoha: Implement LRO TCP support + +Signed-off-by: Lorenzo Bianconi +--- + drivers/net/ethernet/airoha/airoha_eth.c | 178 ++++++++++++++++++++-- + drivers/net/ethernet/airoha/airoha_eth.h | 23 +++ + drivers/net/ethernet/airoha/airoha_regs.h | 22 ++- + 3 files changed, 208 insertions(+), 15 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -11,8 +11,10 @@ + #include + #include + #include ++#include + #include + #include ++#include + #include + + #include "airoha_regs.h" +@@ -487,6 +489,73 @@ static void airoha_fe_crsn_qsel_init(str + CDM_CRSN_QSEL_Q1)); + } + ++static void airoha_fe_lro_rxq_enable(struct airoha_eth *eth, int qdma_id, ++ int lro_queue_index, int qid, ++ int buf_size) ++{ ++ int id = qdma_id + 1; ++ ++ airoha_fe_rmw(eth, REG_CDM_LRO_LIMIT(id), ++ CDM_LRO_AGG_NUM_MASK | CDM_LRO_AGG_SIZE_MASK, ++ FIELD_PREP(CDM_LRO_AGG_SIZE_MASK, buf_size) | ++ FIELD_PREP(CDM_LRO_AGG_NUM_MASK, ++ AIROHA_RXQ_LRO_MAX_AGG_COUNT)); ++ airoha_fe_rmw(eth, REG_CDM_LRO_AGE_TIME(id), ++ CDM_LRO_AGE_TIME_MASK | CDM_LRO_AGG_TIME_MASK, ++ FIELD_PREP(CDM_LRO_AGE_TIME_MASK, ++ AIROHA_RXQ_LRO_MAX_AGE_TIME) | ++ FIELD_PREP(CDM_LRO_AGG_TIME_MASK, ++ AIROHA_RXQ_LRO_MAX_AGG_TIME)); ++ airoha_fe_rmw(eth, REG_CDM_LRO_RXQ(id, lro_queue_index), ++ LRO_RXQ_MASK(lro_queue_index), ++ __field_prep(LRO_RXQ_MASK(lro_queue_index), qid)); ++ airoha_fe_set(eth, REG_CDM_LRO_EN(id), BIT(lro_queue_index)); ++} ++ ++static void airoha_fe_lro_disable(struct airoha_eth *eth, int qdma_id) ++{ ++ int i, id = qdma_id + 1; ++ ++ airoha_fe_clear(eth, REG_CDM_LRO_EN(id), LRO_RXQ_EN_MASK); ++ airoha_fe_clear(eth, REG_CDM_LRO_LIMIT(id), ++ CDM_LRO_AGG_NUM_MASK | CDM_LRO_AGG_SIZE_MASK); ++ airoha_fe_clear(eth, REG_CDM_LRO_AGE_TIME(id), ++ CDM_LRO_AGE_TIME_MASK | CDM_LRO_AGG_TIME_MASK); ++ for (i = 0; i < AIROHA_MAX_NUM_LRO_QUEUES; i++) ++ airoha_fe_clear(eth, REG_CDM_LRO_RXQ(id, i), LRO_RXQ_MASK(i)); ++} ++ ++static bool airoha_fe_lro_is_enabled(struct airoha_eth *eth, int qdma_id) ++{ ++ return airoha_fe_get(eth, REG_CDM_LRO_EN(qdma_id + 1), ++ LRO_RXQ_EN_MASK); ++} ++ ++static void airoha_dev_lro_enable(struct airoha_gdm_dev *dev) ++{ ++ struct airoha_qdma *qdma = dev->qdma; ++ struct airoha_eth *eth = qdma->eth; ++ int qdma_id = qdma - ð->qdma[0]; ++ int i, lro_queue_index = 0; ++ ++ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { ++ struct airoha_queue *q = &qdma->q_rx[i]; ++ u32 size; ++ ++ if (!q->ndesc) ++ continue; ++ ++ if (!airoha_qdma_is_lro_queue(q)) ++ continue; ++ ++ size = SKB_WITH_OVERHEAD(AIROHA_RX_LEN(q->buf_size)); ++ size = min_t(u32, size, CDM_LRO_AGG_SIZE_MASK); ++ airoha_fe_lro_rxq_enable(eth, qdma_id, lro_queue_index, i, ++ size); ++ lro_queue_index++; ++ } ++} ++ + static int airoha_fe_init(struct airoha_eth *eth) + { + airoha_fe_maccr_init(eth); +@@ -614,6 +683,7 @@ static int airoha_qdma_fill_rx_queue(str + e->dma_addr = page_pool_get_dma_addr(page) + offset; + e->dma_len = SKB_WITH_OVERHEAD(AIROHA_RX_LEN(q->buf_size)); + ++ WRITE_ONCE(desc->tcp_ts_reply, 0); + val = FIELD_PREP(QDMA_DESC_LEN_MASK, e->dma_len); + WRITE_ONCE(desc->ctrl, cpu_to_le32(val)); + WRITE_ONCE(desc->addr, cpu_to_le32(e->dma_addr)); +@@ -655,12 +725,169 @@ airoha_qdma_get_gdm_dev(struct airoha_et + return port->devs[d] ? port->devs[d] : ERR_PTR(-ENODEV); + } + ++static struct sk_buff *airoha_qdma_lro_rx_skb(struct airoha_queue *q, ++ struct airoha_qdma_desc *desc, ++ struct airoha_queue_entry *e) ++{ ++ u32 len, th_off, tcp_ack_seq, agg_count, data_off, data_len; ++ u32 desc_ctrl = le32_to_cpu(READ_ONCE(desc->ctrl)); ++ u32 msg1 = le32_to_cpu(READ_ONCE(desc->msg1)); ++ u32 msg2 = le32_to_cpu(READ_ONCE(desc->msg2)); ++ u32 msg3 = le32_to_cpu(READ_ONCE(desc->msg3)); ++ struct skb_shared_info *shinfo; ++ u16 tcp_win, l2_len; ++ struct sk_buff *skb; ++ struct tcphdr *th; ++ struct page *page; ++ bool ipv4, ipv6; ++ ++ ipv4 = FIELD_GET(QDMA_ETH_RXMSG_IP4_MASK, msg1); ++ ipv6 = FIELD_GET(QDMA_ETH_RXMSG_IP6_MASK, msg1); ++ if (!ipv4 && !ipv6) ++ return NULL; ++ ++ l2_len = FIELD_GET(QDMA_ETH_RXMSG_L2_LEN_MASK, msg2); ++ len = FIELD_GET(QDMA_DESC_LEN_MASK, desc_ctrl); ++ ++ if (ipv4) { ++ struct iphdr *iph; ++ ++ if (len < l2_len + sizeof(*iph)) ++ return NULL; ++ ++ iph = (struct iphdr *)(e->buf + l2_len); ++ if (iph->protocol != IPPROTO_TCP) ++ return NULL; ++ ++ if (iph->ihl < 5) ++ return NULL; ++ ++ th_off = l2_len + (iph->ihl << 2); ++ if (len < th_off) ++ return NULL; ++ ++ iph->tot_len = cpu_to_be16(len - l2_len); ++ iph->check = 0; ++ iph->check = ip_fast_csum((void *)iph, iph->ihl); ++ } else { ++ struct ipv6hdr *ip6h; ++ ++ th_off = l2_len + sizeof(*ip6h); ++ if (len < th_off) ++ return NULL; ++ ++ ip6h = (struct ipv6hdr *)(e->buf + l2_len); ++ if (ip6h->nexthdr != NEXTHDR_TCP) ++ return NULL; ++ ++ ip6h->payload_len = cpu_to_be16(len - th_off); ++ } ++ ++ if (len < th_off + sizeof(*th)) ++ return NULL; ++ ++ th = (struct tcphdr *)(e->buf + th_off); ++ if (th->doff < 5) ++ return NULL; ++ ++ data_off = th_off + (th->doff << 2); ++ if (len < data_off) ++ return NULL; ++ ++ tcp_win = FIELD_GET(QDMA_ETH_RXMSG_TCP_WIN_MASK, msg3); ++ tcp_ack_seq = le32_to_cpu(READ_ONCE(desc->data)); ++ th->ack_seq = cpu_to_be32(tcp_ack_seq); ++ th->window = cpu_to_be16(tcp_win); ++ ++ /* Check tcp timestamp option */ ++ if (th->doff == (sizeof(*th) + TCPOLEN_TSTAMP_ALIGNED) / 4) { ++ u32 topt = get_unaligned_be32(th + 1); ++ ++ if (topt == ((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | ++ (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) { ++ u8 *ptr = (u8 *)th + sizeof(*th) + 2 * sizeof(__be32); ++ __le32 tcp_ts_reply = READ_ONCE(desc->tcp_ts_reply); ++ ++ put_unaligned_be32(le32_to_cpu(tcp_ts_reply), ptr); ++ } ++ } ++ ++ if (ipv4) { ++ struct iphdr *iph = (struct iphdr *)(e->buf + l2_len); ++ ++ th->check = ~tcp_v4_check(len - th_off, iph->saddr, ++ iph->daddr, 0); ++ } else { ++ struct ipv6hdr *ip6h = (struct ipv6hdr *)(e->buf + l2_len); ++ ++ th->check = ~tcp_v6_check(len - th_off, &ip6h->saddr, ++ &ip6h->daddr, 0); ++ } ++ ++ skb = napi_alloc_skb(&q->napi, data_off); ++ if (!skb) ++ return NULL; ++ ++ __skb_put(skb, data_off); ++ memcpy(skb->data, e->buf, data_off); ++ ++ page = virt_to_head_page(e->buf); ++ data_len = len - data_off; ++ shinfo = skb_shinfo(skb); ++ skb_add_rx_frag(skb, shinfo->nr_frags, page, ++ e->buf + data_off - page_address(page), data_len, ++ q->buf_size); ++ ++ shinfo->gso_type = ipv4 ? SKB_GSO_TCPV4 : SKB_GSO_TCPV6; ++ agg_count = FIELD_GET(QDMA_ETH_RXMSG_AGG_COUNT_MASK, msg2); ++ shinfo->gso_size = DIV_ROUND_UP(data_len, agg_count); ++ shinfo->gso_segs = agg_count; ++ ++ skb->csum_start = skb_headroom(skb) + th_off; ++ skb->csum_offset = offsetof(struct tcphdr, check); ++ skb->ip_summed = CHECKSUM_PARTIAL; ++ ++ return skb; ++} ++ ++static struct sk_buff *airoha_qdma_build_rx_skb(struct airoha_queue *q, ++ struct airoha_qdma_desc *desc, ++ struct airoha_queue_entry *e, ++ struct net_device *netdev) ++{ ++ u32 msg2 = le32_to_cpu(READ_ONCE(desc->msg2)); ++ int qid = q - &q->qdma->q_rx[0]; ++ struct sk_buff *skb; ++ ++ if (FIELD_GET(QDMA_ETH_RXMSG_AGG_COUNT_MASK, msg2) > 1) { /* LRO */ ++ skb = airoha_qdma_lro_rx_skb(q, desc, e); ++ if (!skb) ++ return NULL; ++ } else { ++ u32 desc_ctrl = le32_to_cpu(READ_ONCE(desc->ctrl)); ++ u32 len = FIELD_GET(QDMA_DESC_LEN_MASK, desc_ctrl); ++ ++ skb = napi_build_skb(e->buf - AIROHA_RX_HEADROOM, q->buf_size); ++ if (!skb) ++ return NULL; ++ ++ skb_reserve(skb, AIROHA_RX_HEADROOM); ++ __skb_put(skb, len); ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++ } ++ ++ skb_mark_for_recycle(skb); ++ skb->dev = netdev; ++ skb_record_rx_queue(skb, qid); ++ skb->protocol = eth_type_trans(skb, netdev); ++ ++ return skb; ++} ++ + static int airoha_qdma_rx_process(struct airoha_queue *q, int budget) + { + enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool); +- struct airoha_qdma *qdma = q->qdma; +- struct airoha_eth *eth = qdma->eth; +- int qid = q - &qdma->q_rx[0]; ++ struct airoha_eth *eth = q->qdma->eth; + int done = 0; + + while (done < budget) { +@@ -696,18 +923,9 @@ static int airoha_qdma_rx_process(struct + + netdev = netdev_from_priv(dev); + if (!q->skb) { /* first buffer */ +- q->skb = napi_build_skb(e->buf - AIROHA_RX_HEADROOM, +- q->buf_size); ++ q->skb = airoha_qdma_build_rx_skb(q, desc, e, netdev); + if (!q->skb) + goto free_frag; +- +- skb_reserve(q->skb, AIROHA_RX_HEADROOM); +- __skb_put(q->skb, len); +- skb_mark_for_recycle(q->skb); +- q->skb->dev = netdev; +- q->skb->protocol = eth_type_trans(q->skb, netdev); +- q->skb->ip_summed = CHECKSUM_UNNECESSARY; +- skb_record_rx_queue(q->skb, qid); + } else { /* scattered frame */ + struct skb_shared_info *shinfo = skb_shinfo(q->skb); + int nr_frags = shinfo->nr_frags; +@@ -798,12 +1016,10 @@ static int airoha_qdma_rx_napi_poll(stru + static int airoha_qdma_init_rx_queue(struct airoha_queue *q, + struct airoha_qdma *qdma, int ndesc) + { +- const struct page_pool_params pp_params = { +- .order = 0, ++ struct page_pool_params pp_params = { + .pool_size = 256, + .flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV, + .dma_dir = DMA_FROM_DEVICE, +- .max_len = PAGE_SIZE, + .nid = NUMA_NO_NODE, + .dev = qdma->eth->dev, + .napi = &q->napi, +@@ -811,9 +1027,10 @@ static int airoha_qdma_init_rx_queue(str + struct airoha_eth *eth = qdma->eth; + int qid = q - &qdma->q_rx[0], thr; + dma_addr_t dma_addr; ++ bool lro_q; + +- q->buf_size = PAGE_SIZE / 2; + q->qdma = qdma; ++ lro_q = airoha_qdma_is_lro_queue(q); + + q->entry = devm_kzalloc(eth->dev, ndesc * sizeof(*q->entry), + GFP_KERNEL); +@@ -825,6 +1042,9 @@ static int airoha_qdma_init_rx_queue(str + if (!q->desc) + return -ENOMEM; + ++ pp_params.order = lro_q ? AIROHA_LRO_PAGE_ORDER : 0; ++ pp_params.max_len = PAGE_SIZE << pp_params.order; ++ + q->page_pool = page_pool_create(&pp_params); + if (IS_ERR(q->page_pool)) { + int err = PTR_ERR(q->page_pool); +@@ -833,6 +1053,7 @@ static int airoha_qdma_init_rx_queue(str + return err; + } + ++ q->buf_size = lro_q ? pp_params.max_len : pp_params.max_len / 2; + q->ndesc = ndesc; + netif_napi_add(eth->napi_dev, &q->napi, airoha_qdma_rx_napi_poll); + +@@ -846,7 +1067,12 @@ static int airoha_qdma_init_rx_queue(str + FIELD_PREP(RX_RING_THR_MASK, thr)); + airoha_qdma_rmw(qdma, REG_RX_DMA_IDX(qid), RX_RING_DMA_IDX_MASK, + FIELD_PREP(RX_RING_DMA_IDX_MASK, q->head)); +- airoha_qdma_set(qdma, REG_RX_SCATTER_CFG(qid), RX_RING_SG_EN_MASK); ++ if (lro_q) ++ airoha_qdma_clear(qdma, REG_RX_SCATTER_CFG(qid), ++ RX_RING_SG_EN_MASK); ++ else ++ airoha_qdma_set(qdma, REG_RX_SCATTER_CFG(qid), ++ RX_RING_SG_EN_MASK); + + airoha_qdma_fill_rx_queue(q); + +@@ -868,6 +1094,7 @@ static void airoha_qdma_cleanup_rx_queue + page_pool_get_dma_dir(q->page_pool)); + page_pool_put_full_page(q->page_pool, page, false); + /* Reset DMA descriptor */ ++ WRITE_ONCE(desc->tcp_ts_reply, 0); + WRITE_ONCE(desc->ctrl, 0); + WRITE_ONCE(desc->addr, 0); + WRITE_ONCE(desc->data, 0); +@@ -1809,6 +2036,37 @@ static void airoha_update_hw_stats(struc + spin_unlock(&port->lock); + } + ++static void airoha_update_netdev_features(struct airoha_gdm_dev *dev) ++{ ++ struct airoha_eth *eth = dev->eth; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { ++ struct airoha_gdm_port *port = dev->port; ++ int j; ++ ++ if (!port) ++ continue; ++ ++ for (j = 0; j < ARRAY_SIZE(port->devs); j++) { ++ struct airoha_gdm_dev *iter_dev = port->devs[j]; ++ struct net_device *netdev; ++ ++ if (!iter_dev || iter_dev == dev) ++ continue; ++ ++ if (iter_dev->qdma != dev->qdma) ++ continue; ++ ++ netdev = netdev_from_priv(iter_dev); ++ if (netdev->reg_state != NETREG_REGISTERED) ++ continue; ++ ++ netdev_update_features(netdev); ++ } ++ } ++} ++ + static int airoha_dev_open(struct net_device *netdev) + { + int err, len = ETH_HLEN + netdev->mtu + ETH_FCS_LEN; +@@ -1816,6 +2074,18 @@ static int airoha_dev_open(struct net_de + struct airoha_gdm_port *port = dev->port; + u32 cur_len, pse_port = FE_PSE_PORT_PPE1; + struct airoha_qdma *qdma = dev->qdma; ++ struct airoha_eth *eth = qdma->eth; ++ int qdma_id = qdma - ð->qdma[0]; ++ ++ /* HW LRO is configured on the QDMA and it is shared between ++ * all the devices using it. Refuse to open a second device on ++ * the same QDMA if LRO is enabled on any device sharing it. ++ */ ++ if (qdma->users && airoha_fe_lro_is_enabled(eth, qdma_id)) { ++ netdev_warn(netdev, "required to disable HW GRO on QDMA%d\n", ++ qdma_id); ++ return -EBUSY; ++ } + + err = phylink_of_phy_connect(dev->phylink, netdev->dev.of_node, 0); + if (err) { +@@ -1832,13 +2102,13 @@ static int airoha_dev_open(struct net_de + + /* It seems GDM3 and GDM4 needs SPORT enabled to correctly work */ + if (netdev_uses_dsa(netdev) || port->id > 2) +- airoha_fe_set(qdma->eth, REG_GDM_INGRESS_CFG(port->id), ++ airoha_fe_set(eth, REG_GDM_INGRESS_CFG(port->id), + GDM_STAG_EN_MASK); + else +- airoha_fe_clear(qdma->eth, REG_GDM_INGRESS_CFG(port->id), ++ airoha_fe_clear(eth, REG_GDM_INGRESS_CFG(port->id), + GDM_STAG_EN_MASK); + +- cur_len = airoha_fe_get(qdma->eth, REG_GDM_LEN_CFG(port->id), ++ cur_len = airoha_fe_get(eth, REG_GDM_LEN_CFG(port->id), + GDM_LONG_LEN_MASK); + if (!port->users || len > cur_len) { + /* Opening a sibling net_device with a larger MTU updates the +@@ -1846,7 +2116,7 @@ static int airoha_dev_open(struct net_de + * multiple net_devices with different MTUs to share the same + * GDM port. + */ +- airoha_fe_rmw(qdma->eth, REG_GDM_LEN_CFG(port->id), ++ airoha_fe_rmw(eth, REG_GDM_LEN_CFG(port->id), + GDM_SHORT_LEN_MASK | GDM_LONG_LEN_MASK, + FIELD_PREP(GDM_SHORT_LEN_MASK, 60) | + FIELD_PREP(GDM_LONG_LEN_MASK, len)); +@@ -1859,11 +2129,16 @@ static int airoha_dev_open(struct net_de + qdma->users++; + + if (!airoha_is_lan_gdm_dev(dev) && +- airoha_ppe_is_enabled(qdma->eth, 1)) ++ airoha_ppe_is_enabled(eth, 1)) + pse_port = FE_PSE_PORT_PPE2; +- airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id), ++ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), + pse_port); + ++ if (netdev->features & NETIF_F_GRO_HW) ++ airoha_dev_lro_enable(dev); ++ ++ airoha_update_netdev_features(dev); ++ + return 0; + } + +@@ -1896,6 +2171,7 @@ static int airoha_dev_stop(struct net_de + struct airoha_gdm_dev *dev = netdev_priv(netdev); + struct airoha_gdm_port *port = dev->port; + struct airoha_qdma *qdma = dev->qdma; ++ struct airoha_eth *eth = qdma->eth; + int i; + + netif_tx_disable(netdev); +@@ -1904,9 +2180,9 @@ static int airoha_dev_stop(struct net_de + netdev_tx_reset_subqueue(netdev, i); + + if (--port->users) +- airoha_set_port_mtu(dev->eth, port); ++ airoha_set_port_mtu(eth, port); + else +- airoha_set_gdm_port_fwd_cfg(qdma->eth, ++ airoha_set_gdm_port_fwd_cfg(eth, + REG_GDM_FWD_CFG(port->id), + FE_PSE_PORT_DROP); + +@@ -1923,6 +2199,8 @@ static int airoha_dev_stop(struct net_de + } + } + ++ airoha_update_netdev_features(dev); ++ + phylink_stop(dev->phylink); + phylink_disconnect_phy(dev->phylink); + +@@ -2195,6 +2473,38 @@ int airoha_get_fe_port(struct airoha_gdm + } + } + ++static netdev_features_t airoha_dev_fix_features(struct net_device *netdev, ++ netdev_features_t features) ++{ ++ struct airoha_gdm_dev *dev = netdev_priv(netdev); ++ struct airoha_qdma *qdma = dev->qdma; ++ ++ if (qdma->users > 1) ++ features &= ~NETIF_F_GRO_HW; ++ ++ return features; ++} ++ ++static int airoha_dev_set_features(struct net_device *netdev, ++ netdev_features_t features) ++{ ++ netdev_features_t diff = netdev->features ^ features; ++ struct airoha_gdm_dev *dev = netdev_priv(netdev); ++ struct airoha_qdma *qdma = dev->qdma; ++ struct airoha_eth *eth = qdma->eth; ++ int qdma_id = qdma - ð->qdma[0]; ++ ++ if (!(diff & NETIF_F_GRO_HW)) ++ return 0; ++ ++ if (features & NETIF_F_GRO_HW) ++ airoha_dev_lro_enable(dev); ++ else ++ airoha_fe_lro_disable(eth, qdma_id); ++ ++ return 0; ++} ++ + static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb, + struct net_device *netdev) + { +@@ -3146,6 +3456,8 @@ static const struct net_device_ops airoh + .ndo_stop = airoha_dev_stop, + .ndo_change_mtu = airoha_dev_change_mtu, + .ndo_select_queue = airoha_dev_select_queue, ++ .ndo_fix_features = airoha_dev_fix_features, ++ .ndo_set_features = airoha_dev_set_features, + .ndo_start_xmit = airoha_dev_xmit, + .ndo_get_stats64 = airoha_dev_get_stats64, + .ndo_set_mac_address = airoha_dev_set_macaddr, +@@ -3387,11 +3699,9 @@ static int airoha_alloc_gdm_device(struc + netdev->ethtool_ops = &airoha_ethtool_ops; + netdev->max_mtu = AIROHA_MAX_MTU; + netdev->watchdog_timeo = 5 * HZ; +- netdev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | NETIF_F_TSO6 | +- NETIF_F_IPV6_CSUM | NETIF_F_SG | NETIF_F_TSO | +- NETIF_F_HW_TC; +- netdev->features |= netdev->hw_features; +- netdev->vlan_features = netdev->hw_features; ++ netdev->hw_features = AIROHA_HW_FEATURES | NETIF_F_LRO; ++ netdev->features |= AIROHA_HW_FEATURES; ++ netdev->vlan_features = AIROHA_HW_FEATURES; + SET_NETDEV_DEV(netdev, eth->dev); + + /* reserve hw queues for HTB offloading */ +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -44,6 +44,18 @@ + (_n) == 15 ? 128 : \ + (_n) == 0 ? 1024 : 16) + ++#define AIROHA_LRO_PAGE_ORDER order_base_2(SZ_16K / PAGE_SIZE) ++#define AIROHA_MAX_NUM_LRO_QUEUES 8 ++#define AIROHA_RXQ_LRO_EN_MASK GENMASK(7, 0) ++#define AIROHA_RXQ_LRO_MAX_AGG_COUNT 64 ++#define AIROHA_RXQ_LRO_MAX_AGG_TIME 100 ++#define AIROHA_RXQ_LRO_MAX_AGE_TIME 2000 ++ ++#define AIROHA_HW_FEATURES \ ++ (NETIF_F_IP_CSUM | NETIF_F_RXCSUM | \ ++ NETIF_F_TSO6 | NETIF_F_IPV6_CSUM | \ ++ NETIF_F_SG | NETIF_F_TSO | NETIF_F_HW_TC) ++ + #define PSE_RSV_PAGES 128 + #define PSE_QUEUE_RSV_PAGES 64 + +@@ -676,6 +688,18 @@ static inline bool airoha_is_7583(struct + return eth->soc->version == 0x7583; + } + ++static inline bool airoha_qdma_is_lro_queue(struct airoha_queue *q) ++{ ++ struct airoha_qdma *qdma = q->qdma; ++ int qid = q - &qdma->q_rx[0]; ++ ++ /* EN7581 SoC supports at most 8 LRO rx queues */ ++ BUILD_BUG_ON(hweight32(AIROHA_RXQ_LRO_EN_MASK) > ++ AIROHA_MAX_NUM_LRO_QUEUES); ++ ++ return !!(AIROHA_RXQ_LRO_EN_MASK & BIT(qid)); ++} ++ + int airoha_get_fe_port(struct airoha_gdm_dev *dev); + bool airoha_is_valid_gdm_dev(struct airoha_eth *eth, + struct airoha_gdm_dev *dev); +--- a/drivers/net/ethernet/airoha/airoha_regs.h ++++ b/drivers/net/ethernet/airoha/airoha_regs.h +@@ -122,6 +122,20 @@ + #define CDM_CRSN_QSEL_REASON_MASK(_n) \ + GENMASK(4 + (((_n) % 4) << 3), (((_n) % 4) << 3)) + ++#define REG_CDM_LRO_RXQ(_n, _m) (CDM_BASE(_n) + 0x78 + ((_m) & 0x4)) ++#define LRO_RXQ_MASK(_n) GENMASK(4 + (((_n) & 0x3) << 3), ((_n) & 0x3) << 3) ++ ++#define REG_CDM_LRO_EN(_n) (CDM_BASE(_n) + 0x80) ++#define LRO_RXQ_EN_MASK GENMASK(7, 0) ++ ++#define REG_CDM_LRO_LIMIT(_n) (CDM_BASE(_n) + 0x84) ++#define CDM_LRO_AGG_NUM_MASK GENMASK(23, 16) ++#define CDM_LRO_AGG_SIZE_MASK GENMASK(15, 0) ++ ++#define REG_CDM_LRO_AGE_TIME(_n) (CDM_BASE(_n) + 0x88) ++#define CDM_LRO_AGE_TIME_MASK GENMASK(31, 16) ++#define CDM_LRO_AGG_TIME_MASK GENMASK(15, 0) ++ + #define REG_GDM_FWD_CFG(_n) GDM_BASE(_n) + #define GDM_PAD_EN_MASK BIT(28) + #define GDM_DROP_CRC_ERR_MASK BIT(23) +@@ -895,9 +909,15 @@ + #define QDMA_ETH_RXMSG_SPORT_MASK GENMASK(25, 21) + #define QDMA_ETH_RXMSG_CRSN_MASK GENMASK(20, 16) + #define QDMA_ETH_RXMSG_PPE_ENTRY_MASK GENMASK(15, 0) ++/* RX MSG2 */ ++#define QDMA_ETH_RXMSG_AGG_COUNT_MASK GENMASK(31, 24) ++#define QDMA_ETH_RXMSG_L2_LEN_MASK GENMASK(6, 0) ++/* RX MSG3 */ ++#define QDMA_ETH_RXMSG_AGG_LEN_MASK GENMASK(31, 16) ++#define QDMA_ETH_RXMSG_TCP_WIN_MASK GENMASK(15, 0) + + struct airoha_qdma_desc { +- __le32 rsv; ++ __le32 tcp_ts_reply; + __le32 ctrl; + __le32 addr; + __le32 data; diff --git a/target/linux/airoha/patches-6.18/916-net-airoha-Implement-LRO-TCP-support.patch b/target/linux/airoha/patches-6.18/916-net-airoha-Implement-LRO-TCP-support.patch deleted file mode 100644 index 7636ecbbc8..0000000000 --- a/target/linux/airoha/patches-6.18/916-net-airoha-Implement-LRO-TCP-support.patch +++ /dev/null @@ -1,392 +0,0 @@ -From 598e1ddfe85ad0f4778eeadd5d878209dd931280 Mon Sep 17 00:00:00 2001 -Message-ID: <598e1ddfe85ad0f4778eeadd5d878209dd931280.1779112628.git.lorenzo@kernel.org> -From: Lorenzo Bianconi -Date: Thu, 14 May 2026 20:25:19 +0200 -Subject: [PATCH] net: airoha: Implement LRO TCP support - -Signed-off-by: Lorenzo Bianconi ---- - drivers/net/ethernet/airoha/airoha_eth.c | 178 ++++++++++++++++++++-- - drivers/net/ethernet/airoha/airoha_eth.h | 23 +++ - drivers/net/ethernet/airoha/airoha_regs.h | 22 ++- - 3 files changed, 208 insertions(+), 15 deletions(-) - ---- a/drivers/net/ethernet/airoha/airoha_eth.c -+++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - #include - - #include "airoha_regs.h" -@@ -439,6 +440,48 @@ static void airoha_fe_crsn_qsel_init(str - CDM_CRSN_QSEL_Q1)); - } - -+static void airoha_fe_lro_init_rx_queue(struct airoha_eth *eth, int qdma_id, -+ int lro_queue_index, int qid, -+ int buf_size) -+{ -+ int id = qdma_id + 1; -+ -+ airoha_fe_rmw(eth, REG_CDM_LRO_LIMIT(id), -+ CDM_LRO_AGG_NUM_MASK | CDM_LRO_AGG_SIZE_MASK, -+ FIELD_PREP(CDM_LRO_AGG_SIZE_MASK, buf_size) | -+ FIELD_PREP(CDM_LRO_AGG_NUM_MASK, -+ AIROHA_RXQ_LRO_MAX_AGG_COUNT)); -+ airoha_fe_rmw(eth, REG_CDM_LRO_AGE_TIME(id), -+ CDM_LRO_AGE_TIME_MASK | CDM_LRO_AGG_TIME_MASK, -+ FIELD_PREP(CDM_LRO_AGE_TIME_MASK, -+ AIROHA_RXQ_LRO_MAX_AGE_TIME) | -+ FIELD_PREP(CDM_LRO_AGG_TIME_MASK, -+ AIROHA_RXQ_LRO_MAX_AGG_TIME)); -+ airoha_fe_rmw(eth, REG_CDM_LRO_RXQ(id, lro_queue_index), -+ LRO_RXQ_MASK(lro_queue_index), -+ __field_prep(LRO_RXQ_MASK(lro_queue_index), qid)); -+ airoha_fe_set(eth, REG_CDM_LRO_EN(id), BIT(lro_queue_index)); -+} -+ -+static void airoha_fe_lro_disable(struct airoha_eth *eth, int qdma_id) -+{ -+ int i, id = qdma_id + 1; -+ -+ airoha_fe_clear(eth, REG_CDM_LRO_EN(id), LRO_RXQ_EN_MASK); -+ airoha_fe_clear(eth, REG_CDM_LRO_LIMIT(id), -+ CDM_LRO_AGG_NUM_MASK | CDM_LRO_AGG_SIZE_MASK); -+ airoha_fe_clear(eth, REG_CDM_LRO_AGE_TIME(id), -+ CDM_LRO_AGE_TIME_MASK | CDM_LRO_AGG_TIME_MASK); -+ for (i = 0; i < AIROHA_MAX_NUM_LRO_QUEUES; i++) -+ airoha_fe_clear(eth, REG_CDM_LRO_RXQ(id, i), LRO_RXQ_MASK(i)); -+} -+ -+static bool airoha_fe_lro_is_enabled(struct airoha_eth *eth, int qdma_id) -+{ -+ return airoha_fe_get(eth, REG_CDM_LRO_EN(qdma_id + 1), -+ LRO_RXQ_EN_MASK); -+} -+ - static int airoha_fe_init(struct airoha_eth *eth) - { - airoha_fe_maccr_init(eth); -@@ -603,6 +646,85 @@ static int airoha_qdma_get_gdm_port(stru - return port >= ARRAY_SIZE(eth->ports) ? -EINVAL : port; - } - -+static int airoha_qdma_lro_rx_process(struct airoha_queue *q, -+ struct airoha_qdma_desc *desc) -+{ -+ u32 desc_ctrl = le32_to_cpu(READ_ONCE(desc->ctrl)); -+ u32 msg1 = le32_to_cpu(READ_ONCE(desc->msg1)); -+ u32 msg2 = le32_to_cpu(READ_ONCE(desc->msg2)); -+ u32 msg3 = le32_to_cpu(READ_ONCE(desc->msg3)); -+ struct sk_buff *skb = q->skb; -+ u32 len, th_off, tcp_ack_seq; -+ u16 tcp_win, l2_len; -+ struct tcphdr *th; -+ bool ipv4, ipv6; -+ -+ if (FIELD_GET(QDMA_ETH_RXMSG_AGG_COUNT_MASK, msg2) <= 1) -+ return 0; -+ -+ ipv4 = FIELD_GET(QDMA_ETH_RXMSG_IP4_MASK, msg1); -+ ipv6 = FIELD_GET(QDMA_ETH_RXMSG_IP6_MASK, msg1); -+ if (!ipv4 && !ipv6) -+ return -EOPNOTSUPP; -+ -+ l2_len = FIELD_GET(QDMA_ETH_RXMSG_L2_LEN_MASK, msg2); -+ len = FIELD_GET(QDMA_DESC_LEN_MASK, desc_ctrl); -+ if (ipv4) { -+ struct iphdr *iph; -+ -+ if (!pskb_may_pull(skb, l2_len + sizeof(*iph))) -+ return -EINVAL; -+ -+ iph = (struct iphdr *)(skb->data + l2_len); -+ if (iph->protocol != IPPROTO_TCP) -+ return -EOPNOTSUPP; -+ -+ iph->tot_len = cpu_to_be16(len - l2_len); -+ iph->check = 0; -+ iph->check = ip_fast_csum((void *)iph, iph->ihl); -+ th_off = l2_len + (iph->ihl << 2); -+ } else { -+ struct ipv6hdr *ip6h; -+ -+ if (!pskb_may_pull(skb, l2_len + sizeof(*ip6h))) -+ return -EINVAL; -+ -+ ip6h = (struct ipv6hdr *)(skb->data + l2_len); -+ if (ip6h->nexthdr != NEXTHDR_TCP) -+ return -EOPNOTSUPP; -+ -+ ip6h->payload_len = cpu_to_be16(len - l2_len - sizeof(*ip6h)); -+ th_off = l2_len + sizeof(*ip6h); -+ } -+ -+ tcp_win = FIELD_GET(QDMA_ETH_RXMSG_TCP_WIN_MASK, msg3); -+ tcp_ack_seq = le32_to_cpu(READ_ONCE(desc->data)); -+ -+ if (!pskb_may_pull(skb, th_off + sizeof(*th))) -+ return -EINVAL; -+ -+ th = (struct tcphdr *)(skb->data + th_off); -+ th->ack_seq = cpu_to_be32(tcp_ack_seq); -+ th->window = cpu_to_be16(tcp_win); -+ -+ /* Check tcp timestamp option */ -+ if (th->doff == (sizeof(*th) + TCPOLEN_TSTAMP_ALIGNED) / 4) { -+ __be32 *topt = (__be32 *)(th + 1); -+ -+ if (*topt == cpu_to_be32((TCPOPT_NOP << 24) | -+ (TCPOPT_NOP << 16) | -+ (TCPOPT_TIMESTAMP << 8) | -+ TCPOLEN_TIMESTAMP)) { -+ __le32 tcp_ts_reply = READ_ONCE(desc->tcp_ts_reply); -+ -+ put_unaligned_be32(le32_to_cpu(tcp_ts_reply), -+ topt + 2); -+ } -+ } -+ -+ return 0; -+} -+ - static int airoha_qdma_rx_process(struct airoha_queue *q, int budget) - { - enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool); -@@ -650,11 +772,15 @@ static int airoha_qdma_rx_process(struct - - skb_reserve(q->skb, AIROHA_RX_HEADROOM); - __skb_put(q->skb, len); -- skb_mark_for_recycle(q->skb); - q->skb->dev = port->dev; -- q->skb->protocol = eth_type_trans(q->skb, port->dev); - q->skb->ip_summed = CHECKSUM_UNNECESSARY; - skb_record_rx_queue(q->skb, qid); -+ -+ if (airoha_qdma_lro_rx_process(q, desc) < 0) -+ goto free_frag; -+ -+ q->skb->protocol = eth_type_trans(q->skb, port->dev); -+ skb_mark_for_recycle(q->skb); - } else { /* scattered frame */ - struct skb_shared_info *shinfo = skb_shinfo(q->skb); - int nr_frags = shinfo->nr_frags; -@@ -743,12 +869,10 @@ static int airoha_qdma_rx_napi_poll(stru - static int airoha_qdma_init_rx_queue(struct airoha_queue *q, - struct airoha_qdma *qdma, int ndesc) - { -- const struct page_pool_params pp_params = { -- .order = 0, -+ struct page_pool_params pp_params = { - .pool_size = 256, - .flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV, - .dma_dir = DMA_FROM_DEVICE, -- .max_len = PAGE_SIZE, - .nid = NUMA_NO_NODE, - .dev = qdma->eth->dev, - .napi = &q->napi, -@@ -756,9 +880,10 @@ static int airoha_qdma_init_rx_queue(str - struct airoha_eth *eth = qdma->eth; - int qid = q - &qdma->q_rx[0], thr; - dma_addr_t dma_addr; -+ bool lro_q; - -- q->buf_size = PAGE_SIZE / 2; - q->qdma = qdma; -+ lro_q = airoha_qdma_is_lro_queue(q); - - q->entry = devm_kzalloc(eth->dev, ndesc * sizeof(*q->entry), - GFP_KERNEL); -@@ -770,6 +895,9 @@ static int airoha_qdma_init_rx_queue(str - if (!q->desc) - return -ENOMEM; - -+ pp_params.order = lro_q ? AIROHA_LRO_PAGE_ORDER : 0; -+ pp_params.max_len = PAGE_SIZE << pp_params.order; -+ - q->page_pool = page_pool_create(&pp_params); - if (IS_ERR(q->page_pool)) { - int err = PTR_ERR(q->page_pool); -@@ -778,6 +906,7 @@ static int airoha_qdma_init_rx_queue(str - return err; - } - -+ q->buf_size = lro_q ? pp_params.max_len : pp_params.max_len / 2; - q->ndesc = ndesc; - netif_napi_add(eth->napi_dev, &q->napi, airoha_qdma_rx_napi_poll); - -@@ -2034,6 +2163,67 @@ int airoha_get_fe_port(struct airoha_gdm - } - } - -+static int airoha_dev_set_features(struct net_device *dev, -+ netdev_features_t features) -+{ -+ netdev_features_t diff = dev->features ^ features; -+ struct airoha_gdm_port *port = netdev_priv(dev); -+ struct airoha_qdma *qdma = port->qdma; -+ struct airoha_eth *eth = qdma->eth; -+ int qdma_id = qdma - ð->qdma[0]; -+ int i; -+ -+ if (!(diff & NETIF_F_LRO)) -+ return 0; -+ -+ if (netif_running(dev)) -+ return -EBUSY; -+ -+ /* reset LRO configuration */ -+ if (features & NETIF_F_LRO) { -+ int lro_queue_index = 0; -+ -+ if (airoha_fe_lro_is_enabled(eth, qdma_id)) -+ return 0; -+ -+ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { -+ struct airoha_queue *q = &qdma->q_rx[i]; -+ u32 size; -+ -+ if (!q->ndesc) -+ continue; -+ -+ if (!airoha_qdma_is_lro_queue(q)) -+ continue; -+ -+ size = SKB_WITH_OVERHEAD(AIROHA_RX_LEN(q->buf_size)); -+ size = min_t(u32, size, CDM_LRO_AGG_SIZE_MASK); -+ airoha_fe_lro_init_rx_queue(eth, qdma_id, -+ lro_queue_index, i, size); -+ lro_queue_index++; -+ } -+ } else { -+ for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { -+ struct airoha_gdm_port *p = eth->ports[i]; -+ -+ if (!p) -+ continue; -+ -+ if (p->qdma != qdma) -+ continue; -+ -+ if (p->dev == dev) -+ continue; -+ -+ if (p->dev->features & NETIF_F_LRO) -+ return 0; -+ } -+ airoha_fe_lro_disable(eth, qdma_id); -+ } -+ -+ return 0; -+} -+ - static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb, - struct net_device *dev) - { -@@ -2933,6 +3123,7 @@ static const struct net_device_ops airoh - .ndo_stop = airoha_dev_stop, - .ndo_change_mtu = airoha_dev_change_mtu, - .ndo_select_queue = airoha_dev_select_queue, -+ .ndo_set_features = airoha_dev_set_features, - .ndo_start_xmit = airoha_dev_xmit, - .ndo_get_stats64 = airoha_dev_get_stats64, - .ndo_set_mac_address = airoha_dev_set_macaddr, -@@ -3150,12 +3341,9 @@ static int airoha_alloc_gdm_port(struct - dev->ethtool_ops = &airoha_ethtool_ops; - dev->max_mtu = AIROHA_MAX_MTU; - dev->watchdog_timeo = 5 * HZ; -- dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | -- NETIF_F_TSO6 | NETIF_F_IPV6_CSUM | -- NETIF_F_SG | NETIF_F_TSO | -- NETIF_F_HW_TC; -- dev->features |= dev->hw_features; -- dev->vlan_features = dev->hw_features; -+ dev->hw_features = AIROHA_HW_FEATURES | NETIF_F_LRO; -+ dev->features |= AIROHA_HW_FEATURES; -+ dev->vlan_features = AIROHA_HW_FEATURES; - dev->dev.of_node = np; - SET_NETDEV_DEV(dev, eth->dev); - ---- a/drivers/net/ethernet/airoha/airoha_eth.h -+++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -43,6 +43,18 @@ - (_n) == 15 ? 128 : \ - (_n) == 0 ? 1024 : 16) - -+#define AIROHA_LRO_PAGE_ORDER 2 -+#define AIROHA_MAX_NUM_LRO_QUEUES 8 -+#define AIROHA_RXQ_LRO_EN_MASK 0xff000000 -+#define AIROHA_RXQ_LRO_MAX_AGG_COUNT 64 -+#define AIROHA_RXQ_LRO_MAX_AGG_TIME 100 -+#define AIROHA_RXQ_LRO_MAX_AGE_TIME 2000 /* 1ms */ -+ -+#define AIROHA_HW_FEATURES \ -+ (NETIF_F_IP_CSUM | NETIF_F_RXCSUM | \ -+ NETIF_F_TSO6 | NETIF_F_IPV6_CSUM | \ -+ NETIF_F_SG | NETIF_F_TSO | NETIF_F_HW_TC) -+ - #define PSE_RSV_PAGES 128 - #define PSE_QUEUE_RSV_PAGES 64 - -@@ -666,6 +678,18 @@ static inline bool airoha_is_7583(struct - return eth->soc->version == 0x7583; - } - -+static inline bool airoha_qdma_is_lro_queue(struct airoha_queue *q) -+{ -+ struct airoha_qdma *qdma = q->qdma; -+ int qid = q - &qdma->q_rx[0]; -+ -+ /* EN7581 SoC supports at most 8 LRO rx queues */ -+ BUILD_BUG_ON(hweight32(AIROHA_RXQ_LRO_EN_MASK) > -+ AIROHA_MAX_NUM_LRO_QUEUES); -+ -+ return !!(AIROHA_RXQ_LRO_EN_MASK & BIT(qid)); -+} -+ - int airoha_get_fe_port(struct airoha_gdm_port *port); - bool airoha_is_valid_gdm_port(struct airoha_eth *eth, - struct airoha_gdm_port *port); ---- a/drivers/net/ethernet/airoha/airoha_regs.h -+++ b/drivers/net/ethernet/airoha/airoha_regs.h -@@ -122,6 +122,20 @@ - #define CDM_CRSN_QSEL_REASON_MASK(_n) \ - GENMASK(4 + (((_n) % 4) << 3), (((_n) % 4) << 3)) - -+#define REG_CDM_LRO_RXQ(_n, _m) (CDM_BASE(_n) + 0x78 + ((_m) & 0x4)) -+#define LRO_RXQ_MASK(_n) GENMASK(4 + (((_n) & 0x3) << 3), ((_n) & 0x3) << 3) -+ -+#define REG_CDM_LRO_EN(_n) (CDM_BASE(_n) + 0x80) -+#define LRO_RXQ_EN_MASK GENMASK(7, 0) -+ -+#define REG_CDM_LRO_LIMIT(_n) (CDM_BASE(_n) + 0x84) -+#define CDM_LRO_AGG_NUM_MASK GENMASK(23, 16) -+#define CDM_LRO_AGG_SIZE_MASK GENMASK(15, 0) -+ -+#define REG_CDM_LRO_AGE_TIME(_n) (CDM_BASE(_n) + 0x88) -+#define CDM_LRO_AGE_TIME_MASK GENMASK(31, 16) -+#define CDM_LRO_AGG_TIME_MASK GENMASK(15, 0) -+ - #define REG_GDM_FWD_CFG(_n) GDM_BASE(_n) - #define GDM_PAD_EN_MASK BIT(28) - #define GDM_DROP_CRC_ERR_MASK BIT(23) -@@ -895,9 +909,15 @@ - #define QDMA_ETH_RXMSG_SPORT_MASK GENMASK(25, 21) - #define QDMA_ETH_RXMSG_CRSN_MASK GENMASK(20, 16) - #define QDMA_ETH_RXMSG_PPE_ENTRY_MASK GENMASK(15, 0) -+/* RX MSG2 */ -+#define QDMA_ETH_RXMSG_AGG_COUNT_MASK GENMASK(31, 24) -+#define QDMA_ETH_RXMSG_L2_LEN_MASK GENMASK(6, 0) -+/* RX MSG3 */ -+#define QDMA_ETH_RXMSG_AGG_LEN_MASK GENMASK(31, 16) -+#define QDMA_ETH_RXMSG_TCP_WIN_MASK GENMASK(15, 0) - - struct airoha_qdma_desc { -- __le32 rsv; -+ __le32 tcp_ts_reply; - __le32 ctrl; - __le32 addr; - __le32 data; diff --git a/target/linux/airoha/patches-6.18/920-10-net-airoha-Rename-airoha_set_gdm2_loopback-in-airoha.patch b/target/linux/airoha/patches-6.18/920-10-net-airoha-Rename-airoha_set_gdm2_loopback-in-airoha.patch deleted file mode 100644 index aca2ae2576..0000000000 --- a/target/linux/airoha/patches-6.18/920-10-net-airoha-Rename-airoha_set_gdm2_loopback-in-airoha.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 917f959d54efd09719bd5047aa4b9543615e131e Mon Sep 17 00:00:00 2001 -Message-ID: <917f959d54efd09719bd5047aa4b9543615e131e.1779348625.git.lorenzo@kernel.org> -In-Reply-To: -References: -From: Lorenzo Bianconi -Date: Fri, 19 Dec 2025 23:12:32 +0100 -Subject: [PATCH 10/13] net: airoha: Rename airoha_set_gdm2_loopback in - airoha_enable_gdm2_loopback - -This is a preliminary patch in order to allow the user to select if the -configured device will be used as hw lan or wan. - -Signed-off-by: Lorenzo Bianconi ---- - drivers/net/ethernet/airoha/airoha_eth.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/net/ethernet/airoha/airoha_eth.c -+++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2056,7 +2056,7 @@ static int airoha_dev_set_macaddr(struct - return 0; - } - --static int airoha_set_gdm2_loopback(struct airoha_gdm_dev *dev) -+static int airoha_enable_gdm2_loopback(struct airoha_gdm_dev *dev) - { - struct airoha_gdm_port *port = dev->port; - struct airoha_eth *eth = dev->eth; -@@ -2188,7 +2188,7 @@ static int airoha_dev_init(struct net_de - (port->id == AIROHA_GDM3_IDX || port->id == AIROHA_GDM4_IDX)) { - int err; - -- err = airoha_set_gdm2_loopback(dev); -+ err = airoha_enable_gdm2_loopback(dev); - if (err) - return err; - } diff --git a/target/linux/airoha/patches-6.18/920-12-net-airoha-Add-ethtool-priv_flags-callbacks.patch b/target/linux/airoha/patches-6.18/920-12-net-airoha-Add-ethtool-priv_flags-callbacks.patch deleted file mode 100644 index f55b97253f..0000000000 --- a/target/linux/airoha/patches-6.18/920-12-net-airoha-Add-ethtool-priv_flags-callbacks.patch +++ /dev/null @@ -1,246 +0,0 @@ -From e928621a0bbd010b75624c77105ce31f2b8d2faf Mon Sep 17 00:00:00 2001 -Message-ID: -In-Reply-To: -References: -From: Lorenzo Bianconi -Date: Sat, 13 Dec 2025 09:45:09 +0100 -Subject: [PATCH 12/13] net: airoha: Add ethtool priv_flags callbacks - -Introduce ethtool priv_flags callbacks in order to allow the user to -select if the configured device will be used as hw lan or wan and enable -or disable gdm2 loopback (used for hw QoS). - -Tested-by: Madhur Agrawal -Signed-off-by: Lorenzo Bianconi ---- - drivers/net/ethernet/airoha/airoha_eth.c | 173 ++++++++++++++++++++++ - drivers/net/ethernet/airoha/airoha_regs.h | 1 + - 2 files changed, 174 insertions(+) - ---- a/drivers/net/ethernet/airoha/airoha_eth.c -+++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -1916,6 +1916,11 @@ static int airoha_dev_open(struct net_de - u32 cur_len, pse_port = FE_PSE_PORT_PPE1; - struct airoha_qdma *qdma = dev->qdma; - -+ if (port->id == AIROHA_GDM2_IDX && airoha_is_lan_gdm_dev(dev)) { -+ /* GDM2 can be used just as wan */ -+ return -EBUSY; -+ } -+ - #if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) { - err = phylink_of_phy_connect(dev->phylink, netdev->dev.of_node, 0); -@@ -2118,6 +2123,45 @@ static int airoha_enable_gdm2_loopback(s - return 0; - } - -+static int airoha_disable_gdm2_loopback(struct airoha_gdm_dev *dev) -+{ -+ struct airoha_eth *eth = dev->eth; -+ int i, src_port; -+ u32 pse_port; -+ -+ src_port = eth->soc->ops.get_sport(dev->port, dev->nbq); -+ if (src_port < 0) -+ return src_port; -+ -+ airoha_fe_clear(eth, -+ REG_SP_DFT_CPORT(src_port >> fls(SP_CPORT_DFT_MASK)), -+ SP_CPORT_MASK(src_port & SP_CPORT_DFT_MASK)); -+ -+ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX), -+ FE_PSE_PORT_DROP); -+ airoha_fe_clear(eth, REG_GDM_LPBK_CFG(AIROHA_GDM2_IDX), -+ LPBK_CHAN_MASK | LPBK_MODE_MASK | LPBK_EN_MASK); -+ pse_port = airoha_ppe_is_enabled(eth, 1) ? FE_PSE_PORT_PPE2 -+ : FE_PSE_PORT_PPE1; -+ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX), -+ pse_port); -+ -+ airoha_fe_rmw(eth, REG_FE_WAN_PORT, WAN0_MASK, -+ FIELD_PREP(WAN0_MASK, AIROHA_GDM2_IDX)); -+ -+ for (i = 0; i < eth->soc->num_ppe; i++) -+ airoha_fe_clear(eth, REG_PPE_DFT_CPORT(i, AIROHA_GDM2_IDX), -+ DFT_CPORT_MASK(AIROHA_GDM2_IDX)); -+ -+ /* Enable VIP and IFC for GDM2 */ -+ airoha_fe_set(eth, REG_FE_VIP_PORT_EN, BIT(AIROHA_GDM2_IDX)); -+ airoha_fe_set(eth, REG_FE_IFC_PORT_EN, BIT(AIROHA_GDM2_IDX)); -+ -+ airoha_fe_wr(eth, REG_SRC_PORT_FC_MAP6, FC_MAP6_DEF_VALUE); -+ -+ return 0; -+} -+ - static struct airoha_gdm_dev * - airoha_get_wan_gdm_dev(struct airoha_eth *eth) - { -@@ -2522,6 +2566,80 @@ error: - return NETDEV_TX_OK; - } - -+struct airoha_ethool_priv_flags { -+ char name[ETH_GSTRING_LEN]; -+ int (*handler)(struct net_device *netdev, u32 flags); -+}; -+ -+static int airoha_dev_set_wan_flag(struct net_device *netdev, u32 flags) -+{ -+ struct airoha_gdm_dev *dev = netdev_priv(netdev); -+ struct airoha_gdm_port *port = dev->port; -+ struct airoha_eth *eth = dev->eth; -+ -+ if (!((dev->flags ^ flags) & AIROHA_PRIV_F_WAN)) -+ return 0; -+ -+ if (netif_running(netdev)) -+ return -EBUSY; -+ -+ if (flags & AIROHA_PRIV_F_WAN) { -+ struct airoha_gdm_dev *wan_dev; -+ -+ /* Verify the wan device is not already configured */ -+ wan_dev = airoha_get_wan_gdm_dev(eth); -+ if (wan_dev && wan_dev != dev) -+ return -EBUSY; -+ -+ switch (port->id) { -+ case AIROHA_GDM2_IDX: -+ dev->flags |= AIROHA_PRIV_F_WAN; -+ airoha_dev_set_qdma(dev); -+ break; -+ case AIROHA_GDM3_IDX: -+ case AIROHA_GDM4_IDX: { -+ int err; -+ -+ dev->flags |= AIROHA_PRIV_F_WAN; -+ airoha_dev_set_qdma(dev); -+ -+ err = airoha_enable_gdm2_loopback(dev); -+ if (err) { -+ dev->flags &= ~AIROHA_PRIV_F_WAN; -+ return err; -+ } -+ break; -+ } -+ default: -+ return -EOPNOTSUPP; -+ } -+ } else { -+ switch (port->id) { -+ case AIROHA_GDM3_IDX: -+ case AIROHA_GDM4_IDX: { -+ int err; -+ -+ err = airoha_disable_gdm2_loopback(dev); -+ if (err) -+ return err; -+ break; -+ } -+ default: -+ break; -+ } -+ -+ dev->flags &= ~AIROHA_PRIV_F_WAN; -+ airoha_dev_set_qdma(dev); -+ } -+ -+ return airoha_set_macaddr(dev, netdev->dev_addr); -+} -+ -+static const struct airoha_ethool_priv_flags airoha_eth_priv_flags[] = { -+ { "wan", airoha_dev_set_wan_flag }, -+}; -+#define AIROHA_PRIV_FLAGS_STR_LEN ARRAY_SIZE(airoha_eth_priv_flags) -+ - static void airoha_ethtool_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *info) - { -@@ -2530,6 +2648,7 @@ static void airoha_ethtool_get_drvinfo(s - - strscpy(info->driver, eth->dev->driver->name, sizeof(info->driver)); - strscpy(info->bus_info, dev_name(eth->dev), sizeof(info->bus_info)); -+ info->n_priv_flags = AIROHA_PRIV_FLAGS_STR_LEN; - } - - static void airoha_ethtool_get_mac_stats(struct net_device *netdev, -@@ -2594,6 +2713,56 @@ airoha_ethtool_get_rmon_stats(struct net - } while (u64_stats_fetch_retry(&port->stats.syncp, start)); - } - -+static int airoha_ethtool_set_priv_flags(struct net_device *netdev, u32 flags) -+{ -+ int i; -+ -+ for (i = 0; i < AIROHA_PRIV_FLAGS_STR_LEN; i++) { -+ int err; -+ -+ if (!airoha_eth_priv_flags[i].handler) -+ continue; -+ -+ err = airoha_eth_priv_flags[i].handler(netdev, flags); -+ if (err) -+ return err; -+ } -+ -+ return 0; -+} -+ -+static u32 airoha_ethtool_get_priv_flags(struct net_device *netdev) -+{ -+ struct airoha_gdm_dev *dev = netdev_priv(netdev); -+ -+ return dev->flags; -+} -+ -+static int airoha_ethtool_get_sset_count(struct net_device *netdev, int sset) -+{ -+ switch (sset) { -+ case ETH_SS_PRIV_FLAGS: -+ return AIROHA_PRIV_FLAGS_STR_LEN; -+ default: -+ return -EOPNOTSUPP; -+ } -+} -+ -+static void airoha_ethtool_get_strings(struct net_device *netdev, -+ u32 stringset, u8 *data) -+{ -+ int i; -+ -+ switch (stringset) { -+ case ETH_SS_PRIV_FLAGS: -+ for (i = 0; i < AIROHA_PRIV_FLAGS_STR_LEN; i++) -+ ethtool_puts(&data, airoha_eth_priv_flags[i].name); -+ break; -+ default: -+ break; -+ } -+} -+ - static int airoha_qdma_set_chan_tx_sched(struct net_device *netdev, - int channel, enum tx_sched_mode mode, - const u16 *weights, u8 n_weights) -@@ -3315,6 +3484,10 @@ static const struct ethtool_ops airoha_e - .get_rmon_stats = airoha_ethtool_get_rmon_stats, - .get_link_ksettings = phy_ethtool_get_link_ksettings, - .get_link = ethtool_op_get_link, -+ .set_priv_flags = airoha_ethtool_set_priv_flags, -+ .get_priv_flags = airoha_ethtool_get_priv_flags, -+ .get_sset_count = airoha_ethtool_get_sset_count, -+ .get_strings = airoha_ethtool_get_strings, - }; - - static void airoha_mac_config(struct phylink_config *config, unsigned int mode, ---- a/drivers/net/ethernet/airoha/airoha_regs.h -+++ b/drivers/net/ethernet/airoha/airoha_regs.h -@@ -402,6 +402,7 @@ - - #define REG_SRC_PORT_FC_MAP6 0x2298 - #define FC_ID_OF_SRC_PORT_MASK(_n) GENMASK(4 + ((_n) << 3), ((_n) << 3)) -+#define FC_MAP6_DEF_VALUE 0x1b1a1918 - - #define REG_CDM5_RX_OQ1_DROP_CNT 0x29d4 - diff --git a/target/linux/airoha/patches-6.18/920-12-net-airoha-defer-GDM3-GDM4-WAN-mode-and-GDM2-loopbac.patch b/target/linux/airoha/patches-6.18/920-12-net-airoha-defer-GDM3-GDM4-WAN-mode-and-GDM2-loopbac.patch new file mode 100644 index 0000000000..757d54db70 --- /dev/null +++ b/target/linux/airoha/patches-6.18/920-12-net-airoha-defer-GDM3-GDM4-WAN-mode-and-GDM2-loopbac.patch @@ -0,0 +1,657 @@ +From e928621a0bbd010b75624c77105ce31f2b8d2faf Mon Sep 17 00:00:00 2001 +Message-ID: +In-Reply-To: +References: +From: Lorenzo Bianconi +Date: Sat, 13 Dec 2025 09:45:09 +0100 +Subject: [PATCH 12/13] net: airoha: Add ethtool priv_flags callbacks + +Introduce ethtool priv_flags callbacks in order to allow the user to +select if the configured device will be used as hw lan or wan and enable +or disable gdm2 loopback (used for hw QoS). + +Tested-by: Madhur Agrawal +Signed-off-by: Lorenzo Bianconi +--- + drivers/net/ethernet/airoha/airoha_eth.c | 173 ++++++++++++++++++++++ + drivers/net/ethernet/airoha/airoha_regs.h | 1 + + 2 files changed, 174 insertions(+) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -533,7 +533,7 @@ static bool airoha_fe_lro_is_enabled(str + + static void airoha_dev_lro_enable(struct airoha_gdm_dev *dev) + { +- struct airoha_qdma *qdma = dev->qdma; ++ struct airoha_qdma *qdma = airoha_qdma_deref(dev); + struct airoha_eth *eth = qdma->eth; + int qdma_id = qdma - ð->qdma[0]; + int i, lro_queue_index = 0; +@@ -1159,7 +1159,7 @@ static void airoha_qdma_wake_netdev_txqs + if (!dev) + continue; + +- if (dev->qdma != qdma) ++ if (rcu_access_pointer(dev->qdma) != qdma) + continue; + + netdev = netdev_from_priv(dev); +@@ -2055,7 +2055,8 @@ static void airoha_update_netdev_feature + if (!iter_dev || iter_dev == dev) + continue; + +- if (iter_dev->qdma != dev->qdma) ++ if (rcu_access_pointer(iter_dev->qdma) != ++ rcu_access_pointer(dev->qdma)) + continue; + + netdev = netdev_from_priv(iter_dev); +@@ -2067,20 +2068,57 @@ static void airoha_update_netdev_feature + } + } + ++static void airoha_qdma_start(struct airoha_qdma *qdma) ++{ ++ airoha_qdma_set(qdma, REG_QDMA_GLOBAL_CFG, ++ GLOBAL_CFG_TX_DMA_EN_MASK | ++ GLOBAL_CFG_RX_DMA_EN_MASK); ++ qdma->users++; ++} ++ ++static void airoha_qdma_stop(struct airoha_qdma *qdma) ++{ ++ u32 status; ++ ++ if (--qdma->users) ++ return; ++ ++ airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG, ++ GLOBAL_CFG_TX_DMA_EN_MASK | ++ GLOBAL_CFG_RX_DMA_EN_MASK); ++ ++ if (read_poll_timeout(airoha_qdma_rr, status, ++ !(status & (GLOBAL_CFG_TX_DMA_BUSY_MASK | ++ GLOBAL_CFG_RX_DMA_BUSY_MASK)), ++ USEC_PER_MSEC, 50 * USEC_PER_MSEC, true, ++ qdma, REG_QDMA_GLOBAL_CFG)) ++ dev_warn(qdma->eth->dev, "QDMA DMA engine busy timeout\n"); ++ ++ for (int i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) { ++ if (!qdma->q_tx[i].ndesc) ++ continue; ++ ++ airoha_qdma_cleanup_tx_queue(&qdma->q_tx[i]); ++ } ++} ++ + static int airoha_dev_open(struct net_device *netdev) + { + int err, len = ETH_HLEN + netdev->mtu + ETH_FCS_LEN; + struct airoha_gdm_dev *dev = netdev_priv(netdev); + struct airoha_gdm_port *port = dev->port; + u32 cur_len, pse_port = FE_PSE_PORT_PPE1; +- struct airoha_qdma *qdma = dev->qdma; +- struct airoha_eth *eth = qdma->eth; +- int qdma_id = qdma - ð->qdma[0]; ++ struct airoha_eth *eth = dev->eth; ++ struct airoha_qdma *qdma; ++ int qdma_id; + + /* HW LRO is configured on the QDMA and it is shared between + * all the devices using it. Refuse to open a second device on + * the same QDMA if LRO is enabled on any device sharing it. + */ ++ qdma = airoha_qdma_deref(dev); ++ qdma_id = qdma - ð->qdma[0]; ++ + if (qdma->users && airoha_fe_lro_is_enabled(eth, qdma_id)) { + netdev_warn(netdev, "required to disable HW GRO on QDMA%d\n", + qdma_id); +@@ -2123,10 +2161,7 @@ static int airoha_dev_open(struct net_de + } + port->users++; + +- airoha_qdma_set(qdma, REG_QDMA_GLOBAL_CFG, +- GLOBAL_CFG_TX_DMA_EN_MASK | +- GLOBAL_CFG_RX_DMA_EN_MASK); +- qdma->users++; ++ airoha_qdma_start(qdma); + + if (!airoha_is_lan_gdm_dev(dev) && + airoha_ppe_is_enabled(eth, 1)) +@@ -2170,8 +2205,7 @@ static int airoha_dev_stop(struct net_de + { + struct airoha_gdm_dev *dev = netdev_priv(netdev); + struct airoha_gdm_port *port = dev->port; +- struct airoha_qdma *qdma = dev->qdma; +- struct airoha_eth *eth = qdma->eth; ++ struct airoha_qdma *qdma; + int i; + + netif_tx_disable(netdev); +@@ -2179,26 +2213,14 @@ static int airoha_dev_stop(struct net_de + for (i = 0; i < netdev->num_tx_queues; i++) + netdev_tx_reset_subqueue(netdev, i); + ++ qdma = airoha_qdma_deref(dev); + if (--port->users) +- airoha_set_port_mtu(eth, port); ++ airoha_set_port_mtu(dev->eth, port); + else +- airoha_set_gdm_port_fwd_cfg(eth, ++ airoha_set_gdm_port_fwd_cfg(qdma->eth, + REG_GDM_FWD_CFG(port->id), + FE_PSE_PORT_DROP); +- +- if (!--qdma->users) { +- airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG, +- GLOBAL_CFG_TX_DMA_EN_MASK | +- GLOBAL_CFG_RX_DMA_EN_MASK); +- +- for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) { +- if (!qdma->q_tx[i].ndesc) +- continue; +- +- airoha_qdma_cleanup_tx_queue(&qdma->q_tx[i]); +- } +- } +- ++ airoha_qdma_stop(qdma); + airoha_update_netdev_features(dev); + + phylink_stop(dev->phylink); +@@ -2288,6 +2310,53 @@ static int airoha_enable_gdm2_loopback(s + return 0; + } + ++static int airoha_disable_gdm2_loopback(struct airoha_gdm_dev *dev) ++{ ++ struct airoha_gdm_port *port = dev->port; ++ struct airoha_eth *eth = dev->eth; ++ int i, src_port; ++ u32 pse_port; ++ ++ src_port = eth->soc->ops.get_sport(dev->port, dev->nbq); ++ if (src_port < 0) ++ return src_port; ++ ++ airoha_fe_clear(eth, ++ REG_SP_DFT_CPORT(src_port >> fls(SP_CPORT_DFT_MASK)), ++ SP_CPORT_MASK(src_port & SP_CPORT_DFT_MASK)); ++ ++ airoha_fe_set(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX), ++ GDM_STRIP_CRC_MASK); ++ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX), ++ FE_PSE_PORT_DROP); ++ airoha_fe_clear(eth, REG_GDM_LPBK_CFG(AIROHA_GDM2_IDX), ++ LPBK_CHAN_MASK | LPBK_MODE_MASK | LPBK_EN_MASK); ++ pse_port = airoha_ppe_is_enabled(eth, 1) ? FE_PSE_PORT_PPE2 ++ : FE_PSE_PORT_PPE1; ++ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX), ++ pse_port); ++ ++ airoha_fe_rmw(eth, REG_FE_WAN_PORT, WAN0_MASK, ++ FIELD_PREP(WAN0_MASK, AIROHA_GDM2_IDX)); ++ ++ for (i = 0; i < eth->soc->num_ppe; i++) ++ airoha_fe_clear(eth, REG_PPE_DFT_CPORT(i, AIROHA_GDM2_IDX), ++ DFT_CPORT_MASK(AIROHA_GDM2_IDX)); ++ ++ /* Enable VIP and IFC for GDM2 */ ++ airoha_fe_set(eth, REG_FE_VIP_PORT_EN, BIT(AIROHA_GDM2_IDX)); ++ airoha_fe_set(eth, REG_FE_IFC_PORT_EN, BIT(AIROHA_GDM2_IDX)); ++ ++ if (port->id == AIROHA_GDM4_IDX && airoha_is_7581(eth)) { ++ u32 mask = FC_ID_OF_SRC_PORT_MASK(dev->nbq); ++ ++ airoha_fe_rmw(eth, REG_SRC_PORT_FC_MAP6, mask, ++ FC_MAP6_DEF_VALUE & mask); ++ } ++ ++ return 0; ++} ++ + static struct airoha_gdm_dev * + airoha_get_wan_gdm_dev(struct airoha_eth *eth) + { +@@ -2314,15 +2383,30 @@ airoha_get_wan_gdm_dev(struct airoha_eth + static void airoha_dev_set_qdma(struct airoha_gdm_dev *dev) + { + struct net_device *netdev = netdev_from_priv(dev); ++ struct airoha_qdma *cur_qdma, *qdma; + struct airoha_eth *eth = dev->eth; + int ppe_id; + + /* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */ +- dev->qdma = ð->qdma[!airoha_is_lan_gdm_dev(dev)]; +- netdev->irq = dev->qdma->irq_banks[0].irq; ++ qdma = ð->qdma[!airoha_is_lan_gdm_dev(dev)]; ++ cur_qdma = airoha_qdma_deref(dev); ++ if (netif_running(netdev)) ++ airoha_qdma_start(qdma); ++ ++ rcu_assign_pointer(dev->qdma, qdma); ++ netdev->irq = qdma->irq_banks[0].irq; + + ppe_id = !airoha_is_lan_gdm_dev(dev) && airoha_ppe_is_enabled(eth, 1); + airoha_ppe_set_cpu_port(dev, ppe_id, airoha_get_fe_port(dev)); ++ ++ if (!cur_qdma) ++ return; ++ ++ synchronize_rcu(); ++ netif_tx_wake_all_queues(netdev); ++ ++ if (netif_running(netdev)) ++ airoha_qdma_stop(cur_qdma); + } + + static int airoha_dev_init(struct net_device *netdev) +@@ -2477,8 +2561,9 @@ static netdev_features_t airoha_dev_fix_ + netdev_features_t features) + { + struct airoha_gdm_dev *dev = netdev_priv(netdev); +- struct airoha_qdma *qdma = dev->qdma; ++ struct airoha_qdma *qdma; + ++ qdma = airoha_qdma_deref(dev); + if (qdma->users > 1) + features &= ~NETIF_F_GRO_HW; + +@@ -2490,9 +2575,8 @@ static int airoha_dev_set_features(struc + { + netdev_features_t diff = netdev->features ^ features; + struct airoha_gdm_dev *dev = netdev_priv(netdev); +- struct airoha_qdma *qdma = dev->qdma; +- struct airoha_eth *eth = qdma->eth; +- int qdma_id = qdma - ð->qdma[0]; ++ struct airoha_qdma *qdma = airoha_qdma_deref(dev); ++ int qdma_id = qdma - &dev->eth->qdma[0]; + + if (!(diff & NETIF_F_GRO_HW)) + return 0; +@@ -2500,7 +2584,7 @@ static int airoha_dev_set_features(struc + if (features & NETIF_F_GRO_HW) + airoha_dev_lro_enable(dev); + else +- airoha_fe_lro_disable(eth, qdma_id); ++ airoha_fe_lro_disable(dev->eth, qdma_id); + + return 0; + } +@@ -2509,9 +2593,9 @@ static netdev_tx_t airoha_dev_xmit(struc + struct net_device *netdev) + { + struct airoha_gdm_dev *dev = netdev_priv(netdev); +- struct airoha_qdma *qdma = dev->qdma; + u32 nr_frags, tag, msg0, msg1, len; + struct airoha_queue_entry *e; ++ struct airoha_qdma *qdma; + struct netdev_queue *txq; + struct airoha_queue *q; + LIST_HEAD(tx_list); +@@ -2520,6 +2604,8 @@ static netdev_tx_t airoha_dev_xmit(struc + u16 index; + u8 fport; + ++ rcu_read_lock(); ++ qdma = rcu_dereference(dev->qdma); + qid = airoha_qdma_get_txq(qdma, skb_get_queue_mapping(skb)); + tag = airoha_get_dsa_tag(skb, netdev); + +@@ -2566,6 +2652,8 @@ static netdev_tx_t airoha_dev_xmit(struc + netif_tx_stop_queue(txq); + q->txq_stopped = true; + spin_unlock_bh(&q->lock); ++ rcu_read_unlock(); ++ + return NETDEV_TX_BUSY; + } + +@@ -2628,6 +2716,7 @@ static netdev_tx_t airoha_dev_xmit(struc + FIELD_PREP(TX_RING_CPU_IDX_MASK, index)); + + spin_unlock_bh(&q->lock); ++ rcu_read_unlock(); + + return NETDEV_TX_OK; + +@@ -2643,6 +2732,7 @@ error_unmap: + error: + dev_kfree_skb_any(skb); + netdev->stats.tx_dropped++; ++ rcu_read_unlock(); + + return NETDEV_TX_OK; + } +@@ -2740,17 +2830,19 @@ static int airoha_qdma_set_chan_tx_sched + const u16 *weights, u8 n_weights) + { + struct airoha_gdm_dev *dev = netdev_priv(netdev); ++ struct airoha_qdma *qdma; + int i; + ++ qdma = airoha_qdma_deref(dev); + for (i = 0; i < AIROHA_NUM_QOS_QUEUES; i++) +- airoha_qdma_clear(dev->qdma, REG_QUEUE_CLOSE_CFG(channel), ++ airoha_qdma_clear(qdma, REG_QUEUE_CLOSE_CFG(channel), + TXQ_DISABLE_CHAN_QUEUE_MASK(channel, i)); + + for (i = 0; i < n_weights; i++) { + u32 status; + int err; + +- airoha_qdma_wr(dev->qdma, REG_TXWRR_WEIGHT_CFG, ++ airoha_qdma_wr(qdma, REG_TXWRR_WEIGHT_CFG, + TWRR_RW_CMD_MASK | + FIELD_PREP(TWRR_CHAN_IDX_MASK, channel) | + FIELD_PREP(TWRR_QUEUE_IDX_MASK, i) | +@@ -2758,12 +2850,12 @@ static int airoha_qdma_set_chan_tx_sched + err = read_poll_timeout(airoha_qdma_rr, status, + status & TWRR_RW_CMD_DONE, + USEC_PER_MSEC, 10 * USEC_PER_MSEC, +- true, dev->qdma, REG_TXWRR_WEIGHT_CFG); ++ true, qdma, REG_TXWRR_WEIGHT_CFG); + if (err) + return err; + } + +- airoha_qdma_rmw(dev->qdma, REG_CHAN_QOS_MODE(channel >> 3), ++ airoha_qdma_rmw(qdma, REG_CHAN_QOS_MODE(channel >> 3), + CHAN_QOS_MODE_MASK(channel), + __field_prep(CHAN_QOS_MODE_MASK(channel), mode)); + +@@ -2827,13 +2919,15 @@ static int airoha_qdma_get_tx_ets_stats( + struct tc_ets_qopt_offload *opt) + { + struct airoha_gdm_dev *dev = netdev_priv(netdev); +- struct airoha_qdma *qdma = dev->qdma; ++ u64 cpu_tx_packets, fwd_tx_packets, tx_packets; ++ struct airoha_qdma *qdma; + +- u64 cpu_tx_packets = airoha_qdma_rr(qdma, REG_CNTR_VAL(channel << 1)); +- u64 fwd_tx_packets = airoha_qdma_rr(qdma, +- REG_CNTR_VAL((channel << 1) + 1)); +- u64 tx_packets = (cpu_tx_packets - dev->cpu_tx_packets) + +- (fwd_tx_packets - dev->fwd_tx_packets); ++ qdma = airoha_qdma_deref(dev); ++ cpu_tx_packets = airoha_qdma_rr(qdma, REG_CNTR_VAL(channel << 1)); ++ fwd_tx_packets = airoha_qdma_rr(qdma, ++ REG_CNTR_VAL((channel << 1) + 1)); ++ tx_packets = (cpu_tx_packets - dev->cpu_tx_packets) + ++ (fwd_tx_packets - dev->fwd_tx_packets); + + _bstats_update(opt->stats.bstats, 0, tx_packets); + dev->cpu_tx_packets = cpu_tx_packets; +@@ -3093,16 +3187,18 @@ static int airoha_qdma_set_tx_rate_limit + u32 bucket_size) + { + struct airoha_gdm_dev *dev = netdev_priv(netdev); ++ struct airoha_qdma *qdma; + int i, err; + ++ qdma = airoha_qdma_deref(dev); + for (i = 0; i <= TRTCM_PEAK_MODE; i++) { +- err = airoha_qdma_set_trtcm_config(dev->qdma, channel, ++ err = airoha_qdma_set_trtcm_config(qdma, channel, + REG_EGRESS_TRTCM_CFG, i, + !!rate, TRTCM_METER_MODE); + if (err) + return err; + +- err = airoha_qdma_set_trtcm_token_bucket(dev->qdma, channel, ++ err = airoha_qdma_set_trtcm_token_bucket(qdma, channel, + REG_EGRESS_TRTCM_CFG, + i, rate, bucket_size); + if (err) +@@ -3138,11 +3234,12 @@ static int airoha_tc_htb_alloc_leaf_queu + u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; + int err, num_tx_queues = AIROHA_NUM_TX_RING + channel + 1; + struct airoha_gdm_dev *dev = netdev_priv(netdev); +- struct airoha_qdma *qdma = dev->qdma; ++ struct airoha_qdma *qdma; + + /* Here we need to check the requested QDMA channel is not already + * in use by another net_device running on the same QDMA block. + */ ++ qdma = airoha_qdma_deref(dev); + if (test_and_set_bit(channel, qdma->qos_channel_map)) { + NL_SET_ERR_MSG_MOD(opt->extack, + "qdma qos channel already in use"); +@@ -3178,7 +3275,7 @@ static int airoha_qdma_set_rx_meter(stru + u32 rate, u32 bucket_size, + enum trtcm_unit_type unit_type) + { +- struct airoha_qdma *qdma = dev->qdma; ++ struct airoha_qdma *qdma = airoha_qdma_deref(dev); + int i; + + for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { +@@ -3353,10 +3450,11 @@ static void airoha_tc_remove_htb_queue(s + { + struct airoha_gdm_dev *dev = netdev_priv(netdev); + int num_tx_queues = AIROHA_NUM_TX_RING; +- struct airoha_qdma *qdma = dev->qdma; ++ struct airoha_qdma *qdma; + + airoha_qdma_set_tx_rate_limit(netdev, queue, 0, 0); + ++ qdma = airoha_qdma_deref(dev); + clear_bit(queue, qdma->qos_channel_map); + clear_bit(queue, dev->qos_sq_bmap); + +@@ -3382,6 +3480,95 @@ static int airoha_tc_htb_delete_leaf_que + return 0; + } + ++static void airoha_disable_qos_for_gdm34(struct net_device *netdev) ++{ ++ struct airoha_gdm_dev *dev = netdev_priv(netdev); ++ struct airoha_gdm_port *port = dev->port; ++ int err; ++ ++ if (port->id != AIROHA_GDM3_IDX && ++ port->id != AIROHA_GDM4_IDX) ++ return; ++ ++ err = airoha_disable_gdm2_loopback(dev); ++ if (err) ++ netdev_warn(netdev, ++ "failed disabling GDM2 loopback: %d\n", err); ++ ++ dev->flags &= ~AIROHA_PRIV_F_WAN; ++ airoha_dev_set_qdma(dev); ++ ++ airoha_set_macaddr(dev, netdev->dev_addr); ++ if (netif_running(netdev)) ++ airoha_set_gdm_port_fwd_cfg(dev->eth, ++ REG_GDM_FWD_CFG(port->id), ++ FE_PSE_PORT_PPE1); ++} ++ ++static int airoha_enable_qos_for_gdm34(struct net_device *netdev, ++ struct netlink_ext_ack *extack) ++{ ++ struct airoha_gdm_dev *wan_dev, *dev = netdev_priv(netdev); ++ struct airoha_gdm_port *port = dev->port; ++ struct airoha_eth *eth = dev->eth; ++ int err = -EBUSY; ++ ++ if (port->id != AIROHA_GDM3_IDX && ++ port->id != AIROHA_GDM4_IDX) { ++ /* HW QoS is always supported by GDM1 and GDM2 */ ++ return 0; ++ } ++ ++ if (!airoha_is_lan_gdm_dev(dev)) /* Already enabled */ ++ return 0; ++ ++ mutex_lock(&flow_offload_mutex); ++ ++ wan_dev = airoha_get_wan_gdm_dev(eth); ++ if (wan_dev) { ++ if ((wan_dev->flags & AIROHA_PRIV_F_QOS) || ++ wan_dev->port->id == AIROHA_GDM2_IDX) { ++ NL_SET_ERR_MSG_MOD(extack, ++ "QoS configured for WAN device"); ++ goto error_unlock; ++ } ++ airoha_disable_qos_for_gdm34(netdev_from_priv(wan_dev)); ++ } ++ ++ dev->flags |= AIROHA_PRIV_F_WAN; ++ airoha_dev_set_qdma(dev); ++ err = airoha_enable_gdm2_loopback(dev); ++ if (err) ++ goto error_disable_wan; ++ ++ err = airoha_set_macaddr(dev, netdev->dev_addr); ++ if (err) ++ goto error_disable_loopback; ++ ++ if (netif_running(netdev)) { ++ u32 pse_port; ++ ++ pse_port = airoha_ppe_is_enabled(eth, 1) ? FE_PSE_PORT_PPE2 ++ : FE_PSE_PORT_PPE1; ++ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), ++ pse_port); ++ } ++ ++ mutex_unlock(&flow_offload_mutex); ++ ++ return 0; ++ ++error_disable_loopback: ++ airoha_disable_gdm2_loopback(dev); ++error_disable_wan: ++ dev->flags &= ~AIROHA_PRIV_F_WAN; ++ airoha_dev_set_qdma(dev); ++error_unlock: ++ mutex_unlock(&flow_offload_mutex); ++ ++ return err; ++} ++ + static int airoha_tc_htb_destroy(struct net_device *netdev) + { + struct airoha_gdm_dev *dev = netdev_priv(netdev); +@@ -3390,6 +3577,8 @@ static int airoha_tc_htb_destroy(struct + for_each_set_bit(q, dev->qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS) + airoha_tc_remove_htb_queue(netdev, q); + ++ dev->flags &= ~AIROHA_PRIV_F_QOS; ++ + return 0; + } + +@@ -3409,24 +3598,33 @@ static int airoha_tc_get_htb_get_leaf_qu + return 0; + } + +-static int airoha_tc_setup_qdisc_htb(struct net_device *dev, ++static int airoha_tc_setup_qdisc_htb(struct net_device *netdev, + struct tc_htb_qopt_offload *opt) + { + switch (opt->command) { +- case TC_HTB_CREATE: ++ case TC_HTB_CREATE: { ++ struct airoha_gdm_dev *dev = netdev_priv(netdev); ++ int err; ++ ++ err = airoha_enable_qos_for_gdm34(netdev, opt->extack); ++ if (err) ++ return err; ++ ++ dev->flags |= AIROHA_PRIV_F_QOS; + break; ++ } + case TC_HTB_DESTROY: +- return airoha_tc_htb_destroy(dev); ++ return airoha_tc_htb_destroy(netdev); + case TC_HTB_NODE_MODIFY: +- return airoha_tc_htb_modify_queue(dev, opt); ++ return airoha_tc_htb_modify_queue(netdev, opt); + case TC_HTB_LEAF_ALLOC_QUEUE: +- return airoha_tc_htb_alloc_leaf_queue(dev, opt); ++ return airoha_tc_htb_alloc_leaf_queue(netdev, opt); + case TC_HTB_LEAF_DEL: + case TC_HTB_LEAF_DEL_LAST: + case TC_HTB_LEAF_DEL_LAST_FORCE: +- return airoha_tc_htb_delete_leaf_queue(dev, opt); ++ return airoha_tc_htb_delete_leaf_queue(netdev, opt); + case TC_HTB_LEAF_QUERY_QUEUE: +- return airoha_tc_get_htb_get_leaf_queue(dev, opt); ++ return airoha_tc_get_htb_get_leaf_queue(netdev, opt); + default: + return -EOPNOTSUPP; + } +--- a/drivers/net/ethernet/airoha/airoha_regs.h ++++ b/drivers/net/ethernet/airoha/airoha_regs.h +@@ -402,6 +402,7 @@ + + #define REG_SRC_PORT_FC_MAP6 0x2298 + #define FC_ID_OF_SRC_PORT_MASK(_n) GENMASK(4 + ((_n) << 3), ((_n) << 3)) ++#define FC_MAP6_DEF_VALUE 0x1b1a1918 + + #define REG_CDM5_RX_OQ1_DROP_CNT 0x29d4 + +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -550,11 +550,12 @@ struct airoha_qdma { + + enum airoha_priv_flags { + AIROHA_PRIV_F_WAN = BIT(0), ++ AIROHA_PRIV_F_QOS = BIT(1), + }; + + struct airoha_gdm_dev { ++ struct airoha_qdma __rcu *qdma; + struct airoha_gdm_port *port; +- struct airoha_qdma *qdma; + struct airoha_eth *eth; + + DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS); +@@ -704,6 +705,16 @@ int airoha_get_fe_port(struct airoha_gdm + bool airoha_is_valid_gdm_dev(struct airoha_eth *eth, + struct airoha_gdm_dev *dev); + ++extern struct mutex flow_offload_mutex; ++ ++static inline struct airoha_qdma * ++airoha_qdma_deref(struct airoha_gdm_dev *dev) ++{ ++ return rcu_dereference_protected(dev->qdma, ++ lockdep_rtnl_is_held() || ++ lockdep_is_held(&flow_offload_mutex)); ++} ++ + void airoha_ppe_set_cpu_port(struct airoha_gdm_dev *dev, u8 ppe_id, u8 fport); + bool airoha_ppe_is_enabled(struct airoha_eth *eth, int index); + void airoha_ppe_check_skb(struct airoha_ppe_dev *dev, struct sk_buff *skb, +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -16,7 +16,10 @@ + #include "airoha_regs.h" + #include "airoha_eth.h" + +-static DEFINE_MUTEX(flow_offload_mutex); ++/* Serialize airoha_gdm_dev flags, QDMA pointer and PPE CPU port ++ * configuration. ++ */ ++DEFINE_MUTEX(flow_offload_mutex); + static DEFINE_SPINLOCK(ppe_lock); + + static const struct rhashtable_params airoha_flow_table_params = { +@@ -87,8 +90,8 @@ static u32 airoha_ppe_get_timestamp(stru + + void airoha_ppe_set_cpu_port(struct airoha_gdm_dev *dev, u8 ppe_id, u8 fport) + { +- struct airoha_qdma *qdma = dev->qdma; +- struct airoha_eth *eth = qdma->eth; ++ struct airoha_qdma *qdma = airoha_qdma_deref(dev); ++ struct airoha_eth *eth = dev->eth; + u8 qdma_id = qdma - ð->qdma[0]; + u32 fe_cpu_port; + diff --git a/target/linux/airoha/patches-6.18/920-13-net-airoha-Rework-MTU-configuration.patch b/target/linux/airoha/patches-6.18/920-13-net-airoha-Rework-MTU-configuration.patch index 072b50fe35..1769b58372 100644 --- a/target/linux/airoha/patches-6.18/920-13-net-airoha-Rework-MTU-configuration.patch +++ b/target/linux/airoha/patches-6.18/920-13-net-airoha-Rework-MTU-configuration.patch @@ -16,7 +16,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -185,10 +185,15 @@ static void airoha_fe_maccr_init(struct +@@ -181,10 +181,15 @@ static void airoha_fe_maccr_init(struct { int p; @@ -33,8 +33,8 @@ Signed-off-by: Lorenzo Bianconi airoha_fe_rmw(eth, REG_CDM_VLAN_CTRL(1), CDM_VLAN_MASK, FIELD_PREP(CDM_VLAN_MASK, 0x8100)); -@@ -1908,13 +1913,24 @@ static void airoha_update_hw_stats(struc - spin_unlock(&port->stats.lock); +@@ -2102,15 +2107,25 @@ static void airoha_qdma_stop(struct airo + } } +static void airoha_dev_set_mtu(struct net_device *netdev) @@ -54,17 +54,19 @@ Signed-off-by: Lorenzo Bianconi struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; - u32 cur_len, pse_port = FE_PSE_PORT_PPE1; - struct airoha_qdma *qdma = dev->qdma; + struct airoha_eth *eth = dev->eth; + struct airoha_qdma *qdma; +- int qdma_id; + u32 pse_port = FE_PSE_PORT_PPE1; -+ int err; ++ int err, qdma_id; - if (port->id == AIROHA_GDM2_IDX && airoha_is_lan_gdm_dev(dev)) { - /* GDM2 can be used just as wan */ -@@ -1947,19 +1963,7 @@ static int airoha_dev_open(struct net_de - airoha_fe_clear(qdma->eth, REG_GDM_INGRESS_CFG(port->id), + /* HW LRO is configured on the QDMA and it is shared between + * all the devices using it. Refuse to open a second device on +@@ -2146,19 +2161,7 @@ static int airoha_dev_open(struct net_de + airoha_fe_clear(eth, REG_GDM_INGRESS_CFG(port->id), GDM_STAG_EN_MASK); -- cur_len = airoha_fe_get(qdma->eth, REG_GDM_LEN_CFG(port->id), +- cur_len = airoha_fe_get(eth, REG_GDM_LEN_CFG(port->id), - GDM_LONG_LEN_MASK); - if (!port->users || len > cur_len) { - /* Opening a sibling net_device with a larger MTU updates the @@ -72,7 +74,7 @@ Signed-off-by: Lorenzo Bianconi - * multiple net_devices with different MTUs to share the same - * GDM port. - */ -- airoha_fe_rmw(qdma->eth, REG_GDM_LEN_CFG(port->id), +- airoha_fe_rmw(eth, REG_GDM_LEN_CFG(port->id), - GDM_SHORT_LEN_MASK | GDM_LONG_LEN_MASK, - FIELD_PREP(GDM_SHORT_LEN_MASK, 60) | - FIELD_PREP(GDM_LONG_LEN_MASK, len)); @@ -80,8 +82,8 @@ Signed-off-by: Lorenzo Bianconi + airoha_dev_set_mtu(netdev); port->users++; - airoha_qdma_set(qdma, REG_QDMA_GLOBAL_CFG, -@@ -1976,30 +1980,6 @@ static int airoha_dev_open(struct net_de + airoha_qdma_start(qdma); +@@ -2177,30 +2180,6 @@ static int airoha_dev_open(struct net_de return 0; } @@ -98,7 +100,7 @@ Signed-off-by: Lorenzo Bianconi - if (!dev) - continue; - -- netdev = dev->dev; +- netdev = netdev_from_priv(dev); - if (netif_running(netdev)) - len = max_t(u32, len, netdev->mtu); - } @@ -112,16 +114,16 @@ Signed-off-by: Lorenzo Bianconi static int airoha_dev_stop(struct net_device *netdev) { struct airoha_gdm_dev *dev = netdev_priv(netdev); -@@ -2013,7 +1993,7 @@ static int airoha_dev_stop(struct net_de - netdev_tx_reset_subqueue(netdev, i); +@@ -2215,7 +2194,7 @@ static int airoha_dev_stop(struct net_de + qdma = airoha_qdma_deref(dev); if (--port->users) - airoha_set_port_mtu(dev->eth, port); + airoha_ppe_set_mtu(dev); else airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id), -@@ -2083,10 +2063,6 @@ static int airoha_enable_gdm2_loopback(s +@@ -2274,10 +2253,6 @@ static int airoha_enable_gdm2_loopback(s FIELD_PREP(LPBK_CHAN_MASK, chan) | LBK_GAP_MODE_MASK | LBK_LEN_MODE_MASK | LBK_CHAN_MODE_MASK | LPBK_EN_MASK); @@ -132,7 +134,7 @@ Signed-off-by: Lorenzo Bianconi /* Forward the traffic to the proper GDM port */ pse_port = port->id == AIROHA_GDM3_IDX ? FE_PSE_PORT_GDM3 : FE_PSE_PORT_GDM4; -@@ -2270,7 +2246,7 @@ static int airoha_dev_change_mtu(struct +@@ -2472,7 +2447,7 @@ static int airoha_dev_change_mtu(struct WRITE_ONCE(netdev->mtu, mtu); if (port->users) @@ -141,14 +143,22 @@ Signed-off-by: Lorenzo Bianconi return 0; } -@@ -2613,6 +2589,7 @@ static int airoha_dev_set_wan_flag(struc - default: - return -EOPNOTSUPP; - } -+ airoha_dev_set_mtu(netdev); - } else { - switch (port->id) { - case AIROHA_GDM3_IDX: +@@ -3497,6 +3472,7 @@ static void airoha_disable_qos_for_gdm34 + + dev->flags &= ~AIROHA_PRIV_F_WAN; + airoha_dev_set_qdma(dev); ++ airoha_dev_set_mtu(netdev); + + airoha_set_macaddr(dev, netdev->dev_addr); + if (netif_running(netdev)) +@@ -3545,6 +3521,7 @@ static int airoha_enable_qos_for_gdm34(s + if (err) + goto error_disable_loopback; + ++ airoha_dev_set_mtu(netdev); + if (netif_running(netdev)) { + u32 pse_port; + --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h @@ -23,6 +23,7 @@ @@ -159,9 +169,9 @@ Signed-off-by: Lorenzo Bianconi #define AIROHA_MAX_PACKET_SIZE 2048 #define AIROHA_NUM_QOS_CHANNELS 4 #define AIROHA_NUM_QOS_QUEUES 8 -@@ -706,6 +707,7 @@ int airoha_get_fe_port(struct airoha_gdm - bool airoha_is_valid_gdm_dev(struct airoha_eth *eth, - struct airoha_gdm_dev *dev); +@@ -715,6 +716,7 @@ airoha_qdma_deref(struct airoha_gdm_dev + lockdep_is_held(&flow_offload_mutex)); + } +void airoha_ppe_set_mtu(struct airoha_gdm_dev *dev); void airoha_ppe_set_cpu_port(struct airoha_gdm_dev *dev, u8 ppe_id, u8 fport); @@ -169,7 +179,7 @@ Signed-off-by: Lorenzo Bianconi void airoha_ppe_check_skb(struct airoha_ppe_dev *dev, struct sk_buff *skb, --- a/drivers/net/ethernet/airoha/airoha_ppe.c +++ b/drivers/net/ethernet/airoha/airoha_ppe.c -@@ -98,6 +98,35 @@ void airoha_ppe_set_cpu_port(struct airo +@@ -101,6 +101,39 @@ void airoha_ppe_set_cpu_port(struct airo __field_prep(DFT_CPORT_MASK(fport), fe_cpu_port)); } @@ -177,20 +187,24 @@ Signed-off-by: Lorenzo Bianconi +{ + struct airoha_gdm_port *port = dev->port; + struct airoha_eth *eth = dev->eth; ++ struct airoha_qdma *qdma; + int i, ppe_id, index; + u32 mtu = 0; + ++ qdma = airoha_qdma_deref(dev); + for (i = 0; i < ARRAY_SIZE(port->devs); i++) { + struct airoha_gdm_dev *d = port->devs[i]; + struct net_device *netdev; ++ struct airoha_qdma *q; + + if (!d) + continue; + -+ if (d->qdma != dev->qdma) ++ q = airoha_qdma_deref(d); ++ if (q != qdma) + continue; + -+ netdev = d->dev; ++ netdev = netdev_from_priv(d); + if (netif_running(netdev)) + mtu = max_t(u32, mtu, netdev->mtu); + } @@ -205,7 +219,7 @@ Signed-off-by: Lorenzo Bianconi static void airoha_ppe_hw_init(struct airoha_ppe *ppe) { u32 sram_ppe_num_data_entries = PPE_SRAM_NUM_ENTRIES, sram_num_entries; -@@ -116,8 +145,6 @@ static void airoha_ppe_hw_init(struct ai +@@ -119,8 +152,6 @@ static void airoha_ppe_hw_init(struct ai PPE_RAM_NUM_ENTRIES_SHIFT(sram_ppe_num_data_entries); for (i = 0; i < eth->soc->num_ppe; i++) { @@ -214,7 +228,7 @@ Signed-off-by: Lorenzo Bianconi airoha_fe_wr(eth, REG_PPE_TB_BASE(i), ppe->foe_dma + sram_tb_size); -@@ -167,15 +194,6 @@ static void airoha_ppe_hw_init(struct ai +@@ -170,15 +201,6 @@ static void airoha_ppe_hw_init(struct ai airoha_fe_wr(eth, REG_PPE_HASH_SEED(i), PPE_HASH_SEED); airoha_fe_clear(eth, REG_PPE_PPE_FLOW_CFG(i), PPE_FLOW_CFG_IP6_6RD_MASK); @@ -230,7 +244,7 @@ Signed-off-by: Lorenzo Bianconi } for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { -@@ -197,6 +215,7 @@ static void airoha_ppe_hw_init(struct ai +@@ -200,6 +222,7 @@ static void airoha_ppe_hw_init(struct ai airoha_ppe_is_enabled(eth, 1); fport = airoha_get_fe_port(dev); airoha_ppe_set_cpu_port(dev, ppe_id, fport); diff --git a/target/linux/airoha/patches-6.18/920-15-net-airoha-fix-wrong-airoha_get_fe_port.patch b/target/linux/airoha/patches-6.18/920-15-net-airoha-fix-wrong-airoha_get_fe_port.patch index 75a49306c2..a0a1ed0135 100644 --- a/target/linux/airoha/patches-6.18/920-15-net-airoha-fix-wrong-airoha_get_fe_port.patch +++ b/target/linux/airoha/patches-6.18/920-15-net-airoha-fix-wrong-airoha_get_fe_port.patch @@ -18,7 +18,7 @@ Signed-off-by: Christian Marangi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2345,17 +2345,9 @@ static u32 airoha_get_dsa_tag(struct sk_ +@@ -2519,17 +2519,9 @@ static u32 airoha_get_dsa_tag(struct sk_ int airoha_get_fe_port(struct airoha_gdm_dev *dev) { struct airoha_gdm_port *port = dev->port; @@ -37,4 +37,4 @@ Signed-off-by: Christian Marangi + : port->id; } - static int airoha_dev_set_features(struct net_device *netdev, + static netdev_features_t airoha_dev_fix_features(struct net_device *netdev, diff --git a/target/linux/airoha/patches-6.18/920-16-net-airoha-Account-for-L2-overhead-in-PPE-MTU-configuration.patch b/target/linux/airoha/patches-6.18/920-16-net-airoha-Account-for-L2-overhead-in-PPE-MTU-configuration.patch new file mode 100644 index 0000000000..5aac6bd031 --- /dev/null +++ b/target/linux/airoha/patches-6.18/920-16-net-airoha-Account-for-L2-overhead-in-PPE-MTU-configuration.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sayantan Nandy +Date: Thu, 19 Jun 2026 12:00:00 +0530 +Subject: [PATCH] net: airoha: Account for L2 overhead in PPE MTU configuration + +The PPE egress MTU register and WAN MTU register compare against L2 +frame length without FCS, as confirmed by the hardware reset value of +0x05EA (1514 = ETH_HLEN + 1500). + +Account for VLAN_ETH_HLEN when programming these registers to prevent +valid VLAN-tagged frames from being incorrectly dropped by hardware. + +Rename the local variable from 'mtu' to 'len' in airoha_ppe_set_mtu() +since it now represents a frame length rather than an L3 MTU value. + +Fixes: 99e204d255c9 ("net: airoha: Rework MTU configuration") + +Signed-off-by: Sayantan Nandy +--- + drivers/net/ethernet/airoha/airoha_eth.c | 2 +- + drivers/net/ethernet/airoha/airoha_ppe.c | 7 ++++--- + 2 files changed, 5 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -2115,7 +2116,7 @@ static void airoha_dev_set_mtu(struct ne + if (!airoha_is_lan_gdm_dev(dev)) + airoha_fe_rmw(dev->eth, REG_WAN_MTU0, + WAN_MTU0_MASK, +- FIELD_PREP(WAN_MTU0_MASK, netdev->mtu)); ++ FIELD_PREP(WAN_MTU0_MASK, netdev->mtu + VLAN_ETH_HLEN)); + } + + static int airoha_dev_open(struct net_device *netdev) +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -107,7 +108,7 @@ void airoha_ppe_set_mtu(struct airoha_gd + struct airoha_eth *eth = dev->eth; + struct airoha_qdma *qdma; + int i, ppe_id, index; +- u32 mtu = 0; ++ u32 len = 0; + + qdma = airoha_qdma_deref(dev); + for (i = 0; i < ARRAY_SIZE(port->devs); i++) { +@@ -124,14 +125,15 @@ void airoha_ppe_set_mtu(struct airoha_gd + + netdev = netdev_from_priv(d); + if (netif_running(netdev)) +- mtu = max_t(u32, mtu, netdev->mtu); ++ len = max_t(u32, len, netdev->mtu); + } + ++ len += VLAN_ETH_HLEN; + ppe_id = !airoha_is_lan_gdm_dev(dev) && airoha_ppe_is_enabled(eth, 1); + index = port->id == AIROHA_GDM4_IDX ? 7 : port->id; + airoha_fe_rmw(eth, REG_PPE_MTU(ppe_id, index), + FP_EGRESS_MTU_MASK(index), +- __field_prep(FP_EGRESS_MTU_MASK(index), mtu)); ++ __field_prep(FP_EGRESS_MTU_MASK(index), len)); + } + + static void airoha_ppe_hw_init(struct airoha_ppe *ppe) diff --git a/target/linux/armsr/armv8/config-6.12 b/target/linux/armsr/armv8/config-6.12 index 6463660b5a..a1176c0585 100644 --- a/target/linux/armsr/armv8/config-6.12 +++ b/target/linux/armsr/armv8/config-6.12 @@ -83,6 +83,8 @@ CONFIG_ARM64_ERRATUM_2441007=y CONFIG_ARM64_ERRATUM_2441009=y CONFIG_ARM64_ERRATUM_2457168=y CONFIG_ARM64_ERRATUM_2658417=y +CONFIG_ARM64_ERRATUM_4118414=y +CONFIG_ARM64_ERRATUM_4193714=y CONFIG_ARM64_ERRATUM_819472=y CONFIG_ARM64_ERRATUM_824069=y CONFIG_ARM64_ERRATUM_826319=y diff --git a/target/linux/armsr/armv8/config-6.18 b/target/linux/armsr/armv8/config-6.18 index 80d325e44e..0e132297fb 100644 --- a/target/linux/armsr/armv8/config-6.18 +++ b/target/linux/armsr/armv8/config-6.18 @@ -91,6 +91,7 @@ CONFIG_ARM64_ERRATUM_2441007=y CONFIG_ARM64_ERRATUM_2441009=y CONFIG_ARM64_ERRATUM_2457168=y CONFIG_ARM64_ERRATUM_2658417=y +CONFIG_ARM64_ERRATUM_4118414=y CONFIG_ARM64_ERRATUM_4193714=y CONFIG_ARM64_ERRATUM_819472=y CONFIG_ARM64_ERRATUM_824069=y diff --git a/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c new file mode 100644 index 0000000000..d517980b37 --- /dev/null +++ b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c @@ -0,0 +1,172 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Atheros AR71xx/AR724x/AR913x specific interrupt handling + * + * Copyright (C) 2018 John Crispin + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define ATH79_MAX_INTC_CASCADE 3 + +struct ath79_intc { + int irq; + u32 num_irqs; + u32 enable_mask; + u32 int_status; + u32 irq_mask[ATH79_MAX_INTC_CASCADE]; + u32 irq_wb_chan[ATH79_MAX_INTC_CASCADE]; + struct irq_chip chip; +}; + +static void ath79_intc_irq_handler(struct irq_desc *desc) +{ + struct irq_domain *domain = irq_desc_get_handler_data(desc); + struct irq_chip *chip = irq_desc_get_chip(desc); + struct ath79_intc *intc = domain->host_data; + u32 pending; + int i; + + chained_irq_enter(chip, desc); + + pending = ath79_reset_rr(intc->int_status); + pending &= intc->enable_mask; + + if (!pending) { + spurious_interrupt(); + chained_irq_exit(chip, desc); + return; + } + + for (i = 0; i < intc->num_irqs; i++) + if (pending & intc->irq_mask[i]) { + if (intc->irq_wb_chan[i] != 0xffffffff) + ath79_ddr_wb_flush(intc->irq_wb_chan[i]); + generic_handle_domain_irq(domain, i); + } + + chained_irq_exit(chip, desc); +} + +static void ath79_intc_irq_enable(struct irq_data *d) +{ + struct ath79_intc *intc = d->domain->host_data; + enable_irq(intc->irq); +} + +static void ath79_intc_irq_disable(struct irq_data *d) +{ + struct ath79_intc *intc = d->domain->host_data; + disable_irq(intc->irq); +} + +static int ath79_intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) +{ + struct ath79_intc *intc = d->host_data; + + irq_set_chip_and_handler(irq, &intc->chip, handle_level_irq); + + return 0; +} + +static const struct irq_domain_ops ath79_irq_domain_ops = { + .xlate = irq_domain_xlate_onecell, + .map = ath79_intc_map, +}; + +static int __init ath79_intc_of_init( + struct device_node *node, struct device_node *parent) +{ + struct irq_domain *domain; + struct ath79_intc *intc; + int cnt, cntwb, i, err; + + cnt = of_property_count_u32_elems(node, "qca,pending-bits"); + if (cnt < 0 || cnt > ATH79_MAX_INTC_CASCADE) { + pr_err("Invalid number of INTC pending bits (%d)\n", cnt); + return -EINVAL; + } + + intc = kzalloc(sizeof(*intc), GFP_KERNEL); + if (!intc) + return -ENOMEM; + + intc->chip = dummy_irq_chip; + intc->chip.name = "INTC"; + intc->chip.irq_disable = ath79_intc_irq_disable; + intc->chip.irq_enable = ath79_intc_irq_enable; + intc->num_irqs = cnt; + + if (of_property_read_u32(node, "qca,int-status-addr", &intc->int_status) < 0) { + pr_err("Missing address of interrupt status register\n"); + err = -EINVAL; + goto err; + } + + of_property_read_u32_array(node, "qca,pending-bits", intc->irq_mask, cnt); + for (i = 0; i < cnt; i++) { + intc->enable_mask |= intc->irq_mask[i]; + intc->irq_wb_chan[i] = 0xffffffff; + } + + cntwb = of_count_phandle_with_args( + node, "qca,ddr-wb-channels", "#qca,ddr-wb-channel-cells"); + cntwb = max(0, cntwb); + + for (i = 0; i < cntwb; i++) { + struct of_phandle_args args; + u32 irq = i; + + of_property_read_u32_index( + node, "qca,ddr-wb-channel-interrupts", i, &irq); + if (irq >= intc->num_irqs) + continue; + + err = of_parse_phandle_with_args( + node, "qca,ddr-wb-channels", + "#qca,ddr-wb-channel-cells", + i, &args); + if (err) + goto err; + + intc->irq_wb_chan[irq] = args.args[0]; + } + + intc->irq = of_irq_get(node, 0); + if (intc->irq < 0) { + pr_err("Failed to get INTC IRQ\n"); + err = intc->irq; + goto err; + } + + if (!intc->irq) { + pr_err("Failed to get INTC IRQ\n"); + err = -ENODEV; + goto err; + } + + domain = irq_domain_create_linear(of_fwnode_handle(node), cnt, &ath79_irq_domain_ops, intc); + if (!domain) { + err = -EINVAL; + goto err; + } + + irq_set_chained_handler_and_data(intc->irq, ath79_intc_irq_handler, domain); + + return 0; + +err: + kfree(intc); + return err; +} +IRQCHIP_DECLARE(ath79_intc, "qca,ar9340-intc", + ath79_intc_of_init); diff --git a/target/linux/ath79/files/drivers/leds/leds-reset.c b/target/linux/ath79/files/drivers/leds/leds-reset.c new file mode 100644 index 0000000000..ead9d18a82 --- /dev/null +++ b/target/linux/ath79/files/drivers/leds/leds-reset.c @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2018 John Crispin + * + * 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. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +struct reset_led_data { + struct reset_control *rst; + struct led_classdev cdev; +}; + +static inline struct reset_led_data * + cdev_to_reset_led_data(struct led_classdev *led_cdev) +{ + return container_of(led_cdev, struct reset_led_data, cdev); +} + +static void reset_led_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + struct reset_led_data *led_dat = cdev_to_reset_led_data(led_cdev); + + if (value == LED_OFF) + reset_control_assert(led_dat->rst); + else + reset_control_deassert(led_dat->rst); +} + +struct reset_leds_priv { + int num_leds; + struct reset_led_data leds[]; +}; + +static int reset_led_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct reset_leds_priv *priv; + int count; + + count = device_get_child_node_count(dev); + if (!count) + return -ENODEV; + + priv = devm_kzalloc(dev, struct_size(priv, leds, count), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + device_for_each_child_node_scoped(dev, child) { + struct reset_led_data *led = &priv->leds[priv->num_leds]; + struct led_init_data init_data = { + .fwnode = child, + }; + int ret; + + ret = fwnode_property_read_string(child, "label", &led->cdev.name); + if (ret) + return ret; + + led->rst = of_reset_control_get_exclusive(to_of_node(child), NULL); + if (IS_ERR(led->rst)) + return PTR_ERR(led->rst); + + fwnode_property_read_string(child, "linux,default-trigger", + &led->cdev.default_trigger); + + led->cdev.brightness_set = reset_led_set; + ret = devm_led_classdev_register_ext(dev, &led->cdev, &init_data); + if (ret < 0) + return ret; + + priv->num_leds++; + } + + platform_set_drvdata(pdev, priv); + + return 0; +} + +static void reset_led_shutdown(struct platform_device *pdev) +{ + struct reset_leds_priv *priv = platform_get_drvdata(pdev); + int i; + + for (i = 0; i < priv->num_leds; i++) { + struct reset_led_data *led = &priv->leds[i]; + + if (!(led->cdev.flags & LED_RETAIN_AT_SHUTDOWN)) + reset_led_set(&led->cdev, LED_OFF); + } +} + +static const struct of_device_id of_reset_leds_match[] = { + { .compatible = "reset-leds", }, + {}, +}; + +MODULE_DEVICE_TABLE(of, of_reset_leds_match); + +static struct platform_driver reset_led_driver = { + .probe = reset_led_probe, + .shutdown = reset_led_shutdown, + .driver = { + .name = "leds-reset", + .of_match_table = of_reset_leds_match, + }, +}; + +module_platform_driver(reset_led_driver); + +MODULE_AUTHOR("John Crispin "); +MODULE_DESCRIPTION("reset controller LED driver"); +MODULE_LICENSE("GPL"); diff --git a/target/linux/ath79/patches-6.12/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch b/target/linux/ath79/patches-6.12/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch index ceda511c21..4d0cadc7e6 100644 --- a/target/linux/ath79/patches-6.12/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch +++ b/target/linux/ath79/patches-6.12/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch @@ -21,148 +21,3 @@ Signed-off-by: John Crispin obj-$(CONFIG_ATH79) += irq-ath79-misc.o obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2836.o ---- /dev/null -+++ b/drivers/irqchip/irq-ath79-intc.c -@@ -0,0 +1,142 @@ -+/* -+ * Atheros AR71xx/AR724x/AR913x specific interrupt handling -+ * -+ * Copyright (C) 2018 John Crispin -+ * -+ * 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. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#define ATH79_MAX_INTC_CASCADE 3 -+ -+struct ath79_intc { -+ struct irq_chip chip; -+ u32 irq; -+ u32 pending_mask; -+ u32 int_status; -+ u32 irq_mask[ATH79_MAX_INTC_CASCADE]; -+ u32 irq_wb_chan[ATH79_MAX_INTC_CASCADE]; -+}; -+ -+static void ath79_intc_irq_handler(struct irq_desc *desc) -+{ -+ struct irq_domain *domain = irq_desc_get_handler_data(desc); -+ struct ath79_intc *intc = domain->host_data; -+ u32 pending; -+ -+ pending = ath79_reset_rr(intc->int_status); -+ pending &= intc->pending_mask; -+ -+ if (pending) { -+ int i; -+ -+ for (i = 0; i < domain->hwirq_max; i++) -+ if (pending & intc->irq_mask[i]) { -+ if (intc->irq_wb_chan[i] != 0xffffffff) -+ ath79_ddr_wb_flush(intc->irq_wb_chan[i]); -+ generic_handle_irq(irq_find_mapping(domain, i)); -+ } -+ } else { -+ spurious_interrupt(); -+ } -+} -+ -+static void ath79_intc_irq_enable(struct irq_data *d) -+{ -+ struct ath79_intc *intc = d->domain->host_data; -+ enable_irq(intc->irq); -+} -+ -+static void ath79_intc_irq_disable(struct irq_data *d) -+{ -+ struct ath79_intc *intc = d->domain->host_data; -+ disable_irq(intc->irq); -+} -+ -+static int ath79_intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) -+{ -+ struct ath79_intc *intc = d->host_data; -+ -+ irq_set_chip_and_handler(irq, &intc->chip, handle_level_irq); -+ -+ return 0; -+} -+ -+static const struct irq_domain_ops ath79_irq_domain_ops = { -+ .xlate = irq_domain_xlate_onecell, -+ .map = ath79_intc_map, -+}; -+ -+static int __init ath79_intc_of_init( -+ struct device_node *node, struct device_node *parent) -+{ -+ struct irq_domain *domain; -+ struct ath79_intc *intc; -+ int cnt, cntwb, i, err; -+ -+ cnt = of_property_count_u32_elems(node, "qca,pending-bits"); -+ if (cnt > ATH79_MAX_INTC_CASCADE) -+ panic("Too many INTC pending bits\n"); -+ -+ intc = kzalloc(sizeof(*intc), GFP_KERNEL); -+ if (!intc) -+ panic("Failed to allocate INTC memory\n"); -+ intc->chip = dummy_irq_chip; -+ intc->chip.name = "INTC"; -+ intc->chip.irq_disable = ath79_intc_irq_disable; -+ intc->chip.irq_enable = ath79_intc_irq_enable; -+ -+ if (of_property_read_u32(node, "qca,int-status-addr", &intc->int_status) < 0) { -+ panic("Missing address of interrupt status register\n"); -+ } -+ -+ of_property_read_u32_array(node, "qca,pending-bits", intc->irq_mask, cnt); -+ for (i = 0; i < cnt; i++) { -+ intc->pending_mask |= intc->irq_mask[i]; -+ intc->irq_wb_chan[i] = 0xffffffff; -+ } -+ -+ cntwb = of_count_phandle_with_args( -+ node, "qca,ddr-wb-channels", "#qca,ddr-wb-channel-cells"); -+ -+ for (i = 0; i < cntwb; i++) { -+ struct of_phandle_args args; -+ u32 irq = i; -+ -+ of_property_read_u32_index( -+ node, "qca,ddr-wb-channel-interrupts", i, &irq); -+ if (irq >= ATH79_MAX_INTC_CASCADE) -+ continue; -+ -+ err = of_parse_phandle_with_args( -+ node, "qca,ddr-wb-channels", -+ "#qca,ddr-wb-channel-cells", -+ i, &args); -+ if (err) -+ return err; -+ -+ intc->irq_wb_chan[irq] = args.args[0]; -+ } -+ -+ intc->irq = irq_of_parse_and_map(node, 0); -+ if (!intc->irq) -+ panic("Failed to get INTC IRQ"); -+ -+ domain = irq_domain_add_linear(node, cnt, &ath79_irq_domain_ops, intc); -+ irq_set_chained_handler_and_data(intc->irq, ath79_intc_irq_handler, domain); -+ -+ return 0; -+} -+IRQCHIP_DECLARE(ath79_intc, "qca,ar9340-intc", -+ ath79_intc_of_init); diff --git a/target/linux/ath79/patches-6.12/800-leds-add-reset-controller-based-driver.patch b/target/linux/ath79/patches-6.12/800-leds-add-reset-controller-based-driver.patch index 883d4910fc..d68566f03a 100644 --- a/target/linux/ath79/patches-6.12/800-leds-add-reset-controller-based-driver.patch +++ b/target/linux/ath79/patches-6.12/800-leds-add-reset-controller-based-driver.patch @@ -31,149 +31,6 @@ Signed-off-by: John Crispin comment "LED Triggers" source "drivers/leds/trigger/Kconfig" ---- /dev/null -+++ b/drivers/leds/leds-reset.c -@@ -0,0 +1,140 @@ -+/* -+ * Copyright (C) 2018 John Crispin -+ * -+ * 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. -+ * -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct reset_led_data { -+ struct led_classdev cdev; -+ struct reset_control *rst; -+}; -+ -+static inline struct reset_led_data * -+ cdev_to_reset_led_data(struct led_classdev *led_cdev) -+{ -+ return container_of(led_cdev, struct reset_led_data, cdev); -+} -+ -+static void reset_led_set(struct led_classdev *led_cdev, -+ enum led_brightness value) -+{ -+ struct reset_led_data *led_dat = cdev_to_reset_led_data(led_cdev); -+ -+ if (value == LED_OFF) -+ reset_control_assert(led_dat->rst); -+ else -+ reset_control_deassert(led_dat->rst); -+} -+ -+struct reset_leds_priv { -+ int num_leds; -+ struct reset_led_data leds[]; -+}; -+ -+static inline int sizeof_reset_leds_priv(int num_leds) -+{ -+ return sizeof(struct reset_leds_priv) + -+ (sizeof(struct reset_led_data) * num_leds); -+} -+ -+static struct reset_leds_priv *reset_leds_create(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct fwnode_handle *child; -+ struct reset_leds_priv *priv; -+ int count, ret; -+ -+ count = device_get_child_node_count(dev); -+ if (!count) -+ return ERR_PTR(-ENODEV); -+ -+ priv = devm_kzalloc(dev, sizeof_reset_leds_priv(count), GFP_KERNEL); -+ if (!priv) -+ return ERR_PTR(-ENOMEM); -+ -+ device_for_each_child_node(dev, child) { -+ struct reset_led_data *led = &priv->leds[priv->num_leds]; -+ struct device_node *np = to_of_node(child); -+ -+ ret = fwnode_property_read_string(child, "label", &led->cdev.name); -+ if (!led->cdev.name) { -+ fwnode_handle_put(child); -+ return ERR_PTR(-EINVAL); -+ } -+ led->rst = __of_reset_control_get(np, NULL, 0, RESET_CONTROL_EXCLUSIVE); -+ if (IS_ERR(led->rst)) -+ return ERR_PTR(-EINVAL); -+ -+ fwnode_property_read_string(child, "linux,default-trigger", -+ &led->cdev.default_trigger); -+ -+ led->cdev.brightness_set = reset_led_set; -+ ret = devm_led_classdev_register(&pdev->dev, &led->cdev); -+ if (ret < 0) -+ return ERR_PTR(ret); -+ led->cdev.dev->of_node = np; -+ priv->num_leds++; -+ } -+ -+ return priv; -+} -+ -+static const struct of_device_id of_reset_leds_match[] = { -+ { .compatible = "reset-leds", }, -+ {}, -+}; -+ -+MODULE_DEVICE_TABLE(of, of_reset_leds_match); -+ -+static int reset_led_probe(struct platform_device *pdev) -+{ -+ struct reset_leds_priv *priv; -+ -+ priv = reset_leds_create(pdev); -+ if (IS_ERR(priv)) -+ return PTR_ERR(priv); -+ -+ platform_set_drvdata(pdev, priv); -+ -+ return 0; -+} -+ -+static void reset_led_shutdown(struct platform_device *pdev) -+{ -+ struct reset_leds_priv *priv = platform_get_drvdata(pdev); -+ int i; -+ -+ for (i = 0; i < priv->num_leds; i++) { -+ struct reset_led_data *led = &priv->leds[i]; -+ -+ if (!(led->cdev.flags & LED_RETAIN_AT_SHUTDOWN)) -+ reset_led_set(&led->cdev, LED_OFF); -+ } -+} -+ -+static struct platform_driver reset_led_driver = { -+ .probe = reset_led_probe, -+ .shutdown = reset_led_shutdown, -+ .driver = { -+ .name = "leds-reset", -+ .of_match_table = of_reset_leds_match, -+ }, -+}; -+ -+module_platform_driver(reset_led_driver); -+ -+MODULE_AUTHOR("John Crispin "); -+MODULE_DESCRIPTION("reset controller LED driver"); -+MODULE_LICENSE("GPL"); -+MODULE_ALIAS("platform:leds-reset"); --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -93,6 +93,7 @@ obj-$(CONFIG_LEDS_TURRIS_OMNIA) += leds diff --git a/target/linux/ath79/patches-6.12/900-unaligned_access_hacks.patch b/target/linux/ath79/patches-6.12/900-unaligned_access_hacks.patch index e26aaebab3..71ecaa9ce1 100644 --- a/target/linux/ath79/patches-6.12/900-unaligned_access_hacks.patch +++ b/target/linux/ath79/patches-6.12/900-unaligned_access_hacks.patch @@ -259,7 +259,7 @@ SVN-Revision: 35130 #include #include #include -@@ -915,10 +916,10 @@ static void tcp_v6_send_response(const s +@@ -912,10 +913,10 @@ static void tcp_v6_send_response(const s topt = (__be32 *)(t1 + 1); if (tsecr) { @@ -701,7 +701,7 @@ SVN-Revision: 35130 +#include struct net; - + extern struct net init_net; --- a/include/uapi/linux/in.h +++ b/include/uapi/linux/in.h @@ -93,7 +93,7 @@ enum { diff --git a/target/linux/ath79/patches-6.18/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch b/target/linux/ath79/patches-6.18/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch index ceda511c21..4d0cadc7e6 100644 --- a/target/linux/ath79/patches-6.18/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch +++ b/target/linux/ath79/patches-6.18/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch @@ -21,148 +21,3 @@ Signed-off-by: John Crispin obj-$(CONFIG_ATH79) += irq-ath79-misc.o obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2836.o ---- /dev/null -+++ b/drivers/irqchip/irq-ath79-intc.c -@@ -0,0 +1,142 @@ -+/* -+ * Atheros AR71xx/AR724x/AR913x specific interrupt handling -+ * -+ * Copyright (C) 2018 John Crispin -+ * -+ * 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. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#define ATH79_MAX_INTC_CASCADE 3 -+ -+struct ath79_intc { -+ struct irq_chip chip; -+ u32 irq; -+ u32 pending_mask; -+ u32 int_status; -+ u32 irq_mask[ATH79_MAX_INTC_CASCADE]; -+ u32 irq_wb_chan[ATH79_MAX_INTC_CASCADE]; -+}; -+ -+static void ath79_intc_irq_handler(struct irq_desc *desc) -+{ -+ struct irq_domain *domain = irq_desc_get_handler_data(desc); -+ struct ath79_intc *intc = domain->host_data; -+ u32 pending; -+ -+ pending = ath79_reset_rr(intc->int_status); -+ pending &= intc->pending_mask; -+ -+ if (pending) { -+ int i; -+ -+ for (i = 0; i < domain->hwirq_max; i++) -+ if (pending & intc->irq_mask[i]) { -+ if (intc->irq_wb_chan[i] != 0xffffffff) -+ ath79_ddr_wb_flush(intc->irq_wb_chan[i]); -+ generic_handle_irq(irq_find_mapping(domain, i)); -+ } -+ } else { -+ spurious_interrupt(); -+ } -+} -+ -+static void ath79_intc_irq_enable(struct irq_data *d) -+{ -+ struct ath79_intc *intc = d->domain->host_data; -+ enable_irq(intc->irq); -+} -+ -+static void ath79_intc_irq_disable(struct irq_data *d) -+{ -+ struct ath79_intc *intc = d->domain->host_data; -+ disable_irq(intc->irq); -+} -+ -+static int ath79_intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) -+{ -+ struct ath79_intc *intc = d->host_data; -+ -+ irq_set_chip_and_handler(irq, &intc->chip, handle_level_irq); -+ -+ return 0; -+} -+ -+static const struct irq_domain_ops ath79_irq_domain_ops = { -+ .xlate = irq_domain_xlate_onecell, -+ .map = ath79_intc_map, -+}; -+ -+static int __init ath79_intc_of_init( -+ struct device_node *node, struct device_node *parent) -+{ -+ struct irq_domain *domain; -+ struct ath79_intc *intc; -+ int cnt, cntwb, i, err; -+ -+ cnt = of_property_count_u32_elems(node, "qca,pending-bits"); -+ if (cnt > ATH79_MAX_INTC_CASCADE) -+ panic("Too many INTC pending bits\n"); -+ -+ intc = kzalloc(sizeof(*intc), GFP_KERNEL); -+ if (!intc) -+ panic("Failed to allocate INTC memory\n"); -+ intc->chip = dummy_irq_chip; -+ intc->chip.name = "INTC"; -+ intc->chip.irq_disable = ath79_intc_irq_disable; -+ intc->chip.irq_enable = ath79_intc_irq_enable; -+ -+ if (of_property_read_u32(node, "qca,int-status-addr", &intc->int_status) < 0) { -+ panic("Missing address of interrupt status register\n"); -+ } -+ -+ of_property_read_u32_array(node, "qca,pending-bits", intc->irq_mask, cnt); -+ for (i = 0; i < cnt; i++) { -+ intc->pending_mask |= intc->irq_mask[i]; -+ intc->irq_wb_chan[i] = 0xffffffff; -+ } -+ -+ cntwb = of_count_phandle_with_args( -+ node, "qca,ddr-wb-channels", "#qca,ddr-wb-channel-cells"); -+ -+ for (i = 0; i < cntwb; i++) { -+ struct of_phandle_args args; -+ u32 irq = i; -+ -+ of_property_read_u32_index( -+ node, "qca,ddr-wb-channel-interrupts", i, &irq); -+ if (irq >= ATH79_MAX_INTC_CASCADE) -+ continue; -+ -+ err = of_parse_phandle_with_args( -+ node, "qca,ddr-wb-channels", -+ "#qca,ddr-wb-channel-cells", -+ i, &args); -+ if (err) -+ return err; -+ -+ intc->irq_wb_chan[irq] = args.args[0]; -+ } -+ -+ intc->irq = irq_of_parse_and_map(node, 0); -+ if (!intc->irq) -+ panic("Failed to get INTC IRQ"); -+ -+ domain = irq_domain_add_linear(node, cnt, &ath79_irq_domain_ops, intc); -+ irq_set_chained_handler_and_data(intc->irq, ath79_intc_irq_handler, domain); -+ -+ return 0; -+} -+IRQCHIP_DECLARE(ath79_intc, "qca,ar9340-intc", -+ ath79_intc_of_init); diff --git a/target/linux/ath79/patches-6.18/800-leds-add-reset-controller-based-driver.patch b/target/linux/ath79/patches-6.18/800-leds-add-reset-controller-based-driver.patch index febdadd666..f3a0f8ebea 100644 --- a/target/linux/ath79/patches-6.18/800-leds-add-reset-controller-based-driver.patch +++ b/target/linux/ath79/patches-6.18/800-leds-add-reset-controller-based-driver.patch @@ -31,149 +31,6 @@ Signed-off-by: John Crispin comment "LED Triggers" source "drivers/leds/trigger/Kconfig" ---- /dev/null -+++ b/drivers/leds/leds-reset.c -@@ -0,0 +1,140 @@ -+/* -+ * Copyright (C) 2018 John Crispin -+ * -+ * 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. -+ * -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct reset_led_data { -+ struct led_classdev cdev; -+ struct reset_control *rst; -+}; -+ -+static inline struct reset_led_data * -+ cdev_to_reset_led_data(struct led_classdev *led_cdev) -+{ -+ return container_of(led_cdev, struct reset_led_data, cdev); -+} -+ -+static void reset_led_set(struct led_classdev *led_cdev, -+ enum led_brightness value) -+{ -+ struct reset_led_data *led_dat = cdev_to_reset_led_data(led_cdev); -+ -+ if (value == LED_OFF) -+ reset_control_assert(led_dat->rst); -+ else -+ reset_control_deassert(led_dat->rst); -+} -+ -+struct reset_leds_priv { -+ int num_leds; -+ struct reset_led_data leds[]; -+}; -+ -+static inline int sizeof_reset_leds_priv(int num_leds) -+{ -+ return sizeof(struct reset_leds_priv) + -+ (sizeof(struct reset_led_data) * num_leds); -+} -+ -+static struct reset_leds_priv *reset_leds_create(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct fwnode_handle *child; -+ struct reset_leds_priv *priv; -+ int count, ret; -+ -+ count = device_get_child_node_count(dev); -+ if (!count) -+ return ERR_PTR(-ENODEV); -+ -+ priv = devm_kzalloc(dev, sizeof_reset_leds_priv(count), GFP_KERNEL); -+ if (!priv) -+ return ERR_PTR(-ENOMEM); -+ -+ device_for_each_child_node(dev, child) { -+ struct reset_led_data *led = &priv->leds[priv->num_leds]; -+ struct device_node *np = to_of_node(child); -+ -+ ret = fwnode_property_read_string(child, "label", &led->cdev.name); -+ if (!led->cdev.name) { -+ fwnode_handle_put(child); -+ return ERR_PTR(-EINVAL); -+ } -+ led->rst = __of_reset_control_get(np, NULL, 0, RESET_CONTROL_EXCLUSIVE); -+ if (IS_ERR(led->rst)) -+ return ERR_PTR(-EINVAL); -+ -+ fwnode_property_read_string(child, "linux,default-trigger", -+ &led->cdev.default_trigger); -+ -+ led->cdev.brightness_set = reset_led_set; -+ ret = devm_led_classdev_register(&pdev->dev, &led->cdev); -+ if (ret < 0) -+ return ERR_PTR(ret); -+ led->cdev.dev->of_node = np; -+ priv->num_leds++; -+ } -+ -+ return priv; -+} -+ -+static const struct of_device_id of_reset_leds_match[] = { -+ { .compatible = "reset-leds", }, -+ {}, -+}; -+ -+MODULE_DEVICE_TABLE(of, of_reset_leds_match); -+ -+static int reset_led_probe(struct platform_device *pdev) -+{ -+ struct reset_leds_priv *priv; -+ -+ priv = reset_leds_create(pdev); -+ if (IS_ERR(priv)) -+ return PTR_ERR(priv); -+ -+ platform_set_drvdata(pdev, priv); -+ -+ return 0; -+} -+ -+static void reset_led_shutdown(struct platform_device *pdev) -+{ -+ struct reset_leds_priv *priv = platform_get_drvdata(pdev); -+ int i; -+ -+ for (i = 0; i < priv->num_leds; i++) { -+ struct reset_led_data *led = &priv->leds[i]; -+ -+ if (!(led->cdev.flags & LED_RETAIN_AT_SHUTDOWN)) -+ reset_led_set(&led->cdev, LED_OFF); -+ } -+} -+ -+static struct platform_driver reset_led_driver = { -+ .probe = reset_led_probe, -+ .shutdown = reset_led_shutdown, -+ .driver = { -+ .name = "leds-reset", -+ .of_match_table = of_reset_leds_match, -+ }, -+}; -+ -+module_platform_driver(reset_led_driver); -+ -+MODULE_AUTHOR("John Crispin "); -+MODULE_DESCRIPTION("reset controller LED driver"); -+MODULE_LICENSE("GPL"); -+MODULE_ALIAS("platform:leds-reset"); --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -98,6 +98,7 @@ obj-$(CONFIG_LEDS_UPBOARD) += leds-upbo diff --git a/target/linux/bcm27xx/bcm2712/config-6.12 b/target/linux/bcm27xx/bcm2712/config-6.12 index eaf00f4bf6..47ceac7024 100644 --- a/target/linux/bcm27xx/bcm2712/config-6.12 +++ b/target/linux/bcm27xx/bcm2712/config-6.12 @@ -30,6 +30,7 @@ CONFIG_ARM64_ERRATUM_1165522=y CONFIG_ARM64_ERRATUM_1286807=y CONFIG_ARM64_ERRATUM_1463225=y CONFIG_ARM64_ERRATUM_3194386=y +CONFIG_ARM64_ERRATUM_4118414=y CONFIG_ARM64_HW_AFDBM=y CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y CONFIG_ARM64_PA_BITS=48 diff --git a/target/linux/bcm27xx/patches-6.12/950-0322-Bluetooth-hci_sync-Add-fallback-bd-address-prop.patch b/target/linux/bcm27xx/patches-6.12/950-0322-Bluetooth-hci_sync-Add-fallback-bd-address-prop.patch index 4e0895dc45..b50b49f2a4 100644 --- a/target/linux/bcm27xx/patches-6.12/950-0322-Bluetooth-hci_sync-Add-fallback-bd-address-prop.patch +++ b/target/linux/bcm27xx/patches-6.12/950-0322-Bluetooth-hci_sync-Add-fallback-bd-address-prop.patch @@ -20,7 +20,7 @@ Signed-off-by: Phil Elwell --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c -@@ -4942,6 +4942,7 @@ static const struct { +@@ -4961,6 +4961,7 @@ static const struct { */ static int hci_dev_setup_sync(struct hci_dev *hdev) { @@ -28,7 +28,7 @@ Signed-off-by: Phil Elwell int ret = 0; bool invalid_bdaddr; size_t i; -@@ -4970,7 +4971,8 @@ static int hci_dev_setup_sync(struct hci +@@ -4989,7 +4990,8 @@ static int hci_dev_setup_sync(struct hci test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks); if (!ret) { if (test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks) && diff --git a/target/linux/bcm27xx/patches-6.12/950-0344-sdhci-Add-SD-Express-hook.patch b/target/linux/bcm27xx/patches-6.12/950-0344-sdhci-Add-SD-Express-hook.patch index 2b695742ed..64c0bfb700 100644 --- a/target/linux/bcm27xx/patches-6.12/950-0344-sdhci-Add-SD-Express-hook.patch +++ b/target/linux/bcm27xx/patches-6.12/950-0344-sdhci-Add-SD-Express-hook.patch @@ -51,7 +51,7 @@ sdhci: remove PYA0_INTR_BUG quirk. Add quirks to disable some of the higher SDR }; /*****************************************************************************\ -@@ -4572,6 +4582,15 @@ int sdhci_setup_host(struct sdhci_host * +@@ -4573,6 +4583,15 @@ int sdhci_setup_host(struct sdhci_host * !(host->quirks2 & SDHCI_QUIRK2_BROKEN_DDR50)) mmc->caps |= MMC_CAP_UHS_DDR50; diff --git a/target/linux/bcm27xx/patches-6.12/950-0434-drivers-mmc-add-debugfs-entries-for-SD-extension-reg.patch b/target/linux/bcm27xx/patches-6.12/950-0434-drivers-mmc-add-debugfs-entries-for-SD-extension-reg.patch index eafdd01140..1cc5a26d0a 100644 --- a/target/linux/bcm27xx/patches-6.12/950-0434-drivers-mmc-add-debugfs-entries-for-SD-extension-reg.patch +++ b/target/linux/bcm27xx/patches-6.12/950-0434-drivers-mmc-add-debugfs-entries-for-SD-extension-reg.patch @@ -13,7 +13,7 @@ Signed-off-by: Jonathan Bell --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c -@@ -1915,8 +1915,8 @@ static int mmc_init_card(struct mmc_host +@@ -1917,8 +1917,8 @@ static int mmc_init_card(struct mmc_host host->cqe_enabled = true; if (card->ext_csd.cmdq_en) { diff --git a/target/linux/bcm27xx/patches-6.12/950-0437-mmc-sdhci-extend-maximum-ADMA-transfer-length-to-4Mi.patch b/target/linux/bcm27xx/patches-6.12/950-0437-mmc-sdhci-extend-maximum-ADMA-transfer-length-to-4Mi.patch index 39c26127fb..5c6296a2b5 100644 --- a/target/linux/bcm27xx/patches-6.12/950-0437-mmc-sdhci-extend-maximum-ADMA-transfer-length-to-4Mi.patch +++ b/target/linux/bcm27xx/patches-6.12/950-0437-mmc-sdhci-extend-maximum-ADMA-transfer-length-to-4Mi.patch @@ -23,7 +23,7 @@ Signed-off-by: Jonathan Bell BUG_ON(data->blksz > host->mmc->max_blk_size); BUG_ON(data->blocks > 65535); -@@ -4716,11 +4716,16 @@ int sdhci_setup_host(struct sdhci_host * +@@ -4717,11 +4717,16 @@ int sdhci_setup_host(struct sdhci_host * spin_lock_init(&host->lock); /* diff --git a/target/linux/bcm27xx/patches-6.12/950-0440-mmc-restrict-posted-write-counts-for-SD-cards-in-CQ-.patch b/target/linux/bcm27xx/patches-6.12/950-0440-mmc-restrict-posted-write-counts-for-SD-cards-in-CQ-.patch index df94ea0ca5..995105eff6 100644 --- a/target/linux/bcm27xx/patches-6.12/950-0440-mmc-restrict-posted-write-counts-for-SD-cards-in-CQ-.patch +++ b/target/linux/bcm27xx/patches-6.12/950-0440-mmc-restrict-posted-write-counts-for-SD-cards-in-CQ-.patch @@ -85,7 +85,7 @@ Signed-off-by: Jonathan Bell void mmc_blk_mq_recovery(struct mmc_queue *mq) --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c -@@ -1657,6 +1657,7 @@ static int mmc_init_card(struct mmc_host +@@ -1659,6 +1659,7 @@ static int mmc_init_card(struct mmc_host card->ocr = ocr; card->type = MMC_TYPE_MMC; card->rca = 1; @@ -93,7 +93,7 @@ Signed-off-by: Jonathan Bell memcpy(card->raw_cid, cid, sizeof(card->raw_cid)); } -@@ -1922,6 +1923,7 @@ static int mmc_init_card(struct mmc_host +@@ -1924,6 +1925,7 @@ static int mmc_init_card(struct mmc_host pr_info("%s: Host Software Queue enabled\n", mmc_hostname(host)); } diff --git a/target/linux/bcm27xx/patches-6.12/950-0502-Bluetooth-hci_sync-Fix-crash-on-NULL-parent.patch b/target/linux/bcm27xx/patches-6.12/950-0502-Bluetooth-hci_sync-Fix-crash-on-NULL-parent.patch index ee48969572..98c428e7a8 100644 --- a/target/linux/bcm27xx/patches-6.12/950-0502-Bluetooth-hci_sync-Fix-crash-on-NULL-parent.patch +++ b/target/linux/bcm27xx/patches-6.12/950-0502-Bluetooth-hci_sync-Fix-crash-on-NULL-parent.patch @@ -15,7 +15,7 @@ Signed-off-by: Phil Elwell --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c -@@ -4942,7 +4942,8 @@ static const struct { +@@ -4961,7 +4961,8 @@ static const struct { */ static int hci_dev_setup_sync(struct hci_dev *hdev) { diff --git a/target/linux/bcm27xx/patches-6.12/950-0588-drm-vc4-Make-v3d-paths-unavailable-on-any-generation.patch b/target/linux/bcm27xx/patches-6.12/950-0588-drm-vc4-Make-v3d-paths-unavailable-on-any-generation.patch index 1c5725d7aa..5b43bbf224 100644 --- a/target/linux/bcm27xx/patches-6.12/950-0588-drm-vc4-Make-v3d-paths-unavailable-on-any-generation.patch +++ b/target/linux/bcm27xx/patches-6.12/950-0588-drm-vc4-Make-v3d-paths-unavailable-on-any-generation.patch @@ -569,7 +569,7 @@ Signed-off-by: Dave Stevenson 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 +@@ -787,7 +787,7 @@ vc4_validate_shader(struct drm_gem_dma_o struct vc4_validated_shader_info *validated_shader = NULL; struct vc4_shader_validation_state validation_state; diff --git a/target/linux/bcm27xx/patches-6.12/950-0777-drm-v3d-Remove-v3d-cpu_job.patch b/target/linux/bcm27xx/patches-6.12/950-0777-drm-v3d-Remove-v3d-cpu_job.patch index 620f208543..436740ffbc 100644 --- a/target/linux/bcm27xx/patches-6.12/950-0777-drm-v3d-Remove-v3d-cpu_job.patch +++ b/target/linux/bcm27xx/patches-6.12/950-0777-drm-v3d-Remove-v3d-cpu_job.patch @@ -35,7 +35,7 @@ Link: https://patchwork.freedesktop.org/patch/msgid/20250113154741.67520-2-mcana --- a/drivers/gpu/drm/v3d/v3d_sched.c +++ b/drivers/gpu/drm/v3d/v3d_sched.c -@@ -663,8 +663,6 @@ v3d_cpu_job_run(struct drm_sched_job *sc +@@ -664,8 +664,6 @@ v3d_cpu_job_run(struct drm_sched_job *sc struct v3d_cpu_job *job = to_cpu_job(sched_job); struct v3d_dev *v3d = job->base.v3d; diff --git a/target/linux/bcm53xx/base-files/etc/board.d/02_network b/target/linux/bcm53xx/base-files/etc/board.d/02_network index f255edf8b5..1b8baed147 100644 --- a/target/linux/bcm53xx/base-files/etc/board.d/02_network +++ b/target/linux/bcm53xx/base-files/etc/board.d/02_network @@ -53,25 +53,28 @@ bcm53xx_setup_macs() wan_macaddr="$(nvram get wan_hwaddr)" case "$board" in - asus,rt-ac87u) - etXmacaddr=$(nvram get et1macaddr) - offset=1 - ;; - dlink,dir-885l | \ - linksys,ea9200 | \ - linksys,panamera | \ netgear,r7900 | \ netgear,r8000 | \ netgear,r8500) etXmacaddr=$(nvram get et2macaddr) offset=1 ;; - luxul,xwr-3100-v1 | \ - luxul,xwr-3150-v1) - etXmacaddr=$(nvram get et0macaddr) - offset=5 - ;; - *) + asus,rt-ac3200|\ + asus,rt-ac5300|\ + asus,rt-ac56u|\ + asus,rt-ac68u|\ + asus,rt-n18u|\ + buffalo,wxr-1900dhp|\ + buffalo,wzr-600dhp2|\ + buffalo,wzr-900dhp|\ + buffalo,wzr-1750dhp|\ + dlink,dir-890l|\ + linksys,ea6500-v2|\ + netgear,r6250-v1|\ + netgear,r6300-v2|\ + netgear,r7000|\ + smartrg,sr400ac|\ + tenda,ac9) etXmacaddr=$(nvram get et0macaddr) offset=1 ;; diff --git a/target/linux/bcm53xx/patches-6.12/304-ARM-dts-BCM5301X-Specify-switch-ports-for-remaining-.patch b/target/linux/bcm53xx/patches-6.12/304-ARM-dts-BCM5301X-Specify-switch-ports-for-remaining-.patch index 9cfc3aac15..c09a690cb8 100644 --- a/target/linux/bcm53xx/patches-6.12/304-ARM-dts-BCM5301X-Specify-switch-ports-for-remaining-.patch +++ b/target/linux/bcm53xx/patches-6.12/304-ARM-dts-BCM5301X-Specify-switch-ports-for-remaining-.patch @@ -140,50 +140,6 @@ Signed-off-by: Rafał Miłecki + }; + }; +}; ---- a/arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6300-v1.dts -+++ b/arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6300-v1.dts -@@ -46,3 +46,41 @@ - &usb3_phy { - status = "okay"; - }; -+ -+&srab { -+ status = "okay"; -+ -+ ports { -+ port@0 { -+ label = "lan1"; -+ }; -+ -+ port@1 { -+ label = "lan2"; -+ }; -+ -+ port@2 { -+ label = "lan3"; -+ }; -+ -+ port@3 { -+ label = "lan4"; -+ }; -+ -+ port@4 { -+ label = "wan"; -+ }; -+ -+ port@5 { -+ label = "cpu"; -+ }; -+ -+ port@7 { -+ status = "disabled"; -+ }; -+ -+ port@8 { -+ status = "disabled"; -+ }; -+ }; -+}; --- a/arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6500-v2.dts +++ b/arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6500-v2.dts @@ -43,3 +43,41 @@ @@ -316,49 +272,6 @@ Signed-off-by: Rafał Miłecki + }; + }; +}; ---- a/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts -+++ b/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts -@@ -77,6 +77,40 @@ - status = "okay"; - }; - -+&srab { -+ status = "okay"; -+ -+ ports { -+ port@0 { -+ label = "wan"; -+ }; -+ -+ port@1 { -+ label = "lan1"; -+ }; -+ -+ port@2 { -+ label = "lan2"; -+ }; -+ -+ port@3 { -+ label = "lan3"; -+ }; -+ -+ port@5 { -+ status = "disabled"; -+ }; -+ -+ port@7 { -+ label = "cpu"; -+ }; -+ -+ port@8 { -+ status = "disabled"; -+ }; -+ }; -+}; -+ - &nandcs { - partitions { - compatible = "fixed-partitions"; --- a/arch/arm/boot/dts/broadcom/bcm4709-buffalo-wxr-1900dhp.dts +++ b/arch/arm/boot/dts/broadcom/bcm4709-buffalo-wxr-1900dhp.dts @@ -130,3 +130,41 @@ @@ -491,49 +404,6 @@ Signed-off-by: Rafał Miłecki + }; + }; +}; ---- a/arch/arm/boot/dts/broadcom/bcm47094-phicomm-k3.dts -+++ b/arch/arm/boot/dts/broadcom/bcm47094-phicomm-k3.dts -@@ -38,6 +38,40 @@ - status = "okay"; - }; - -+&srab { -+ status = "okay"; -+ -+ ports { -+ port@0 { -+ label = "lan1"; -+ }; -+ -+ port@1 { -+ label = "lan2"; -+ }; -+ -+ port@2 { -+ label = "lan3"; -+ }; -+ -+ port@3 { -+ label = "wan"; -+ }; -+ -+ port@5 { -+ label = "cpu"; -+ }; -+ -+ port@7 { -+ status = "disabled"; -+ }; -+ -+ port@8 { -+ status = "disabled"; -+ }; -+ }; -+}; -+ - &nandcs { - partitions { - compatible = "fixed-partitions"; --- a/arch/arm/boot/dts/broadcom/bcm47081-tplink-archer-c5-v2.dts +++ b/arch/arm/boot/dts/broadcom/bcm47081-tplink-archer-c5-v2.dts @@ -91,6 +91,44 @@ diff --git a/target/linux/bcm53xx/patches-6.12/311-ARM-dts-BCM5301X-EA9200-set-WAN-MAC-from-nvram.patch b/target/linux/bcm53xx/patches-6.12/311-ARM-dts-BCM5301X-EA9200-set-WAN-MAC-from-nvram.patch new file mode 100644 index 0000000000..3abec78a61 --- /dev/null +++ b/target/linux/bcm53xx/patches-6.12/311-ARM-dts-BCM5301X-EA9200-set-WAN-MAC-from-nvram.patch @@ -0,0 +1,36 @@ +From 3482a3f37240826c825d05fceebbfe5877f587d4 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Tue, 17 Feb 2026 20:20:16 -0800 +Subject: [PATCH] ARM: dts: BCM5301X: EA9200: set WAN MAC from nvram + +The MAC address from the stock firmare is offset by 1. Define it +properly to avoid having to override it in userspace. + +Signed-off-by: Rosen Penev +--- + arch/arm/boot/dts/broadcom/bcm4709-linksys-ea9200.dts | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/arch/arm/boot/dts/broadcom/bcm4709-linksys-ea9200.dts ++++ b/arch/arm/boot/dts/broadcom/bcm4709-linksys-ea9200.dts +@@ -25,6 +25,10 @@ + nvram@1c080000 { + compatible = "brcm,nvram"; + reg = <0x1c080000 0x180000>; ++ ++ et2macaddr: et2macaddr { ++ #nvmem-cell-cells = <1>; ++ }; + }; + + gpio-keys { +@@ -70,6 +74,9 @@ + + port@4 { + label = "wan"; ++ ++ nvmem-cells = <&et2macaddr 1>; ++ nvmem-cell-names = "mac-address"; + }; + + port@5 { diff --git a/target/linux/bcm53xx/patches-6.12/312-ARM-dts-BCM5301X-panamera-set-WAN-MAC-from-nvram.patch b/target/linux/bcm53xx/patches-6.12/312-ARM-dts-BCM5301X-panamera-set-WAN-MAC-from-nvram.patch new file mode 100644 index 0000000000..a775f7e1f0 --- /dev/null +++ b/target/linux/bcm53xx/patches-6.12/312-ARM-dts-BCM5301X-panamera-set-WAN-MAC-from-nvram.patch @@ -0,0 +1,36 @@ +From cbbaa1f69301755409bc3ddbf2401c8b87a73658 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Tue, 17 Feb 2026 20:30:02 -0800 +Subject: [PATCH] ARM: dts: BCM5301X: panamera: set WAN MAC from nvram + +The MAC address from the stock firmare is offset by 1. Define it +properly to avoid having to override it in userspace. + +Signed-off-by: Rosen Penev +--- + arch/arm/boot/dts/broadcom/bcm47094-linksys-panamera.dts | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/arch/arm/boot/dts/broadcom/bcm47094-linksys-panamera.dts ++++ b/arch/arm/boot/dts/broadcom/bcm47094-linksys-panamera.dts +@@ -25,6 +25,10 @@ + nvram@1c080000 { + compatible = "brcm,nvram"; + reg = <0x1c080000 0x100000>; ++ ++ et2macaddr: et2macaddr { ++ #nvmem-cell-cells = <1>; ++ }; + }; + + gpio-keys { +@@ -230,6 +234,9 @@ + + port@4 { + label = "wan"; ++ ++ nvmem-cells = <&et2macaddr 1>; ++ nvmem-cell-names = "mac-address"; + }; + + port@5 { diff --git a/target/linux/bcm53xx/patches-6.12/313-ARM-dts-BCM5301X-AC87U-specify-switch.patch b/target/linux/bcm53xx/patches-6.12/313-ARM-dts-BCM5301X-AC87U-specify-switch.patch new file mode 100644 index 0000000000..cefe251e0d --- /dev/null +++ b/target/linux/bcm53xx/patches-6.12/313-ARM-dts-BCM5301X-AC87U-specify-switch.patch @@ -0,0 +1,69 @@ +From cdcbe55d86588aa8c296847a445c1b1a59f4a617 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Tue, 17 Feb 2026 20:58:58 -0800 +Subject: [PATCH] ARM: dts: BCM5301X: AC87U: specify switch + +bcm-ns.dtsi specifies a default layout that is not correct for the +RT-AC87U. Also allows setting the WAN MAC address properly. + +Signed-off-by: Rosen Penev +--- + .../dts/broadcom/bcm4709-asus-rt-ac87u.dts | 40 +++++++++++++++++++ + 1 file changed, 40 insertions(+) + +--- a/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts ++++ b/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts +@@ -26,6 +26,9 @@ + }; + + nvram@1c080000 { ++ compatible = "brcm,nvram"; ++ reg = <0x1c080000 0x180000>; ++ + et1macaddr: et1macaddr { + #nvmem-cell-cells = <1>; + }; +@@ -77,6 +80,43 @@ + status = "okay"; + }; + ++&srab { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ label = "wan"; ++ ++ nvmem-cells = <&et1macaddr 1>; ++ nvmem-cell-names = "mac-address"; ++ }; ++ ++ port@1 { ++ label = "lan1"; ++ }; ++ ++ port@2 { ++ label = "lan2"; ++ }; ++ ++ port@3 { ++ label = "lan3"; ++ }; ++ ++ port@5 { ++ status = "disabled"; ++ }; ++ ++ port@7 { ++ label = "cpu"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; ++ }; ++}; ++ + &nandcs { + partitions { + compatible = "fixed-partitions"; diff --git a/target/linux/bcm53xx/patches-6.12/314-ARM-dts-BCM5301X-EA6300-specify-switch.patch b/target/linux/bcm53xx/patches-6.12/314-ARM-dts-BCM5301X-EA6300-specify-switch.patch new file mode 100644 index 0000000000..259cd312ab --- /dev/null +++ b/target/linux/bcm53xx/patches-6.12/314-ARM-dts-BCM5301X-EA6300-specify-switch.patch @@ -0,0 +1,71 @@ +From c4c21947b9a641131afe07d6c5f1abd3ff6b8bb0 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Tue, 17 Feb 2026 21:05:09 -0800 +Subject: [PATCH] ARM: dts: BCM5301X: EA6300: specify switch + +bcm-ns.dtsi specifies a default layout that is not correct for the +EA6300. Also allows setting the WAN MAC address properly. + +Signed-off-by: Rosen Penev +--- + .../broadcom/bcm4708-linksys-ea6300-v1.dts | 45 +++++++++++++++++++ + 1 file changed, 45 insertions(+) + +--- a/arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6300-v1.dts ++++ b/arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6300-v1.dts +@@ -24,6 +24,10 @@ + nvram@1c080000 { + compatible = "brcm,nvram"; + reg = <0x1c080000 0x180000>; ++ ++ et0macaddr: et0macaddr { ++ #nvmem-cell-cells = <1>; ++ }; + }; + + gpio-keys { +@@ -46,3 +50,44 @@ + &usb3_phy { + status = "okay"; + }; ++ ++&srab { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ label = "lan1"; ++ }; ++ ++ port@1 { ++ label = "lan2"; ++ }; ++ ++ port@2 { ++ label = "lan3"; ++ }; ++ ++ port@3 { ++ label = "lan4"; ++ }; ++ ++ port@4 { ++ label = "wan"; ++ ++ nvmem-cells = <&et0macaddr 1>; ++ nvmem-cell-names = "mac-address"; ++ }; ++ ++ port@5 { ++ label = "cpu"; ++ }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; ++ }; ++}; diff --git a/target/linux/bcm53xx/patches-6.12/315-ARM-dts-BCM5301X-phicomm-k3-specify-switch.patch b/target/linux/bcm53xx/patches-6.12/315-ARM-dts-BCM5301X-phicomm-k3-specify-switch.patch new file mode 100644 index 0000000000..84aa912e11 --- /dev/null +++ b/target/linux/bcm53xx/patches-6.12/315-ARM-dts-BCM5301X-phicomm-k3-specify-switch.patch @@ -0,0 +1,75 @@ +From 22785d47e3a5a8e5321586a9776a70a5e88148a2 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Tue, 17 Feb 2026 21:13:49 -0800 +Subject: [PATCH] ARM: dts: BCM5301X: phicomm-k3: specify switch + +bcm-ns.dtsi specifies a default layout that is not correct for the +K3. Also allows setting the WAN MAC address properly. + +Signed-off-by: Rosen Penev +--- + .../boot/dts/broadcom/bcm47094-phicomm-k3.dts | 46 +++++++++++++++++++ + 1 file changed, 46 insertions(+) + +--- a/arch/arm/boot/dts/broadcom/bcm47094-phicomm-k3.dts ++++ b/arch/arm/boot/dts/broadcom/bcm47094-phicomm-k3.dts +@@ -19,6 +19,15 @@ + <0x88000000 0x18000000>; + }; + ++ nvram@1c080000 { ++ compatible = "brcm,nvram"; ++ reg = <0x1c080000 0x100000>; ++ ++ et0macaddr: et0macaddr { ++ #nvmem-cell-cells = <1>; ++ }; ++ }; ++ + gpio-keys { + compatible = "gpio-keys"; + +@@ -38,6 +47,43 @@ + status = "okay"; + }; + ++&srab { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ label = "lan1"; ++ }; ++ ++ port@1 { ++ label = "lan2"; ++ }; ++ ++ port@2 { ++ label = "lan3"; ++ }; ++ ++ port@3 { ++ label = "wan"; ++ ++ nvmem-cells = <&et0macaddr 1>; ++ nvmem-cell-names = "mac-address"; ++ }; ++ ++ port@5 { ++ label = "cpu"; ++ }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; ++ }; ++}; ++ + &nandcs { + partitions { + compatible = "fixed-partitions"; diff --git a/target/linux/bcm53xx/patches-6.12/331-v7.2-ARM-dts-NSP-Move-MX6X-pinctrl-config-to-PWM-node.patch b/target/linux/bcm53xx/patches-6.12/331-v7.2-ARM-dts-NSP-Move-MX6X-pinctrl-config-to-PWM-node.patch new file mode 100644 index 0000000000..515d2b7df9 --- /dev/null +++ b/target/linux/bcm53xx/patches-6.12/331-v7.2-ARM-dts-NSP-Move-MX6X-pinctrl-config-to-PWM-node.patch @@ -0,0 +1,41 @@ +From d7b3f4a4eb23d82ef923cf17509292b719340378 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Wed, 29 Apr 2026 22:16:12 -0700 +Subject: [PATCH] ARM: dts: NSP: Move MX6X pinctrl config to PWM node + +On boot there is this warning: + +/axi@18000000/pinctrl@3f1c0: Fixed dependency cycle(s) with /axi@18000000/pinctrl@3f1c0/pwm_leds + +Fix by moving the pinctrl configuration to pwm, which is the actual +consumer. + +Signed-off-by: Rosen Penev +Link: https://lore.kernel.org/r/20260430051612.700050-1-rosenp@gmail.com +Signed-off-by: Florian Fainelli +--- + .../arm/boot/dts/broadcom/bcm958625-meraki-mx6x-common.dtsi | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/arch/arm/boot/dts/broadcom/bcm958625-meraki-mx6x-common.dtsi ++++ b/arch/arm/boot/dts/broadcom/bcm958625-meraki-mx6x-common.dtsi +@@ -121,9 +121,6 @@ + }; + + &pinctrl { +- pinctrl-names = "default"; +- pinctrl-0 = <&pwm_leds>; +- + pwm_leds: pwm_leds { + function = "pwm"; + groups = "pwm1_grp", "pwm2_grp", "pwm3_grp"; +@@ -131,6 +128,9 @@ + }; + + &pwm { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwm_leds>; ++ + status = "okay"; + #pwm-cells = <2>; + }; diff --git a/target/linux/bcm53xx/patches-6.18/304-ARM-dts-BCM5301X-Specify-switch-ports-for-remaining-.patch b/target/linux/bcm53xx/patches-6.18/304-ARM-dts-BCM5301X-Specify-switch-ports-for-remaining-.patch index 9cfc3aac15..c09a690cb8 100644 --- a/target/linux/bcm53xx/patches-6.18/304-ARM-dts-BCM5301X-Specify-switch-ports-for-remaining-.patch +++ b/target/linux/bcm53xx/patches-6.18/304-ARM-dts-BCM5301X-Specify-switch-ports-for-remaining-.patch @@ -140,50 +140,6 @@ Signed-off-by: Rafał Miłecki + }; + }; +}; ---- a/arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6300-v1.dts -+++ b/arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6300-v1.dts -@@ -46,3 +46,41 @@ - &usb3_phy { - status = "okay"; - }; -+ -+&srab { -+ status = "okay"; -+ -+ ports { -+ port@0 { -+ label = "lan1"; -+ }; -+ -+ port@1 { -+ label = "lan2"; -+ }; -+ -+ port@2 { -+ label = "lan3"; -+ }; -+ -+ port@3 { -+ label = "lan4"; -+ }; -+ -+ port@4 { -+ label = "wan"; -+ }; -+ -+ port@5 { -+ label = "cpu"; -+ }; -+ -+ port@7 { -+ status = "disabled"; -+ }; -+ -+ port@8 { -+ status = "disabled"; -+ }; -+ }; -+}; --- a/arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6500-v2.dts +++ b/arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6500-v2.dts @@ -43,3 +43,41 @@ @@ -316,49 +272,6 @@ Signed-off-by: Rafał Miłecki + }; + }; +}; ---- a/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts -+++ b/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts -@@ -77,6 +77,40 @@ - status = "okay"; - }; - -+&srab { -+ status = "okay"; -+ -+ ports { -+ port@0 { -+ label = "wan"; -+ }; -+ -+ port@1 { -+ label = "lan1"; -+ }; -+ -+ port@2 { -+ label = "lan2"; -+ }; -+ -+ port@3 { -+ label = "lan3"; -+ }; -+ -+ port@5 { -+ status = "disabled"; -+ }; -+ -+ port@7 { -+ label = "cpu"; -+ }; -+ -+ port@8 { -+ status = "disabled"; -+ }; -+ }; -+}; -+ - &nandcs { - partitions { - compatible = "fixed-partitions"; --- a/arch/arm/boot/dts/broadcom/bcm4709-buffalo-wxr-1900dhp.dts +++ b/arch/arm/boot/dts/broadcom/bcm4709-buffalo-wxr-1900dhp.dts @@ -130,3 +130,41 @@ @@ -491,49 +404,6 @@ Signed-off-by: Rafał Miłecki + }; + }; +}; ---- a/arch/arm/boot/dts/broadcom/bcm47094-phicomm-k3.dts -+++ b/arch/arm/boot/dts/broadcom/bcm47094-phicomm-k3.dts -@@ -38,6 +38,40 @@ - status = "okay"; - }; - -+&srab { -+ status = "okay"; -+ -+ ports { -+ port@0 { -+ label = "lan1"; -+ }; -+ -+ port@1 { -+ label = "lan2"; -+ }; -+ -+ port@2 { -+ label = "lan3"; -+ }; -+ -+ port@3 { -+ label = "wan"; -+ }; -+ -+ port@5 { -+ label = "cpu"; -+ }; -+ -+ port@7 { -+ status = "disabled"; -+ }; -+ -+ port@8 { -+ status = "disabled"; -+ }; -+ }; -+}; -+ - &nandcs { - partitions { - compatible = "fixed-partitions"; --- a/arch/arm/boot/dts/broadcom/bcm47081-tplink-archer-c5-v2.dts +++ b/arch/arm/boot/dts/broadcom/bcm47081-tplink-archer-c5-v2.dts @@ -91,6 +91,44 @@ diff --git a/target/linux/bcm53xx/patches-6.18/311-ARM-dts-BCM5301X-EA9200-set-WAN-MAC-from-nvram.patch b/target/linux/bcm53xx/patches-6.18/311-ARM-dts-BCM5301X-EA9200-set-WAN-MAC-from-nvram.patch new file mode 100644 index 0000000000..3abec78a61 --- /dev/null +++ b/target/linux/bcm53xx/patches-6.18/311-ARM-dts-BCM5301X-EA9200-set-WAN-MAC-from-nvram.patch @@ -0,0 +1,36 @@ +From 3482a3f37240826c825d05fceebbfe5877f587d4 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Tue, 17 Feb 2026 20:20:16 -0800 +Subject: [PATCH] ARM: dts: BCM5301X: EA9200: set WAN MAC from nvram + +The MAC address from the stock firmare is offset by 1. Define it +properly to avoid having to override it in userspace. + +Signed-off-by: Rosen Penev +--- + arch/arm/boot/dts/broadcom/bcm4709-linksys-ea9200.dts | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/arch/arm/boot/dts/broadcom/bcm4709-linksys-ea9200.dts ++++ b/arch/arm/boot/dts/broadcom/bcm4709-linksys-ea9200.dts +@@ -25,6 +25,10 @@ + nvram@1c080000 { + compatible = "brcm,nvram"; + reg = <0x1c080000 0x180000>; ++ ++ et2macaddr: et2macaddr { ++ #nvmem-cell-cells = <1>; ++ }; + }; + + gpio-keys { +@@ -70,6 +74,9 @@ + + port@4 { + label = "wan"; ++ ++ nvmem-cells = <&et2macaddr 1>; ++ nvmem-cell-names = "mac-address"; + }; + + port@5 { diff --git a/target/linux/bcm53xx/patches-6.18/312-ARM-dts-BCM5301X-panamera-set-WAN-MAC-from-nvram.patch b/target/linux/bcm53xx/patches-6.18/312-ARM-dts-BCM5301X-panamera-set-WAN-MAC-from-nvram.patch new file mode 100644 index 0000000000..a775f7e1f0 --- /dev/null +++ b/target/linux/bcm53xx/patches-6.18/312-ARM-dts-BCM5301X-panamera-set-WAN-MAC-from-nvram.patch @@ -0,0 +1,36 @@ +From cbbaa1f69301755409bc3ddbf2401c8b87a73658 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Tue, 17 Feb 2026 20:30:02 -0800 +Subject: [PATCH] ARM: dts: BCM5301X: panamera: set WAN MAC from nvram + +The MAC address from the stock firmare is offset by 1. Define it +properly to avoid having to override it in userspace. + +Signed-off-by: Rosen Penev +--- + arch/arm/boot/dts/broadcom/bcm47094-linksys-panamera.dts | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/arch/arm/boot/dts/broadcom/bcm47094-linksys-panamera.dts ++++ b/arch/arm/boot/dts/broadcom/bcm47094-linksys-panamera.dts +@@ -25,6 +25,10 @@ + nvram@1c080000 { + compatible = "brcm,nvram"; + reg = <0x1c080000 0x100000>; ++ ++ et2macaddr: et2macaddr { ++ #nvmem-cell-cells = <1>; ++ }; + }; + + gpio-keys { +@@ -230,6 +234,9 @@ + + port@4 { + label = "wan"; ++ ++ nvmem-cells = <&et2macaddr 1>; ++ nvmem-cell-names = "mac-address"; + }; + + port@5 { diff --git a/target/linux/bcm53xx/patches-6.18/313-ARM-dts-BCM5301X-AC87U-specify-switch.patch b/target/linux/bcm53xx/patches-6.18/313-ARM-dts-BCM5301X-AC87U-specify-switch.patch new file mode 100644 index 0000000000..cefe251e0d --- /dev/null +++ b/target/linux/bcm53xx/patches-6.18/313-ARM-dts-BCM5301X-AC87U-specify-switch.patch @@ -0,0 +1,69 @@ +From cdcbe55d86588aa8c296847a445c1b1a59f4a617 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Tue, 17 Feb 2026 20:58:58 -0800 +Subject: [PATCH] ARM: dts: BCM5301X: AC87U: specify switch + +bcm-ns.dtsi specifies a default layout that is not correct for the +RT-AC87U. Also allows setting the WAN MAC address properly. + +Signed-off-by: Rosen Penev +--- + .../dts/broadcom/bcm4709-asus-rt-ac87u.dts | 40 +++++++++++++++++++ + 1 file changed, 40 insertions(+) + +--- a/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts ++++ b/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts +@@ -26,6 +26,9 @@ + }; + + nvram@1c080000 { ++ compatible = "brcm,nvram"; ++ reg = <0x1c080000 0x180000>; ++ + et1macaddr: et1macaddr { + #nvmem-cell-cells = <1>; + }; +@@ -77,6 +80,43 @@ + status = "okay"; + }; + ++&srab { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ label = "wan"; ++ ++ nvmem-cells = <&et1macaddr 1>; ++ nvmem-cell-names = "mac-address"; ++ }; ++ ++ port@1 { ++ label = "lan1"; ++ }; ++ ++ port@2 { ++ label = "lan2"; ++ }; ++ ++ port@3 { ++ label = "lan3"; ++ }; ++ ++ port@5 { ++ status = "disabled"; ++ }; ++ ++ port@7 { ++ label = "cpu"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; ++ }; ++}; ++ + &nandcs { + partitions { + compatible = "fixed-partitions"; diff --git a/target/linux/bcm53xx/patches-6.18/314-ARM-dts-BCM5301X-EA6300-specify-switch.patch b/target/linux/bcm53xx/patches-6.18/314-ARM-dts-BCM5301X-EA6300-specify-switch.patch new file mode 100644 index 0000000000..259cd312ab --- /dev/null +++ b/target/linux/bcm53xx/patches-6.18/314-ARM-dts-BCM5301X-EA6300-specify-switch.patch @@ -0,0 +1,71 @@ +From c4c21947b9a641131afe07d6c5f1abd3ff6b8bb0 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Tue, 17 Feb 2026 21:05:09 -0800 +Subject: [PATCH] ARM: dts: BCM5301X: EA6300: specify switch + +bcm-ns.dtsi specifies a default layout that is not correct for the +EA6300. Also allows setting the WAN MAC address properly. + +Signed-off-by: Rosen Penev +--- + .../broadcom/bcm4708-linksys-ea6300-v1.dts | 45 +++++++++++++++++++ + 1 file changed, 45 insertions(+) + +--- a/arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6300-v1.dts ++++ b/arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6300-v1.dts +@@ -24,6 +24,10 @@ + nvram@1c080000 { + compatible = "brcm,nvram"; + reg = <0x1c080000 0x180000>; ++ ++ et0macaddr: et0macaddr { ++ #nvmem-cell-cells = <1>; ++ }; + }; + + gpio-keys { +@@ -46,3 +50,44 @@ + &usb3_phy { + status = "okay"; + }; ++ ++&srab { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ label = "lan1"; ++ }; ++ ++ port@1 { ++ label = "lan2"; ++ }; ++ ++ port@2 { ++ label = "lan3"; ++ }; ++ ++ port@3 { ++ label = "lan4"; ++ }; ++ ++ port@4 { ++ label = "wan"; ++ ++ nvmem-cells = <&et0macaddr 1>; ++ nvmem-cell-names = "mac-address"; ++ }; ++ ++ port@5 { ++ label = "cpu"; ++ }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; ++ }; ++}; diff --git a/target/linux/bcm53xx/patches-6.18/315-ARM-dts-BCM5301X-phicomm-k3-specify-switch.patch b/target/linux/bcm53xx/patches-6.18/315-ARM-dts-BCM5301X-phicomm-k3-specify-switch.patch new file mode 100644 index 0000000000..84aa912e11 --- /dev/null +++ b/target/linux/bcm53xx/patches-6.18/315-ARM-dts-BCM5301X-phicomm-k3-specify-switch.patch @@ -0,0 +1,75 @@ +From 22785d47e3a5a8e5321586a9776a70a5e88148a2 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Tue, 17 Feb 2026 21:13:49 -0800 +Subject: [PATCH] ARM: dts: BCM5301X: phicomm-k3: specify switch + +bcm-ns.dtsi specifies a default layout that is not correct for the +K3. Also allows setting the WAN MAC address properly. + +Signed-off-by: Rosen Penev +--- + .../boot/dts/broadcom/bcm47094-phicomm-k3.dts | 46 +++++++++++++++++++ + 1 file changed, 46 insertions(+) + +--- a/arch/arm/boot/dts/broadcom/bcm47094-phicomm-k3.dts ++++ b/arch/arm/boot/dts/broadcom/bcm47094-phicomm-k3.dts +@@ -19,6 +19,15 @@ + <0x88000000 0x18000000>; + }; + ++ nvram@1c080000 { ++ compatible = "brcm,nvram"; ++ reg = <0x1c080000 0x100000>; ++ ++ et0macaddr: et0macaddr { ++ #nvmem-cell-cells = <1>; ++ }; ++ }; ++ + gpio-keys { + compatible = "gpio-keys"; + +@@ -38,6 +47,43 @@ + status = "okay"; + }; + ++&srab { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ label = "lan1"; ++ }; ++ ++ port@1 { ++ label = "lan2"; ++ }; ++ ++ port@2 { ++ label = "lan3"; ++ }; ++ ++ port@3 { ++ label = "wan"; ++ ++ nvmem-cells = <&et0macaddr 1>; ++ nvmem-cell-names = "mac-address"; ++ }; ++ ++ port@5 { ++ label = "cpu"; ++ }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; ++ }; ++}; ++ + &nandcs { + partitions { + compatible = "fixed-partitions"; diff --git a/target/linux/bcm53xx/patches-6.18/331-v7.2-ARM-dts-NSP-Move-MX6X-pinctrl-config-to-PWM-node.patch b/target/linux/bcm53xx/patches-6.18/331-v7.2-ARM-dts-NSP-Move-MX6X-pinctrl-config-to-PWM-node.patch new file mode 100644 index 0000000000..49da9fa9dd --- /dev/null +++ b/target/linux/bcm53xx/patches-6.18/331-v7.2-ARM-dts-NSP-Move-MX6X-pinctrl-config-to-PWM-node.patch @@ -0,0 +1,41 @@ +From d7b3f4a4eb23d82ef923cf17509292b719340378 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Wed, 29 Apr 2026 22:16:12 -0700 +Subject: [PATCH] ARM: dts: NSP: Move MX6X pinctrl config to PWM node + +On boot there is this warning: + +/axi@18000000/pinctrl@3f1c0: Fixed dependency cycle(s) with /axi@18000000/pinctrl@3f1c0/pwm_leds + +Fix by moving the pinctrl configuration to pwm, which is the actual +consumer. + +Signed-off-by: Rosen Penev +Link: https://lore.kernel.org/r/20260430051612.700050-1-rosenp@gmail.com +Signed-off-by: Florian Fainelli +--- + .../arm/boot/dts/broadcom/bcm958625-meraki-mx6x-common.dtsi | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/arch/arm/boot/dts/broadcom/bcm958625-meraki-mx6x-common.dtsi ++++ b/arch/arm/boot/dts/broadcom/bcm958625-meraki-mx6x-common.dtsi +@@ -121,9 +121,6 @@ + }; + + &pinctrl { +- pinctrl-names = "default"; +- pinctrl-0 = <&pwm_leds>; +- + pwm_leds: pwm_leds { + function = "pwm"; + groups = "pwm1_grp", "pwm2_grp", "pwm3_grp"; +@@ -131,6 +128,9 @@ + }; + + &pwm { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwm_leds>; ++ + status = "okay"; + }; + diff --git a/target/linux/d1/config-6.18 b/target/linux/d1/config-6.18 index ab1a8b3e4d..fd6e6b0fe8 100644 --- a/target/linux/d1/config-6.18 +++ b/target/linux/d1/config-6.18 @@ -119,6 +119,7 @@ CONFIG_ERRATA_THEAD_MAE=y CONFIG_EXCLUSIVE_SYSTEM_RAM=y CONFIG_EXT4_FS=y CONFIG_EXTCON=y +CONFIG_F2FS_FS=y CONFIG_FAILOVER=y CONFIG_FHANDLE=y CONFIG_FIXED_PHY=y @@ -128,7 +129,6 @@ CONFIG_FONT_AUTOSELECT=y CONFIG_FONT_SUPPORT=y CONFIG_FPU=y CONFIG_FRAME_POINTER=y -CONFIG_F2FS_FS=y CONFIG_FS_IOMAP=y CONFIG_FS_MBCACHE=y CONFIG_FUNCTION_ALIGNMENT=0 diff --git a/target/linux/econet/Makefile b/target/linux/econet/Makefile index c0318ef85d..a895827ef9 100644 --- a/target/linux/econet/Makefile +++ b/target/linux/econet/Makefile @@ -9,7 +9,7 @@ BOARDNAME:=EcoNet EN75xx MIPS FEATURES:=dt source-only squashfs nand usb SUBTARGETS:=en751221 en751627 en7528 -KERNEL_PATCHVER:=6.12 +KERNEL_PATCHVER:=6.18 define Target/Description Build firmware image for EcoNet EN75xx MIPS based boards. diff --git a/target/linux/econet/en751221/config-6.12 b/target/linux/econet/en751221/config-6.18 similarity index 97% rename from target/linux/econet/en751221/config-6.12 rename to target/linux/econet/en751221/config-6.18 index fe69f10c74..523f5454dd 100644 --- a/target/linux/econet/en751221/config-6.12 +++ b/target/linux/econet/en751221/config-6.18 @@ -2,7 +2,6 @@ CONFIG_ARCH_32BIT_OFF_T=y CONFIG_ARCH_KEEP_MEMBLOCK=y CONFIG_ARCH_MMAP_RND_BITS_MAX=15 CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 -CONFIG_BLK_MQ_PCI=y CONFIG_CLKSRC_MMIO=y CONFIG_CLONE_BACKWARDS=y CONFIG_COMMON_CLK=y @@ -32,7 +31,6 @@ CONFIG_CRC16=y CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_ECB=y CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y CONFIG_CRYPTO_LIB_GF128MUL=y CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 CONFIG_CRYPTO_LIB_UTILS=y @@ -61,7 +59,6 @@ CONFIG_GENERIC_CMOS_UPDATE=y CONFIG_GENERIC_CPU_AUTOPROBE=y CONFIG_GENERIC_GETTIMEOFDAY=y CONFIG_GENERIC_IDLE_POLL_SETUP=y -CONFIG_GENERIC_IOMAP=y CONFIG_GENERIC_IRQ_CHIP=y CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y CONFIG_GENERIC_IRQ_SHOW=y @@ -90,8 +87,8 @@ CONFIG_IRQ_DOMAIN=y CONFIG_IRQ_DOMAIN_HIERARCHY=y CONFIG_IRQ_FORCED_THREADING=y CONFIG_IRQ_MIPS_CPU=y +CONFIG_IRQ_MSI_LIB=y CONFIG_IRQ_WORK=y -CONFIG_JFFS2_FS=y CONFIG_JFFS2_ZLIB=y CONFIG_LIBFDT=y CONFIG_LOCK_DEBUGGING_SUPPORT=y @@ -136,6 +133,7 @@ CONFIG_OF_GPIO=y CONFIG_OF_IRQ=y CONFIG_OF_KOBJ=y CONFIG_PADATA=y +CONFIG_PAGE_BLOCK_MAX_ORDER=11 CONFIG_PAGE_POOL=y CONFIG_PAGE_SIZE_LESS_THAN_256KB=y CONFIG_PAGE_SIZE_LESS_THAN_64KB=y @@ -152,6 +150,7 @@ CONFIG_PCI_MSI_ARCH_FALLBACKS=y CONFIG_PERF_USE_VMALLOC=y CONFIG_PGTABLE_LEVELS=2 CONFIG_PHY_EN7528_PCIE=y +# CONFIG_PHY_EN7528_USB is not set CONFIG_PTP_1588_CLOCK_OPTIONAL=y CONFIG_QUEUED_RWLOCKS=y CONFIG_QUEUED_SPINLOCKS=y @@ -166,7 +165,6 @@ CONFIG_RPS=y # CONFIG_SERIAL_8250_AIROHA is not set CONFIG_SERIAL_MCTRL_GPIO=y CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_SGL_ALLOC=y CONFIG_SMP=y CONFIG_SMP_UP=y CONFIG_SOCK_RX_QUEUE_MAPPING=y diff --git a/target/linux/econet/en751627/config-6.12 b/target/linux/econet/en751627/config-6.18 similarity index 97% rename from target/linux/econet/en751627/config-6.12 rename to target/linux/econet/en751627/config-6.18 index 5e7b280d72..a078662c73 100644 --- a/target/linux/econet/en751627/config-6.12 +++ b/target/linux/econet/en751627/config-6.18 @@ -4,7 +4,6 @@ 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_BLK_MQ_PCI=y CONFIG_BOARD_SCACHE=y CONFIG_CLKSRC_MMIO=y CONFIG_CLONE_BACKWARDS=y @@ -37,10 +36,8 @@ CONFIG_CRC16=y CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_ECB=y CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y CONFIG_CRYPTO_LIB_GF128MUL=y CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 -CONFIG_CRYPTO_LIB_SHA1=y CONFIG_CRYPTO_LIB_UTILS=y CONFIG_CRYPTO_LZO=y CONFIG_CRYPTO_ZSTD=y @@ -66,7 +63,6 @@ CONFIG_GENERIC_CMOS_UPDATE=y CONFIG_GENERIC_CPU_AUTOPROBE=y CONFIG_GENERIC_GETTIMEOFDAY=y CONFIG_GENERIC_IDLE_POLL_SETUP=y -CONFIG_GENERIC_IOMAP=y CONFIG_GENERIC_IRQ_CHIP=y CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y CONFIG_GENERIC_IRQ_SHOW=y @@ -97,6 +93,7 @@ CONFIG_IRQ_DOMAIN=y CONFIG_IRQ_DOMAIN_HIERARCHY=y CONFIG_IRQ_FORCED_THREADING=y CONFIG_IRQ_MIPS_CPU=y +CONFIG_IRQ_MSI_LIB=y CONFIG_IRQ_WORK=y # CONFIG_JFFS2_FS is not set CONFIG_LEDS_GPIO=y @@ -155,6 +152,7 @@ CONFIG_OF_GPIO=y CONFIG_OF_IRQ=y CONFIG_OF_KOBJ=y CONFIG_PADATA=y +CONFIG_PAGE_BLOCK_MAX_ORDER=11 CONFIG_PAGE_POOL=y CONFIG_PAGE_SIZE_LESS_THAN_256KB=y CONFIG_PAGE_SIZE_LESS_THAN_64KB=y @@ -168,6 +166,7 @@ CONFIG_PCI_MSI_ARCH_FALLBACKS=y CONFIG_PERF_USE_VMALLOC=y CONFIG_PGTABLE_LEVELS=2 CONFIG_PHY_EN7528_PCIE=y +# CONFIG_PHY_EN7528_USB is not set CONFIG_PTP_1588_CLOCK_OPTIONAL=y CONFIG_QUEUED_RWLOCKS=y CONFIG_QUEUED_SPINLOCKS=y @@ -183,7 +182,6 @@ CONFIG_SCHED_SMT=y CONFIG_SERIAL_8250_AIROHA=y CONFIG_SERIAL_MCTRL_GPIO=y CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_SGL_ALLOC=y CONFIG_SMP=y CONFIG_SMP_UP=y CONFIG_SOCK_RX_QUEUE_MAPPING=y @@ -209,7 +207,6 @@ CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y CONFIG_SYS_SUPPORTS_MIPS16=y CONFIG_SYS_SUPPORTS_MIPS_CPS=y CONFIG_SYS_SUPPORTS_MULTITHREADING=y -CONFIG_SYS_SUPPORTS_SCHED_SMT=y CONFIG_SYS_SUPPORTS_SMP=y CONFIG_SYS_SUPPORTS_ZBOOT=y CONFIG_SYS_SUPPORTS_ZBOOT_UART16550=y diff --git a/target/linux/econet/en7528/config-6.12 b/target/linux/econet/en7528/config-6.18 similarity index 97% rename from target/linux/econet/en7528/config-6.12 rename to target/linux/econet/en7528/config-6.18 index f577834028..cef1186274 100644 --- a/target/linux/econet/en7528/config-6.12 +++ b/target/linux/econet/en7528/config-6.18 @@ -4,7 +4,6 @@ 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_BLK_MQ_PCI=y CONFIG_BOARD_SCACHE=y CONFIG_CLKSRC_MMIO=y CONFIG_CLONE_BACKWARDS=y @@ -37,7 +36,6 @@ CONFIG_CRC16=y CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_ECB=y CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y CONFIG_CRYPTO_LIB_GF128MUL=y CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 CONFIG_CRYPTO_LIB_UTILS=y @@ -65,7 +63,6 @@ CONFIG_GENERIC_CMOS_UPDATE=y CONFIG_GENERIC_CPU_AUTOPROBE=y CONFIG_GENERIC_GETTIMEOFDAY=y CONFIG_GENERIC_IDLE_POLL_SETUP=y -CONFIG_GENERIC_IOMAP=y CONFIG_GENERIC_IRQ_CHIP=y CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y CONFIG_GENERIC_IRQ_SHOW=y @@ -96,6 +93,7 @@ CONFIG_IRQ_DOMAIN=y CONFIG_IRQ_DOMAIN_HIERARCHY=y CONFIG_IRQ_FORCED_THREADING=y CONFIG_IRQ_MIPS_CPU=y +CONFIG_IRQ_MSI_LIB=y CONFIG_IRQ_WORK=y # CONFIG_JFFS2_FS is not set CONFIG_LEDS_GPIO=y @@ -154,6 +152,7 @@ CONFIG_OF_GPIO=y CONFIG_OF_IRQ=y CONFIG_OF_KOBJ=y CONFIG_PADATA=y +CONFIG_PAGE_BLOCK_MAX_ORDER=11 CONFIG_PAGE_POOL=y CONFIG_PAGE_SIZE_LESS_THAN_256KB=y CONFIG_PAGE_SIZE_LESS_THAN_64KB=y @@ -185,7 +184,6 @@ CONFIG_SCHED_SMT=y CONFIG_SERIAL_8250_AIROHA=y CONFIG_SERIAL_MCTRL_GPIO=y CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_SGL_ALLOC=y CONFIG_SMP=y CONFIG_SMP_UP=y CONFIG_SOCK_RX_QUEUE_MAPPING=y @@ -211,7 +209,6 @@ CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y CONFIG_SYS_SUPPORTS_MIPS16=y CONFIG_SYS_SUPPORTS_MIPS_CPS=y CONFIG_SYS_SUPPORTS_MULTITHREADING=y -CONFIG_SYS_SUPPORTS_SCHED_SMT=y CONFIG_SYS_SUPPORTS_SMP=y CONFIG_SYS_SUPPORTS_ZBOOT=y CONFIG_SYS_SUPPORTS_ZBOOT_UART16550=y diff --git a/target/linux/econet/patches-6.12/001-v6.16-dt-bindings-interrupt-controller-Add-EcoNet-EN751221.patch b/target/linux/econet/patches-6.12/001-v6.16-dt-bindings-interrupt-controller-Add-EcoNet-EN751221.patch deleted file mode 100644 index c146af679a..0000000000 --- a/target/linux/econet/patches-6.12/001-v6.16-dt-bindings-interrupt-controller-Add-EcoNet-EN751221.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 9773c540441c6ae15aefb49e67142e94369dbbc0 Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Sun, 30 Mar 2025 17:02:58 +0000 -Subject: [PATCH] dt-bindings: interrupt-controller: Add EcoNet EN751221 INTC - -Document the device tree binding for the interrupt controller in the -EcoNet EN751221 MIPS SoC. - -Signed-off-by: Caleb James DeLisle -Signed-off-by: Thomas Gleixner -Reviewed-by: Rob Herring (Arm) -Link: https://lore.kernel.org/all/20250330170306.2584136-3-cjd@cjdns.fr ---- - .../econet,en751221-intc.yaml | 78 +++++++++++++++++++ - 1 file changed, 78 insertions(+) - create mode 100644 Documentation/devicetree/bindings/interrupt-controller/econet,en751221-intc.yaml - ---- /dev/null -+++ b/Documentation/devicetree/bindings/interrupt-controller/econet,en751221-intc.yaml -@@ -0,0 +1,78 @@ -+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/interrupt-controller/econet,en751221-intc.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: EcoNet EN751221 Interrupt Controller -+ -+maintainers: -+ - Caleb James DeLisle -+ -+description: -+ The EcoNet EN751221 Interrupt Controller is a simple interrupt controller -+ designed for the MIPS 34Kc MT SMP processor with 2 VPEs. Each interrupt can -+ be routed to either VPE but not both, so to support per-CPU interrupts, a -+ secondary IRQ number is allocated to control masking/unmasking on VPE#1. For -+ lack of a better term we call these "shadow interrupts". The assignment of -+ shadow interrupts is defined by the SoC integrator when wiring the interrupt -+ lines, so they are configurable in the device tree. -+ -+allOf: -+ - $ref: /schemas/interrupt-controller.yaml# -+ -+properties: -+ compatible: -+ const: econet,en751221-intc -+ -+ reg: -+ maxItems: 1 -+ -+ "#interrupt-cells": -+ const: 1 -+ -+ interrupt-controller: true -+ -+ interrupts: -+ maxItems: 1 -+ description: Interrupt line connecting this controller to its parent. -+ -+ econet,shadow-interrupts: -+ $ref: /schemas/types.yaml#/definitions/uint32-matrix -+ description: -+ An array of interrupt number pairs where each pair represents a shadow -+ interrupt relationship. The first number in each pair is the primary IRQ, -+ and the second is its shadow IRQ used for VPE#1 control. For example, -+ <8 3> means IRQ 8 is shadowed by IRQ 3, so IRQ 3 cannot be mapped, but -+ when VPE#1 requests IRQ 8, it will manipulate the IRQ 3 mask bit. -+ minItems: 1 -+ maxItems: 20 -+ items: -+ items: -+ - description: primary per-CPU IRQ -+ - description: shadow IRQ number -+ -+required: -+ - compatible -+ - reg -+ - interrupt-controller -+ - "#interrupt-cells" -+ - interrupts -+ -+additionalProperties: false -+ -+examples: -+ - | -+ interrupt-controller@1fb40000 { -+ compatible = "econet,en751221-intc"; -+ reg = <0x1fb40000 0x100>; -+ -+ interrupt-controller; -+ #interrupt-cells = <1>; -+ -+ interrupt-parent = <&cpuintc>; -+ interrupts = <2>; -+ -+ econet,shadow-interrupts = <7 2>, <8 3>, <13 12>, <30 29>; -+ }; -+... diff --git a/target/linux/econet/patches-6.12/002-v6.16-irqchip-Add-EcoNet-EN751221-INTC.patch b/target/linux/econet/patches-6.12/002-v6.16-irqchip-Add-EcoNet-EN751221-INTC.patch deleted file mode 100644 index d3f57f4e7f..0000000000 --- a/target/linux/econet/patches-6.12/002-v6.16-irqchip-Add-EcoNet-EN751221-INTC.patch +++ /dev/null @@ -1,353 +0,0 @@ -From 1902a59cf5f9d8b99ecf0cb8f122cb00ef7a3f13 Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Sun, 30 Mar 2025 17:02:59 +0000 -Subject: [PATCH] irqchip: Add EcoNet EN751221 INTC - -Add a driver for the interrupt controller in the EcoNet EN751221 MIPS SoC. - -Signed-off-by: Caleb James DeLisle -Signed-off-by: Thomas Gleixner -Link: https://lore.kernel.org/all/20250330170306.2584136-4-cjd@cjdns.fr ---- - drivers/irqchip/Kconfig | 5 + - drivers/irqchip/Makefile | 1 + - drivers/irqchip/irq-econet-en751221.c | 309 ++++++++++++++++++++++++++ - 3 files changed, 315 insertions(+) - create mode 100644 drivers/irqchip/irq-econet-en751221.c - ---- a/drivers/irqchip/Kconfig -+++ b/drivers/irqchip/Kconfig -@@ -148,6 +148,11 @@ config DW_APB_ICTL - select GENERIC_IRQ_CHIP - select IRQ_DOMAIN_HIERARCHY - -+config ECONET_EN751221_INTC -+ bool -+ select GENERIC_IRQ_CHIP -+ select IRQ_DOMAIN -+ - config FARADAY_FTINTC010 - bool - select IRQ_DOMAIN ---- a/drivers/irqchip/Makefile -+++ b/drivers/irqchip/Makefile -@@ -10,6 +10,7 @@ obj-$(CONFIG_ARCH_BCM2835) += irq-bcm28 - obj-$(CONFIG_ARCH_ACTIONS) += irq-owl-sirq.o - obj-$(CONFIG_DAVINCI_CP_INTC) += irq-davinci-cp-intc.o - obj-$(CONFIG_EXYNOS_IRQ_COMBINER) += exynos-combiner.o -+obj-$(CONFIG_ECONET_EN751221_INTC) += irq-econet-en751221.o - obj-$(CONFIG_FARADAY_FTINTC010) += irq-ftintc010.o - obj-$(CONFIG_ARCH_HIP04) += irq-hip04.o - obj-$(CONFIG_ARCH_LPC32XX) += irq-lpc32xx.o ---- /dev/null -+++ b/drivers/irqchip/irq-econet-en751221.c -@@ -0,0 +1,309 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * EN751221 Interrupt Controller Driver. -+ * -+ * The EcoNet EN751221 Interrupt Controller is a simple interrupt controller -+ * designed for the MIPS 34Kc MT SMP processor with 2 VPEs. Each interrupt can -+ * be routed to either VPE but not both, so to support per-CPU interrupts, a -+ * secondary IRQ number is allocated to control masking/unmasking on VPE#1. In -+ * this driver, these are called "shadow interrupts". The assignment of shadow -+ * interrupts is defined by the SoC integrator when wiring the interrupt lines, -+ * so they are configurable in the device tree. -+ * -+ * If an interrupt (say 30) needs per-CPU capability, the SoC integrator -+ * allocates another IRQ number (say 29) to be its shadow. The device tree -+ * reflects this by adding the pair <30 29> to the "econet,shadow-interrupts" -+ * property. -+ * -+ * When VPE#1 requests IRQ 30, the driver manipulates the mask bit for IRQ 29, -+ * telling the hardware to mask VPE#1's view of IRQ 30. -+ * -+ * Copyright (C) 2025 Caleb James DeLisle -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define IRQ_COUNT 40 -+ -+#define NOT_PERCPU 0xff -+#define IS_SHADOW 0xfe -+ -+#define REG_MASK0 0x04 -+#define REG_MASK1 0x50 -+#define REG_PENDING0 0x08 -+#define REG_PENDING1 0x54 -+ -+/** -+ * @membase: Base address of the interrupt controller registers -+ * @interrupt_shadows: Array of all interrupts, for each value, -+ * - NOT_PERCPU: This interrupt is not per-cpu, so it has no shadow -+ * - IS_SHADOW: This interrupt is a shadow of another per-cpu interrupt -+ * - else: This is a per-cpu interrupt whose shadow is the value -+ */ -+static struct { -+ void __iomem *membase; -+ u8 interrupt_shadows[IRQ_COUNT]; -+} econet_intc __ro_after_init; -+ -+static DEFINE_RAW_SPINLOCK(irq_lock); -+ -+/* IRQs must be disabled */ -+static void econet_wreg(u32 reg, u32 val, u32 mask) -+{ -+ u32 v; -+ -+ guard(raw_spinlock)(&irq_lock); -+ -+ v = ioread32(econet_intc.membase + reg); -+ v &= ~mask; -+ v |= val & mask; -+ iowrite32(v, econet_intc.membase + reg); -+} -+ -+/* IRQs must be disabled */ -+static void econet_chmask(u32 hwirq, bool unmask) -+{ -+ u32 reg, mask; -+ u8 shadow; -+ -+ /* -+ * If the IRQ is a shadow, it should never be manipulated directly. -+ * It should only be masked/unmasked as a result of the "real" per-cpu -+ * irq being manipulated by a thread running on VPE#1. -+ * If it is per-cpu (has a shadow), and we're on VPE#1, the shadow is what we mask. -+ * This is single processor only, so smp_processor_id() never exceeds 1. -+ */ -+ shadow = econet_intc.interrupt_shadows[hwirq]; -+ if (WARN_ON_ONCE(shadow == IS_SHADOW)) -+ return; -+ else if (shadow != NOT_PERCPU && smp_processor_id() == 1) -+ hwirq = shadow; -+ -+ if (hwirq >= 32) { -+ reg = REG_MASK1; -+ mask = BIT(hwirq - 32); -+ } else { -+ reg = REG_MASK0; -+ mask = BIT(hwirq); -+ } -+ -+ econet_wreg(reg, unmask ? mask : 0, mask); -+} -+ -+/* IRQs must be disabled */ -+static void econet_intc_mask(struct irq_data *d) -+{ -+ econet_chmask(d->hwirq, false); -+} -+ -+/* IRQs must be disabled */ -+static void econet_intc_unmask(struct irq_data *d) -+{ -+ econet_chmask(d->hwirq, true); -+} -+ -+static void econet_mask_all(void) -+{ -+ /* IRQs are generally disabled during init, but guarding here makes it non-obligatory. */ -+ guard(irqsave)(); -+ econet_wreg(REG_MASK0, 0, ~0); -+ econet_wreg(REG_MASK1, 0, ~0); -+} -+ -+static void econet_intc_handle_pending(struct irq_domain *d, u32 pending, u32 offset) -+{ -+ int hwirq; -+ -+ while (pending) { -+ hwirq = fls(pending) - 1; -+ generic_handle_domain_irq(d, hwirq + offset); -+ pending &= ~BIT(hwirq); -+ } -+} -+ -+static void econet_intc_from_parent(struct irq_desc *desc) -+{ -+ struct irq_chip *chip = irq_desc_get_chip(desc); -+ struct irq_domain *domain; -+ u32 pending0, pending1; -+ -+ chained_irq_enter(chip, desc); -+ -+ pending0 = ioread32(econet_intc.membase + REG_PENDING0); -+ pending1 = ioread32(econet_intc.membase + REG_PENDING1); -+ -+ if (unlikely(!(pending0 | pending1))) { -+ spurious_interrupt(); -+ } else { -+ domain = irq_desc_get_handler_data(desc); -+ econet_intc_handle_pending(domain, pending0, 0); -+ econet_intc_handle_pending(domain, pending1, 32); -+ } -+ -+ chained_irq_exit(chip, desc); -+} -+ -+static const struct irq_chip econet_irq_chip; -+ -+static int econet_intc_map(struct irq_domain *d, u32 irq, irq_hw_number_t hwirq) -+{ -+ int ret; -+ -+ if (hwirq >= IRQ_COUNT) { -+ pr_err("%s: hwirq %lu out of range\n", __func__, hwirq); -+ return -EINVAL; -+ } else if (econet_intc.interrupt_shadows[hwirq] == IS_SHADOW) { -+ pr_err("%s: can't map hwirq %lu, it is a shadow interrupt\n", __func__, hwirq); -+ return -EINVAL; -+ } -+ -+ if (econet_intc.interrupt_shadows[hwirq] == NOT_PERCPU) { -+ irq_set_chip_and_handler(irq, &econet_irq_chip, handle_level_irq); -+ } else { -+ irq_set_chip_and_handler(irq, &econet_irq_chip, handle_percpu_devid_irq); -+ ret = irq_set_percpu_devid(irq); -+ if (ret) -+ pr_warn("%s: Failed irq_set_percpu_devid for %u: %d\n", d->name, irq, ret); -+ } -+ -+ irq_set_chip_data(irq, NULL); -+ return 0; -+} -+ -+static const struct irq_chip econet_irq_chip = { -+ .name = "en751221-intc", -+ .irq_unmask = econet_intc_unmask, -+ .irq_mask = econet_intc_mask, -+ .irq_mask_ack = econet_intc_mask, -+}; -+ -+static const struct irq_domain_ops econet_domain_ops = { -+ .xlate = irq_domain_xlate_onecell, -+ .map = econet_intc_map -+}; -+ -+static int __init get_shadow_interrupts(struct device_node *node) -+{ -+ const char *field = "econet,shadow-interrupts"; -+ int num_shadows; -+ -+ num_shadows = of_property_count_u32_elems(node, field); -+ -+ memset(econet_intc.interrupt_shadows, NOT_PERCPU, -+ sizeof(econet_intc.interrupt_shadows)); -+ -+ if (num_shadows <= 0) { -+ return 0; -+ } else if (num_shadows % 2) { -+ pr_err("%pOF: %s count is odd, ignoring\n", node, field); -+ return 0; -+ } -+ -+ u32 *shadows __free(kfree) = kmalloc_array(num_shadows, sizeof(u32), GFP_KERNEL); -+ if (!shadows) -+ return -ENOMEM; -+ -+ if (of_property_read_u32_array(node, field, shadows, num_shadows)) { -+ pr_err("%pOF: Failed to read %s\n", node, field); -+ return -EINVAL; -+ } -+ -+ for (int i = 0; i < num_shadows; i += 2) { -+ u32 shadow = shadows[i + 1]; -+ u32 target = shadows[i]; -+ -+ if (shadow > IRQ_COUNT) { -+ pr_err("%pOF: %s[%d] shadow(%d) out of range\n", -+ node, field, i + 1, shadow); -+ continue; -+ } -+ -+ if (target >= IRQ_COUNT) { -+ pr_err("%pOF: %s[%d] target(%d) out of range\n", node, field, i, target); -+ continue; -+ } -+ -+ if (econet_intc.interrupt_shadows[target] != NOT_PERCPU) { -+ pr_err("%pOF: %s[%d] target(%d) already has a shadow\n", -+ node, field, i, target); -+ continue; -+ } -+ -+ if (econet_intc.interrupt_shadows[shadow] != NOT_PERCPU) { -+ pr_err("%pOF: %s[%d] shadow(%d) already has a target\n", -+ node, field, i + 1, shadow); -+ continue; -+ } -+ -+ econet_intc.interrupt_shadows[target] = shadow; -+ econet_intc.interrupt_shadows[shadow] = IS_SHADOW; -+ } -+ -+ return 0; -+} -+ -+static int __init econet_intc_of_init(struct device_node *node, struct device_node *parent) -+{ -+ struct irq_domain *domain; -+ struct resource res; -+ int ret, irq; -+ -+ ret = get_shadow_interrupts(node); -+ if (ret) -+ return ret; -+ -+ irq = irq_of_parse_and_map(node, 0); -+ if (!irq) { -+ pr_err("%pOF: DT: Failed to get IRQ from 'interrupts'\n", node); -+ return -EINVAL; -+ } -+ -+ if (of_address_to_resource(node, 0, &res)) { -+ pr_err("%pOF: DT: Failed to get 'reg'\n", node); -+ ret = -EINVAL; -+ goto err_dispose_mapping; -+ } -+ -+ if (!request_mem_region(res.start, resource_size(&res), res.name)) { -+ pr_err("%pOF: Failed to request memory\n", node); -+ ret = -EBUSY; -+ goto err_dispose_mapping; -+ } -+ -+ econet_intc.membase = ioremap(res.start, resource_size(&res)); -+ if (!econet_intc.membase) { -+ pr_err("%pOF: Failed to remap membase\n", node); -+ ret = -ENOMEM; -+ goto err_release; -+ } -+ -+ econet_mask_all(); -+ -+ domain = irq_domain_add_linear(node, IRQ_COUNT, &econet_domain_ops, NULL); -+ if (!domain) { -+ pr_err("%pOF: Failed to add irqdomain\n", node); -+ ret = -ENOMEM; -+ goto err_unmap; -+ } -+ -+ irq_set_chained_handler_and_data(irq, econet_intc_from_parent, domain); -+ -+ return 0; -+ -+err_unmap: -+ iounmap(econet_intc.membase); -+err_release: -+ release_mem_region(res.start, resource_size(&res)); -+err_dispose_mapping: -+ irq_dispose_mapping(irq); -+ return ret; -+} -+ -+IRQCHIP_DECLARE(econet_en751221_intc, "econet,en751221-intc", econet_intc_of_init); diff --git a/target/linux/econet/patches-6.12/003-v6.16-dt-bindings-vendor-prefixes-Add-EcoNet.patch b/target/linux/econet/patches-6.12/003-v6.16-dt-bindings-vendor-prefixes-Add-EcoNet.patch deleted file mode 100644 index e2466782d1..0000000000 --- a/target/linux/econet/patches-6.12/003-v6.16-dt-bindings-vendor-prefixes-Add-EcoNet.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 9e0dd98654a528735d2b363d0dc73f7904108652 Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Sun, 30 Mar 2025 17:02:57 +0000 -Subject: [PATCH] dt-bindings: vendor-prefixes: Add EcoNet - -Add the "econet" vendor prefix for SoC maker - -Signed-off-by: Caleb James DeLisle -Acked-by: Krzysztof Kozlowski -Link: https://lore.kernel.org/r/20250330170306.2584136-2-cjd@cjdns.fr -Signed-off-by: Rob Herring (Arm) ---- - Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/Documentation/devicetree/bindings/vendor-prefixes.yaml -+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml -@@ -420,6 +420,8 @@ patternProperties: - description: EBV Elektronik - "^eckelmann,.*": - description: Eckelmann AG -+ "^econet,.*": -+ description: EcoNet (HK) Limited - "^edgeble,.*": - description: Edgeble AI Technologies Pvt. Ltd. - "^edimax,.*": diff --git a/target/linux/econet/patches-6.12/004-v6.16-dt-bindings-timer-Add-EcoNet-EN751221-HPT-CPU-Timer.patch b/target/linux/econet/patches-6.12/004-v6.16-dt-bindings-timer-Add-EcoNet-EN751221-HPT-CPU-Timer.patch deleted file mode 100644 index 92f8604ea2..0000000000 --- a/target/linux/econet/patches-6.12/004-v6.16-dt-bindings-timer-Add-EcoNet-EN751221-HPT-CPU-Timer.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 30fddbd5325459102e448c9a26a1bc15ef563381 Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Wed, 7 May 2025 13:44:54 +0000 -Subject: [PATCH] dt-bindings: timer: Add EcoNet EN751221 "HPT" CPU Timer - -Add device tree bindings for the so-called high-precision timer (HPT) -in the EcoNet EN751221 SoC. - -Signed-off-by: Caleb James DeLisle -Reviewed-by: Krzysztof Kozlowski -Link: https://lore.kernel.org/r/20250507134500.390547-2-cjd@cjdns.fr -Signed-off-by: Daniel Lezcano ---- - .../bindings/timer/econet,en751221-timer.yaml | 80 +++++++++++++++++++ - 1 file changed, 80 insertions(+) - create mode 100644 Documentation/devicetree/bindings/timer/econet,en751221-timer.yaml - ---- /dev/null -+++ b/Documentation/devicetree/bindings/timer/econet,en751221-timer.yaml -@@ -0,0 +1,80 @@ -+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/timer/econet,en751221-timer.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: EcoNet EN751221 High Precision Timer (HPT) -+ -+maintainers: -+ - Caleb James DeLisle -+ -+description: -+ The EcoNet High Precision Timer (HPT) is a timer peripheral found in various -+ EcoNet SoCs, including the EN751221 and EN751627 families. It provides per-VPE -+ count/compare registers and a per-CPU control register, with a single interrupt -+ line using a percpu-devid interrupt mechanism. -+ -+properties: -+ compatible: -+ oneOf: -+ - const: econet,en751221-timer -+ - items: -+ - const: econet,en751627-timer -+ - const: econet,en751221-timer -+ -+ reg: -+ minItems: 1 -+ maxItems: 2 -+ -+ interrupts: -+ maxItems: 1 -+ description: A percpu-devid timer interrupt shared across CPUs. -+ -+ clocks: -+ maxItems: 1 -+ -+required: -+ - compatible -+ - reg -+ - interrupts -+ - clocks -+ -+allOf: -+ - if: -+ properties: -+ compatible: -+ contains: -+ const: econet,en751627-timer -+ then: -+ properties: -+ reg: -+ items: -+ - description: VPE timers 0 and 1 -+ - description: VPE timers 2 and 3 -+ else: -+ properties: -+ reg: -+ items: -+ - description: VPE timers 0 and 1 -+ -+additionalProperties: false -+ -+examples: -+ - | -+ timer@1fbf0400 { -+ compatible = "econet,en751627-timer", "econet,en751221-timer"; -+ reg = <0x1fbf0400 0x100>, <0x1fbe0000 0x100>; -+ interrupt-parent = <&intc>; -+ interrupts = <30>; -+ clocks = <&hpt_clock>; -+ }; -+ - | -+ timer@1fbf0400 { -+ compatible = "econet,en751221-timer"; -+ reg = <0x1fbe0400 0x100>; -+ interrupt-parent = <&intc>; -+ interrupts = <30>; -+ clocks = <&hpt_clock>; -+ }; -+... diff --git a/target/linux/econet/patches-6.12/005-v6.16-clocksource-drivers-Add-EcoNet-Timer-HPT-driver.patch b/target/linux/econet/patches-6.12/005-v6.16-clocksource-drivers-Add-EcoNet-Timer-HPT-driver.patch deleted file mode 100644 index dcd4bb15e3..0000000000 --- a/target/linux/econet/patches-6.12/005-v6.16-clocksource-drivers-Add-EcoNet-Timer-HPT-driver.patch +++ /dev/null @@ -1,276 +0,0 @@ -From 3b4c33ac87d0d11308f4445ecec2a124e2e77724 Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Wed, 7 May 2025 13:44:55 +0000 -Subject: [PATCH] clocksource/drivers: Add EcoNet Timer HPT driver - -Introduce a clocksource driver for the so-called high-precision timer (HPT) -in the EcoNet EN751221 and EN751627 MIPS SoCs. - -It's a 32 bit upward-counting one-shot timer which relies on the crystal so it -is unaffected by CPU power mode. On MIPS 34K devices (single core) there is -one timer, and on 1004K devices (dual core) there are two. - -Each timer has two sets of count/compare registers so that there is one for -each of the VPEs on the core. Because each core has 2 VPEs, register selection -takes the CPU number / 2 for the timer corrisponding to the core, then CPU -number % 2 for the register corrisponding to the VPE. - -These timers use a percpu-devid IRQ to route interrupts to the VPE which set -the event. - -Signed-off-by: Caleb James DeLisle -Link: https://lore.kernel.org/r/20250507134500.390547-3-cjd@cjdns.fr -Signed-off-by: Daniel Lezcano ---- - drivers/clocksource/Kconfig | 8 + - drivers/clocksource/Makefile | 1 + - drivers/clocksource/timer-econet-en751221.c | 216 ++++++++++++++++++++ - 3 files changed, 225 insertions(+) - create mode 100644 drivers/clocksource/timer-econet-en751221.c - ---- a/drivers/clocksource/Kconfig -+++ b/drivers/clocksource/Kconfig -@@ -73,6 +73,14 @@ config DW_APB_TIMER_OF - select DW_APB_TIMER - select TIMER_OF - -+config ECONET_EN751221_TIMER -+ bool "EcoNet EN751221 High Precision Timer" if COMPILE_TEST -+ depends on HAS_IOMEM -+ select CLKSRC_MMIO -+ select TIMER_OF -+ help -+ Support for CPU timer found on EcoNet MIPS based SoCs. -+ - config FTTMR010_TIMER - bool "Faraday Technology timer driver" if COMPILE_TEST - depends on HAS_IOMEM ---- a/drivers/clocksource/Makefile -+++ b/drivers/clocksource/Makefile -@@ -17,6 +17,7 @@ obj-$(CONFIG_CLKBLD_I8253) += i8253.o - obj-$(CONFIG_CLKSRC_MMIO) += mmio.o - obj-$(CONFIG_DAVINCI_TIMER) += timer-davinci.o - obj-$(CONFIG_DIGICOLOR_TIMER) += timer-digicolor.o -+obj-$(CONFIG_ECONET_EN751221_TIMER) += timer-econet-en751221.o - obj-$(CONFIG_OMAP_DM_TIMER) += timer-ti-dm.o - obj-$(CONFIG_OMAP_DM_SYSTIMER) += timer-ti-dm-systimer.o - obj-$(CONFIG_DW_APB_TIMER) += dw_apb_timer.o ---- /dev/null -+++ b/drivers/clocksource/timer-econet-en751221.c -@@ -0,0 +1,216 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Timer present on EcoNet EN75xx MIPS based SoCs. -+ * -+ * Copyright (C) 2025 by Caleb James DeLisle -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define ECONET_BITS 32 -+#define ECONET_MIN_DELTA 0x00001000 -+#define ECONET_MAX_DELTA GENMASK(ECONET_BITS - 2, 0) -+/* 34Kc hardware has 1 block and 1004Kc has 2. */ -+#define ECONET_NUM_BLOCKS DIV_ROUND_UP(NR_CPUS, 2) -+ -+static struct { -+ void __iomem *membase[ECONET_NUM_BLOCKS]; -+ u32 freq_hz; -+} econet_timer __ro_after_init; -+ -+static DEFINE_PER_CPU(struct clock_event_device, econet_timer_pcpu); -+ -+/* Each memory block has 2 timers, the order of registers is: -+ * CTL, CMR0, CNT0, CMR1, CNT1 -+ */ -+static inline void __iomem *reg_ctl(u32 timer_n) -+{ -+ return econet_timer.membase[timer_n >> 1]; -+} -+ -+static inline void __iomem *reg_compare(u32 timer_n) -+{ -+ return econet_timer.membase[timer_n >> 1] + (timer_n & 1) * 0x08 + 0x04; -+} -+ -+static inline void __iomem *reg_count(u32 timer_n) -+{ -+ return econet_timer.membase[timer_n >> 1] + (timer_n & 1) * 0x08 + 0x08; -+} -+ -+static inline u32 ctl_bit_enabled(u32 timer_n) -+{ -+ return 1U << (timer_n & 1); -+} -+ -+static inline u32 ctl_bit_pending(u32 timer_n) -+{ -+ return 1U << ((timer_n & 1) + 16); -+} -+ -+static bool cevt_is_pending(int cpu_id) -+{ -+ return ioread32(reg_ctl(cpu_id)) & ctl_bit_pending(cpu_id); -+} -+ -+static irqreturn_t cevt_interrupt(int irq, void *dev_id) -+{ -+ struct clock_event_device *dev = this_cpu_ptr(&econet_timer_pcpu); -+ int cpu = cpumask_first(dev->cpumask); -+ -+ /* Each VPE has its own events, -+ * so this will only happen on spurious interrupt. -+ */ -+ if (!cevt_is_pending(cpu)) -+ return IRQ_NONE; -+ -+ iowrite32(ioread32(reg_count(cpu)), reg_compare(cpu)); -+ dev->event_handler(dev); -+ return IRQ_HANDLED; -+} -+ -+static int cevt_set_next_event(ulong delta, struct clock_event_device *dev) -+{ -+ u32 next; -+ int cpu; -+ -+ cpu = cpumask_first(dev->cpumask); -+ next = ioread32(reg_count(cpu)) + delta; -+ iowrite32(next, reg_compare(cpu)); -+ -+ if ((s32)(next - ioread32(reg_count(cpu))) < ECONET_MIN_DELTA / 2) -+ return -ETIME; -+ -+ return 0; -+} -+ -+static int cevt_init_cpu(uint cpu) -+{ -+ struct clock_event_device *cd = &per_cpu(econet_timer_pcpu, cpu); -+ u32 reg; -+ -+ pr_debug("%s: Setting up clockevent for CPU %d\n", cd->name, cpu); -+ -+ reg = ioread32(reg_ctl(cpu)) | ctl_bit_enabled(cpu); -+ iowrite32(reg, reg_ctl(cpu)); -+ -+ enable_percpu_irq(cd->irq, IRQ_TYPE_NONE); -+ -+ /* Do this last because it synchronously configures the timer */ -+ clockevents_config_and_register(cd, econet_timer.freq_hz, -+ ECONET_MIN_DELTA, ECONET_MAX_DELTA); -+ -+ return 0; -+} -+ -+static u64 notrace sched_clock_read(void) -+{ -+ /* Always read from clock zero no matter the CPU */ -+ return (u64)ioread32(reg_count(0)); -+} -+ -+/* Init */ -+ -+static void __init cevt_dev_init(uint cpu) -+{ -+ iowrite32(0, reg_count(cpu)); -+ iowrite32(U32_MAX, reg_compare(cpu)); -+} -+ -+static int __init cevt_init(struct device_node *np) -+{ -+ int i, irq, ret; -+ -+ irq = irq_of_parse_and_map(np, 0); -+ if (irq <= 0) { -+ pr_err("%pOFn: irq_of_parse_and_map failed", np); -+ return -EINVAL; -+ } -+ -+ ret = request_percpu_irq(irq, cevt_interrupt, np->name, &econet_timer_pcpu); -+ -+ if (ret < 0) { -+ pr_err("%pOFn: IRQ %d setup failed (%d)\n", np, irq, ret); -+ goto err_unmap_irq; -+ } -+ -+ for_each_possible_cpu(i) { -+ struct clock_event_device *cd = &per_cpu(econet_timer_pcpu, i); -+ -+ cd->rating = 310, -+ cd->features = CLOCK_EVT_FEAT_ONESHOT | -+ CLOCK_EVT_FEAT_C3STOP | -+ CLOCK_EVT_FEAT_PERCPU; -+ cd->set_next_event = cevt_set_next_event; -+ cd->irq = irq; -+ cd->cpumask = cpumask_of(i); -+ cd->name = np->name; -+ -+ cevt_dev_init(i); -+ } -+ -+ cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, -+ "clockevents/econet/timer:starting", -+ cevt_init_cpu, NULL); -+ return 0; -+ -+err_unmap_irq: -+ irq_dispose_mapping(irq); -+ return ret; -+} -+ -+static int __init timer_init(struct device_node *np) -+{ -+ int num_blocks = DIV_ROUND_UP(num_possible_cpus(), 2); -+ struct clk *clk; -+ int ret; -+ -+ clk = of_clk_get(np, 0); -+ if (IS_ERR(clk)) { -+ pr_err("%pOFn: Failed to get CPU clock from DT %ld\n", np, PTR_ERR(clk)); -+ return PTR_ERR(clk); -+ } -+ -+ econet_timer.freq_hz = clk_get_rate(clk); -+ -+ for (int i = 0; i < num_blocks; i++) { -+ econet_timer.membase[i] = of_iomap(np, i); -+ if (!econet_timer.membase[i]) { -+ pr_err("%pOFn: failed to map register [%d]\n", np, i); -+ return -ENXIO; -+ } -+ } -+ -+ /* For clocksource purposes always read clock zero, whatever the CPU */ -+ ret = clocksource_mmio_init(reg_count(0), np->name, -+ econet_timer.freq_hz, 301, ECONET_BITS, -+ clocksource_mmio_readl_up); -+ if (ret) { -+ pr_err("%pOFn: clocksource_mmio_init failed: %d", np, ret); -+ return ret; -+ } -+ -+ ret = cevt_init(np); -+ if (ret < 0) -+ return ret; -+ -+ sched_clock_register(sched_clock_read, ECONET_BITS, -+ econet_timer.freq_hz); -+ -+ pr_info("%pOFn: using %u.%03u MHz high precision timer\n", np, -+ econet_timer.freq_hz / 1000000, -+ (econet_timer.freq_hz / 1000) % 1000); -+ -+ return 0; -+} -+ -+TIMER_OF_DECLARE(econet_timer_hpt, "econet,en751221-timer", timer_init); diff --git a/target/linux/econet/patches-6.12/006-v6.16-dt-bindings-mips-Add-EcoNet-platform-binding.patch b/target/linux/econet/patches-6.12/006-v6.16-dt-bindings-mips-Add-EcoNet-platform-binding.patch deleted file mode 100644 index 64714dc8a2..0000000000 --- a/target/linux/econet/patches-6.12/006-v6.16-dt-bindings-mips-Add-EcoNet-platform-binding.patch +++ /dev/null @@ -1,44 +0,0 @@ -From be8b4173719a61fdd8379e86895d855775cf5f91 Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Wed, 7 May 2025 13:44:56 +0000 -Subject: [PATCH] dt-bindings: mips: Add EcoNet platform binding - -Document the top-level device tree binding for EcoNet MIPS-based SoCs. - -Signed-off-by: Caleb James DeLisle -Reviewed-by: Krzysztof Kozlowski -Signed-off-by: Thomas Bogendoerfer ---- - .../devicetree/bindings/mips/econet.yaml | 26 +++++++++++++++++++ - 1 file changed, 26 insertions(+) - create mode 100644 Documentation/devicetree/bindings/mips/econet.yaml - ---- /dev/null -+++ b/Documentation/devicetree/bindings/mips/econet.yaml -@@ -0,0 +1,26 @@ -+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/mips/econet.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: EcoNet MIPS SoCs -+ -+maintainers: -+ - Caleb James DeLisle -+ -+properties: -+ $nodename: -+ const: '/' -+ -+ compatible: -+ oneOf: -+ - description: Boards with EcoNet EN751221 family SoC -+ items: -+ - enum: -+ - smartfiber,xp8421-b -+ - const: econet,en751221 -+ -+additionalProperties: true -+ -+... diff --git a/target/linux/econet/patches-6.12/007-v6.16-mips-Add-EcoNet-MIPS-platform-support.patch b/target/linux/econet/patches-6.12/007-v6.16-mips-Add-EcoNet-MIPS-platform-support.patch deleted file mode 100644 index 86b05b07a1..0000000000 --- a/target/linux/econet/patches-6.12/007-v6.16-mips-Add-EcoNet-MIPS-platform-support.patch +++ /dev/null @@ -1,222 +0,0 @@ -From 35fb26f94dfa1b291086b84b2421f957214824d1 Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Wed, 7 May 2025 13:44:57 +0000 -Subject: [PATCH] mips: Add EcoNet MIPS platform support - -Add platform support for EcoNet MIPS SoCs. - -Signed-off-by: Caleb James DeLisle -Signed-off-by: Thomas Bogendoerfer ---- - arch/mips/Kbuild.platforms | 1 + - arch/mips/Kconfig | 25 +++++++++ - arch/mips/boot/compressed/uart-16550.c | 5 ++ - arch/mips/econet/Kconfig | 37 ++++++++++++ - arch/mips/econet/Makefile | 2 + - arch/mips/econet/Platform | 5 ++ - arch/mips/econet/init.c | 78 ++++++++++++++++++++++++++ - 7 files changed, 153 insertions(+) - create mode 100644 arch/mips/econet/Kconfig - create mode 100644 arch/mips/econet/Makefile - create mode 100644 arch/mips/econet/Platform - create mode 100644 arch/mips/econet/init.c - ---- a/arch/mips/Kbuild.platforms -+++ b/arch/mips/Kbuild.platforms -@@ -11,6 +11,7 @@ platform-$(CONFIG_CAVIUM_OCTEON_SOC) += - platform-$(CONFIG_EYEQ) += mobileye/ - platform-$(CONFIG_MIPS_COBALT) += cobalt/ - platform-$(CONFIG_MACH_DECSTATION) += dec/ -+platform-$(CONFIG_ECONET) += econet/ - platform-$(CONFIG_MIPS_GENERIC) += generic/ - platform-$(CONFIG_MACH_JAZZ) += jazz/ - platform-$(CONFIG_LANTIQ) += lantiq/ ---- a/arch/mips/Kconfig -+++ b/arch/mips/Kconfig -@@ -388,6 +388,30 @@ config MACH_DECSTATION - - otherwise choose R3000. - -+config ECONET -+ bool "EcoNet MIPS family" -+ select BOOT_RAW -+ select CPU_BIG_ENDIAN -+ select DEBUG_ZBOOT -+ select EARLY_PRINTK_8250 -+ select ECONET_EN751221_TIMER -+ select SERIAL_OF_PLATFORM -+ select SYS_SUPPORTS_BIG_ENDIAN -+ select SYS_HAS_CPU_MIPS32_R1 -+ select SYS_HAS_CPU_MIPS32_R2 -+ select SYS_HAS_EARLY_PRINTK -+ select SYS_SUPPORTS_32BIT_KERNEL -+ select SYS_SUPPORTS_MIPS16 -+ select SYS_SUPPORTS_ZBOOT_UART16550 -+ select USE_GENERIC_EARLY_PRINTK_8250 -+ select USE_OF -+ help -+ EcoNet EN75xx MIPS devices are big endian MIPS machines used -+ in XPON (fiber) and DSL applications. They have SPI, PCI, USB, -+ GPIO, and Ethernet, with optional XPON, DSL, and VoIP DSP cores. -+ Don't confuse these with the Airoha ARM devices sometimes referred -+ to as "EcoNet", this family is for MIPS based devices only. -+ - config MACH_JAZZ - bool "Jazz family of machines" - select ARC_MEMORY -@@ -1017,6 +1041,7 @@ source "arch/mips/ath79/Kconfig" - source "arch/mips/bcm47xx/Kconfig" - source "arch/mips/bcm63xx/Kconfig" - source "arch/mips/bmips/Kconfig" -+source "arch/mips/econet/Kconfig" - source "arch/mips/generic/Kconfig" - source "arch/mips/ingenic/Kconfig" - source "arch/mips/jazz/Kconfig" ---- a/arch/mips/boot/compressed/uart-16550.c -+++ b/arch/mips/boot/compressed/uart-16550.c -@@ -20,6 +20,11 @@ - #define PORT(offset) (CKSEG1ADDR(INGENIC_UART_BASE_ADDR) + (4 * offset)) - #endif - -+#ifdef CONFIG_ECONET -+#define EN75_UART_BASE 0x1fbf0003 -+#define PORT(offset) (CKSEG1ADDR(EN75_UART_BASE) + (4 * (offset))) -+#endif -+ - #ifndef IOTYPE - #define IOTYPE char - #endif ---- /dev/null -+++ b/arch/mips/econet/Kconfig -@@ -0,0 +1,37 @@ -+# SPDX-License-Identifier: GPL-2.0 -+if ECONET -+ -+choice -+ prompt "EcoNet SoC selection" -+ default SOC_ECONET_EN751221 -+ help -+ Select EcoNet MIPS SoC type. Individual SoCs within a family are -+ very similar, so is it enough to select the right family, and -+ then customize to the specific SoC using the device tree only. -+ -+ config SOC_ECONET_EN751221 -+ bool "EN751221 family" -+ select COMMON_CLK -+ select ECONET_EN751221_INTC -+ select IRQ_MIPS_CPU -+ select SMP -+ select SMP_UP -+ select SYS_SUPPORTS_SMP -+ help -+ The EN751221 family includes EN7512, RN7513, EN7521, EN7526. -+ They are based on single core MIPS 34Kc processors. To boot -+ this kernel, you will need a device tree such as -+ MIPS_RAW_APPENDED_DTB=y, and a root filesystem. -+endchoice -+ -+choice -+ prompt "Devicetree selection" -+ default DTB_ECONET_NONE -+ help -+ Select the devicetree. -+ -+ config DTB_ECONET_NONE -+ bool "None" -+endchoice -+ -+endif ---- /dev/null -+++ b/arch/mips/econet/Makefile -@@ -0,0 +1,2 @@ -+ -+obj-y := init.o ---- /dev/null -+++ b/arch/mips/econet/Platform -@@ -0,0 +1,5 @@ -+# To address a 7.2MB kernel size limit in the EcoNet SDK bootloader, -+# we put the load address well above where the bootloader loads and then use -+# zboot. So please set CONFIG_ZBOOT_LOAD_ADDRESS to the address where your -+# bootloader actually places the kernel. -+load-$(CONFIG_ECONET) += 0xffffffff81000000 ---- /dev/null -+++ b/arch/mips/econet/init.c -@@ -0,0 +1,78 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * EcoNet setup code -+ * -+ * Copyright (C) 2025 Caleb James DeLisle -+ */ -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define CR_AHB_RSTCR ((void __iomem *)CKSEG1ADDR(0x1fb00040)) -+#define RESET BIT(31) -+ -+#define UART_BASE CKSEG1ADDR(0x1fbf0003) -+#define UART_REG_SHIFT 2 -+ -+static void hw_reset(char *command) -+{ -+ iowrite32(RESET, CR_AHB_RSTCR); -+} -+ -+/* 1. Bring up early printk. */ -+void __init prom_init(void) -+{ -+ setup_8250_early_printk_port(UART_BASE, UART_REG_SHIFT, 0); -+ _machine_restart = hw_reset; -+} -+ -+/* 2. Parse the DT and find memory */ -+void __init plat_mem_setup(void) -+{ -+ void *dtb; -+ -+ set_io_port_base(KSEG1); -+ -+ dtb = get_fdt(); -+ if (!dtb) -+ panic("no dtb found"); -+ -+ __dt_setup_arch(dtb); -+ -+ early_init_dt_scan_memory(); -+} -+ -+/* 3. Overload __weak device_tree_init(), add SMP_UP ops */ -+void __init device_tree_init(void) -+{ -+ unflatten_and_copy_device_tree(); -+ -+ register_up_smp_ops(); -+} -+ -+const char *get_system_type(void) -+{ -+ return "EcoNet-EN75xx"; -+} -+ -+/* 4. Initialize the IRQ subsystem */ -+void __init arch_init_irq(void) -+{ -+ irqchip_init(); -+} -+ -+/* 5. Timers */ -+void __init plat_time_init(void) -+{ -+ of_clk_init(NULL); -+ timer_probe(); -+} diff --git a/target/linux/econet/patches-6.12/008-v6.16-dt-bindings-vendor-prefixes-Add-SmartFiber.patch b/target/linux/econet/patches-6.12/008-v6.16-dt-bindings-vendor-prefixes-Add-SmartFiber.patch deleted file mode 100644 index 6d51af0231..0000000000 --- a/target/linux/econet/patches-6.12/008-v6.16-dt-bindings-vendor-prefixes-Add-SmartFiber.patch +++ /dev/null @@ -1,29 +0,0 @@ -From abc2d0bc2cb7c1412b8b254c0446f94b3e203c7c Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Wed, 7 May 2025 13:44:58 +0000 -Subject: [PATCH] dt-bindings: vendor-prefixes: Add SmartFiber -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add "smartfiber" vendor prefix for manufactorer of EcoNet based boards. - -Signed-off-by: Caleb James DeLisle -Acked-by: Krzysztof Kozlowski -Reviewed-by: Philippe Mathieu-Daudé -Signed-off-by: Thomas Bogendoerfer ---- - Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/Documentation/devicetree/bindings/vendor-prefixes.yaml -+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml -@@ -1370,6 +1370,8 @@ patternProperties: - description: SKOV A/S - "^skyworks,.*": - description: Skyworks Solutions, Inc. -+ "^smartfiber,.*": -+ description: ShenZhen Smartfiber Technology Co, Ltd. - "^smartlabs,.*": - description: SmartLabs LLC - "^smartrg,.*": diff --git a/target/linux/econet/patches-6.12/009-v6.16-mips-dts-Add-EcoNet-DTS-with-EN751221-and-SmartFiber.patch b/target/linux/econet/patches-6.12/009-v6.16-mips-dts-Add-EcoNet-DTS-with-EN751221-and-SmartFiber.patch deleted file mode 100644 index cb5b457137..0000000000 --- a/target/linux/econet/patches-6.12/009-v6.16-mips-dts-Add-EcoNet-DTS-with-EN751221-and-SmartFiber.patch +++ /dev/null @@ -1,149 +0,0 @@ -From 0ec4887009729297f7c10368084e41a8a9fbbd0e Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Wed, 7 May 2025 13:44:59 +0000 -Subject: [PATCH] mips: dts: Add EcoNet DTS with EN751221 and SmartFiber - XP8421-B board - -Add DTS files in support of EcoNet platform, including SmartFiber XP8421-B, -a low cost commercially available board based on EN751221. - -Signed-off-by: Caleb James DeLisle -Signed-off-by: Thomas Bogendoerfer ---- - arch/mips/boot/dts/Makefile | 1 + - arch/mips/boot/dts/econet/Makefile | 2 + - arch/mips/boot/dts/econet/en751221.dtsi | 67 +++++++++++++++++++ - .../econet/en751221_smartfiber_xp8421-b.dts | 19 ++++++ - arch/mips/econet/Kconfig | 11 +++ - 5 files changed, 100 insertions(+) - create mode 100644 arch/mips/boot/dts/econet/Makefile - create mode 100644 arch/mips/boot/dts/econet/en751221.dtsi - create mode 100644 arch/mips/boot/dts/econet/en751221_smartfiber_xp8421-b.dts - ---- a/arch/mips/boot/dts/Makefile -+++ b/arch/mips/boot/dts/Makefile -@@ -1,6 +1,7 @@ - # SPDX-License-Identifier: GPL-2.0 - subdir-$(CONFIG_BMIPS_GENERIC) += brcm - subdir-$(CONFIG_CAVIUM_OCTEON_SOC) += cavium-octeon -+subdir-$(CONFIG_ECONET) += econet - subdir-$(CONFIG_EYEQ) += mobileye - subdir-$(CONFIG_FIT_IMAGE_FDT_MARDUK) += img - subdir-$(CONFIG_FIT_IMAGE_FDT_BOSTON) += img ---- /dev/null -+++ b/arch/mips/boot/dts/econet/Makefile -@@ -0,0 +1,2 @@ -+# SPDX-License-Identifier: GPL-2.0 -+dtb-$(CONFIG_DTB_ECONET_SMARTFIBER_XP8421_B) += en751221_smartfiber_xp8421-b.dtb ---- /dev/null -+++ b/arch/mips/boot/dts/econet/en751221.dtsi -@@ -0,0 +1,67 @@ -+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+/dts-v1/; -+ -+/ { -+ compatible = "econet,en751221"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ hpt_clock: clock { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <200000000>; /* 200 MHz */ -+ }; -+ -+ cpus: cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ cpu@0 { -+ device_type = "cpu"; -+ compatible = "mips,mips24KEc"; -+ reg = <0>; -+ }; -+ }; -+ -+ cpuintc: interrupt-controller { -+ compatible = "mti,cpu-interrupt-controller"; -+ interrupt-controller; -+ #address-cells = <0>; -+ #interrupt-cells = <1>; -+ }; -+ -+ intc: interrupt-controller@1fb40000 { -+ compatible = "econet,en751221-intc"; -+ reg = <0x1fb40000 0x100>; -+ interrupt-parent = <&cpuintc>; -+ interrupts = <2>; -+ -+ interrupt-controller; -+ #interrupt-cells = <1>; -+ econet,shadow-interrupts = <7 2>, <8 3>, <13 12>, <30 29>; -+ }; -+ -+ uart: serial@1fbf0000 { -+ compatible = "ns16550"; -+ reg = <0x1fbf0000 0x30>; -+ reg-io-width = <4>; -+ reg-shift = <2>; -+ interrupt-parent = <&intc>; -+ interrupts = <0>; -+ /* -+ * Conversion of baud rate to clock frequency requires a -+ * computation that is not in the ns16550 driver, so this -+ * uart is fixed at 115200 baud. -+ */ -+ clock-frequency = <1843200>; -+ }; -+ -+ timer_hpt: timer@1fbf0400 { -+ compatible = "econet,en751221-timer"; -+ reg = <0x1fbf0400 0x100>; -+ -+ interrupt-parent = <&intc>; -+ interrupts = <30>; -+ clocks = <&hpt_clock>; -+ }; -+}; ---- /dev/null -+++ b/arch/mips/boot/dts/econet/en751221_smartfiber_xp8421-b.dts -@@ -0,0 +1,19 @@ -+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+/dts-v1/; -+ -+#include "en751221.dtsi" -+ -+/ { -+ model = "SmartFiber XP8421-B"; -+ compatible = "smartfiber,xp8421-b", "econet,en751221"; -+ -+ memory@0 { -+ device_type = "memory"; -+ reg = <0x00000000 0x1c000000>; -+ }; -+ -+ chosen { -+ stdout-path = "/serial@1fbf0000:115200"; -+ linux,usable-memory-range = <0x00020000 0x1bfe0000>; -+ }; -+}; ---- a/arch/mips/econet/Kconfig -+++ b/arch/mips/econet/Kconfig -@@ -32,6 +32,17 @@ choice - - config DTB_ECONET_NONE - bool "None" -+ -+ config DTB_ECONET_SMARTFIBER_XP8421_B -+ bool "EN751221 SmartFiber XP8421-B" -+ depends on SOC_ECONET_EN751221 -+ select BUILTIN_DTB -+ help -+ The SmartFiber XP8421-B is a device based on the EN751221 SoC. -+ It has 512MB of memory and 256MB of NAND flash. This kernel -+ needs only an appended initramfs to boot. It can be loaded -+ through XMODEM and booted from memory in the bootloader, or -+ it can be packed in tclinux.trx format and written to flash. - endchoice - - endif diff --git a/target/linux/econet/patches-6.12/010-v6.16-MAINTAINERS-Add-entry-for-newly-added-EcoNet-platfor.patch b/target/linux/econet/patches-6.12/010-v6.16-MAINTAINERS-Add-entry-for-newly-added-EcoNet-platfor.patch deleted file mode 100644 index e4230573c2..0000000000 --- a/target/linux/econet/patches-6.12/010-v6.16-MAINTAINERS-Add-entry-for-newly-added-EcoNet-platfor.patch +++ /dev/null @@ -1,38 +0,0 @@ -From faefb0a59c5914b7b8f737e2ec5c82822e5bc4c7 Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Wed, 7 May 2025 13:45:00 +0000 -Subject: [PATCH] MAINTAINERS: Add entry for newly added EcoNet platform. -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add a MAINTAINERS entry as part of integration of the EcoNet MIPS platform. - -Signed-off-by: Caleb James DeLisle -Reviewed-by: Philippe Mathieu-Daudé -Signed-off-by: Thomas Bogendoerfer ---- - MAINTAINERS | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -8025,6 +8025,18 @@ W: https://linuxtv.org - Q: http://patchwork.linuxtv.org/project/linux-media/list/ - F: drivers/media/dvb-frontends/ec100* - -+ECONET MIPS PLATFORM -+M: Caleb James DeLisle -+L: linux-mips@vger.kernel.org -+S: Maintained -+F: Documentation/devicetree/bindings/interrupt-controller/econet,en751221-intc.yaml -+F: Documentation/devicetree/bindings/mips/econet.yaml -+F: Documentation/devicetree/bindings/timer/econet,en751221-timer.yaml -+F: arch/mips/boot/dts/econet/ -+F: arch/mips/econet/ -+F: drivers/clocksource/timer-econet-en751221.c -+F: drivers/irqchip/irq-econet-en751221.c -+ - ECRYPT FILE SYSTEM - M: Tyler Hicks - L: ecryptfs@vger.kernel.org diff --git a/target/linux/econet/patches-6.12/011-v6.16-mips-econet-Fix-incorrect-Kconfig-dependencies.patch b/target/linux/econet/patches-6.12/011-v6.16-mips-econet-Fix-incorrect-Kconfig-dependencies.patch deleted file mode 100644 index fe9e6792eb..0000000000 --- a/target/linux/econet/patches-6.12/011-v6.16-mips-econet-Fix-incorrect-Kconfig-dependencies.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 79ee1d20e37cd553cc961962fca8107e69a0c293 Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Wed, 21 May 2025 21:33:33 +0000 -Subject: [PATCH] mips: econet: Fix incorrect Kconfig dependencies - -config ECONET selects SERIAL_OF_PLATFORM and that depends on SERIAL_8250 -so we need to select SERIAL_8250 directly. -Also do not enable DEBUG_ZBOOT unless DEBUG_KERNEL is set. - -Signed-off-by: Caleb James DeLisle -Reported-by: kernel test robot -Closes: https://lore.kernel.org/oe-kbuild-all/202505211654.CBdIsoTq-lkp@intel.com/ -Closes: https://lore.kernel.org/oe-kbuild-all/202505211451.WRjyf3a9-lkp@intel.com/ -Signed-off-by: Thomas Bogendoerfer ---- - arch/mips/Kconfig | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/arch/mips/Kconfig -+++ b/arch/mips/Kconfig -@@ -392,9 +392,10 @@ config ECONET - bool "EcoNet MIPS family" - select BOOT_RAW - select CPU_BIG_ENDIAN -- select DEBUG_ZBOOT -+ select DEBUG_ZBOOT if DEBUG_KERNEL - select EARLY_PRINTK_8250 - select ECONET_EN751221_TIMER -+ select SERIAL_8250 - select SERIAL_OF_PLATFORM - select SYS_SUPPORTS_BIG_ENDIAN - select SYS_HAS_CPU_MIPS32_R1 diff --git a/target/linux/econet/patches-6.12/012-v6.13-clk-en7523-move-en7581_reset_register-in-en7581_clk_.patch b/target/linux/econet/patches-6.12/012-v6.13-clk-en7523-move-en7581_reset_register-in-en7581_clk_.patch deleted file mode 100644 index 26b3da9c4d..0000000000 --- a/target/linux/econet/patches-6.12/012-v6.13-clk-en7523-move-en7581_reset_register-in-en7581_clk_.patch +++ /dev/null @@ -1,174 +0,0 @@ -From 82e6bf912d5846646892becea659b39d178d79e3 Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Tue, 12 Nov 2024 01:08:53 +0100 -Subject: [PATCH 5/8] clk: en7523: move en7581_reset_register() in - en7581_clk_hw_init() - -Move en7581_reset_register routine in en7581_clk_hw_init() since reset -feature is supported just by EN7581 SoC. -Get rid of reset struct in en_clk_soc_data data struct. - -Signed-off-by: Lorenzo Bianconi -Link: https://lore.kernel.org/r/20241112-clk-en7581-syscon-v2-6-8ada5e394ae4@kernel.org -Signed-off-by: Stephen Boyd ---- - drivers/clk/clk-en7523.c | 93 ++++++++++++++-------------------------- - 1 file changed, 33 insertions(+), 60 deletions(-) - ---- a/drivers/clk/clk-en7523.c -+++ b/drivers/clk/clk-en7523.c -@@ -76,11 +76,6 @@ struct en_rst_data { - - struct en_clk_soc_data { - const struct clk_ops pcie_ops; -- struct { -- const u16 *bank_ofs; -- const u16 *idx_map; -- u16 idx_map_nr; -- } reset; - int (*hw_init)(struct platform_device *pdev, - struct clk_hw_onecell_data *clk_data); - }; -@@ -596,32 +591,6 @@ static void en7581_register_clocks(struc - clk_data->num = EN7523_NUM_CLOCKS; - } - --static int en7581_clk_hw_init(struct platform_device *pdev, -- struct clk_hw_onecell_data *clk_data) --{ -- void __iomem *np_base; -- struct regmap *map; -- u32 val; -- -- map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu"); -- if (IS_ERR(map)) -- return PTR_ERR(map); -- -- np_base = devm_platform_ioremap_resource(pdev, 0); -- if (IS_ERR(np_base)) -- return PTR_ERR(np_base); -- -- en7581_register_clocks(&pdev->dev, clk_data, map, np_base); -- -- val = readl(np_base + REG_NP_SCU_SSTR); -- val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK); -- writel(val, np_base + REG_NP_SCU_SSTR); -- val = readl(np_base + REG_NP_SCU_PCIC); -- writel(val | 3, np_base + REG_NP_SCU_PCIC); -- -- return 0; --} -- - static int en7523_reset_update(struct reset_controller_dev *rcdev, - unsigned long id, bool assert) - { -@@ -671,23 +640,18 @@ static int en7523_reset_xlate(struct res - return rst_data->idx_map[reset_spec->args[0]]; - } - --static const struct reset_control_ops en7523_reset_ops = { -+static const struct reset_control_ops en7581_reset_ops = { - .assert = en7523_reset_assert, - .deassert = en7523_reset_deassert, - .status = en7523_reset_status, - }; - --static int en7523_reset_register(struct platform_device *pdev, -- const struct en_clk_soc_data *soc_data) -+static int en7581_reset_register(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; - struct en_rst_data *rst_data; - void __iomem *base; - -- /* no reset lines available */ -- if (!soc_data->reset.idx_map_nr) -- return 0; -- - base = devm_platform_ioremap_resource(pdev, 1); - if (IS_ERR(base)) - return PTR_ERR(base); -@@ -696,13 +660,13 @@ static int en7523_reset_register(struct - if (!rst_data) - return -ENOMEM; - -- rst_data->bank_ofs = soc_data->reset.bank_ofs; -- rst_data->idx_map = soc_data->reset.idx_map; -+ rst_data->bank_ofs = en7581_rst_ofs; -+ rst_data->idx_map = en7581_rst_map; - rst_data->base = base; - -- rst_data->rcdev.nr_resets = soc_data->reset.idx_map_nr; -+ rst_data->rcdev.nr_resets = ARRAY_SIZE(en7581_rst_map); - rst_data->rcdev.of_xlate = en7523_reset_xlate; -- rst_data->rcdev.ops = &en7523_reset_ops; -+ rst_data->rcdev.ops = &en7581_reset_ops; - rst_data->rcdev.of_node = dev->of_node; - rst_data->rcdev.of_reset_n_cells = 1; - rst_data->rcdev.owner = THIS_MODULE; -@@ -711,6 +675,32 @@ static int en7523_reset_register(struct - return devm_reset_controller_register(dev, &rst_data->rcdev); - } - -+static int en7581_clk_hw_init(struct platform_device *pdev, -+ struct clk_hw_onecell_data *clk_data) -+{ -+ void __iomem *np_base; -+ struct regmap *map; -+ u32 val; -+ -+ map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu"); -+ if (IS_ERR(map)) -+ return PTR_ERR(map); -+ -+ np_base = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(np_base)) -+ return PTR_ERR(np_base); -+ -+ en7581_register_clocks(&pdev->dev, clk_data, map, np_base); -+ -+ val = readl(np_base + REG_NP_SCU_SSTR); -+ val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK); -+ writel(val, np_base + REG_NP_SCU_SSTR); -+ val = readl(np_base + REG_NP_SCU_PCIC); -+ writel(val | 3, np_base + REG_NP_SCU_PCIC); -+ -+ return en7581_reset_register(pdev); -+} -+ - static int en7523_clk_probe(struct platform_device *pdev) - { - struct device_node *node = pdev->dev.of_node; -@@ -729,19 +719,7 @@ static int en7523_clk_probe(struct platf - if (r) - return r; - -- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -- if (r) -- return dev_err_probe(&pdev->dev, r, "Could not register clock provider: %s\n", -- pdev->name); -- -- r = en7523_reset_register(pdev, soc_data); -- if (r) { -- of_clk_del_provider(node); -- return dev_err_probe(&pdev->dev, r, "Could not register reset controller: %s\n", -- pdev->name); -- } -- -- return 0; -+ return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - } - - static const struct en_clk_soc_data en7523_data = { -@@ -759,11 +737,6 @@ static const struct en_clk_soc_data en75 - .enable = en7581_pci_enable, - .disable = en7581_pci_disable, - }, -- .reset = { -- .bank_ofs = en7581_rst_ofs, -- .idx_map = en7581_rst_map, -- .idx_map_nr = ARRAY_SIZE(en7581_rst_map), -- }, - .hw_init = en7581_clk_hw_init, - }; - diff --git a/target/linux/econet/patches-6.12/013-v6.13-clk-en7523-map-io-region-in-a-single-block.patch b/target/linux/econet/patches-6.12/013-v6.13-clk-en7523-map-io-region-in-a-single-block.patch deleted file mode 100644 index 4e4952d8a6..0000000000 --- a/target/linux/econet/patches-6.12/013-v6.13-clk-en7523-map-io-region-in-a-single-block.patch +++ /dev/null @@ -1,84 +0,0 @@ -From a9eaf305017a5ebe73ab34e85bd5414055a88f29 Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Tue, 12 Nov 2024 01:08:54 +0100 -Subject: [PATCH 6/8] clk: en7523: map io region in a single block - -Map all clock-controller memory region in a single block. -This patch does not introduce any backward incompatibility since the dts -for EN7581 SoC is not upstream yet. - -Signed-off-by: Lorenzo Bianconi -Link: https://lore.kernel.org/r/20241112-clk-en7581-syscon-v2-7-8ada5e394ae4@kernel.org -Signed-off-by: Stephen Boyd ---- - drivers/clk/clk-en7523.c | 32 +++++++++++++------------------- - 1 file changed, 13 insertions(+), 19 deletions(-) - ---- a/drivers/clk/clk-en7523.c -+++ b/drivers/clk/clk-en7523.c -@@ -39,8 +39,8 @@ - #define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11) - #define REG_CRYPTO_CLKSRC2 0x20c - --#define REG_RST_CTRL2 0x00 --#define REG_RST_CTRL1 0x04 -+#define REG_RST_CTRL2 0x830 -+#define REG_RST_CTRL1 0x834 - - struct en_clk_desc { - int id; -@@ -646,15 +646,9 @@ static const struct reset_control_ops en - .status = en7523_reset_status, - }; - --static int en7581_reset_register(struct platform_device *pdev) -+static int en7581_reset_register(struct device *dev, void __iomem *base) - { -- struct device *dev = &pdev->dev; - struct en_rst_data *rst_data; -- void __iomem *base; -- -- base = devm_platform_ioremap_resource(pdev, 1); -- if (IS_ERR(base)) -- return PTR_ERR(base); - - rst_data = devm_kzalloc(dev, sizeof(*rst_data), GFP_KERNEL); - if (!rst_data) -@@ -678,27 +672,27 @@ static int en7581_reset_register(struct - static int en7581_clk_hw_init(struct platform_device *pdev, - struct clk_hw_onecell_data *clk_data) - { -- void __iomem *np_base; - struct regmap *map; -+ void __iomem *base; - u32 val; - - map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu"); - if (IS_ERR(map)) - return PTR_ERR(map); - -- np_base = devm_platform_ioremap_resource(pdev, 0); -- if (IS_ERR(np_base)) -- return PTR_ERR(np_base); -+ base = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(base)) -+ return PTR_ERR(base); - -- en7581_register_clocks(&pdev->dev, clk_data, map, np_base); -+ en7581_register_clocks(&pdev->dev, clk_data, map, base); - -- val = readl(np_base + REG_NP_SCU_SSTR); -+ val = readl(base + REG_NP_SCU_SSTR); - val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK); -- writel(val, np_base + REG_NP_SCU_SSTR); -- val = readl(np_base + REG_NP_SCU_PCIC); -- writel(val | 3, np_base + REG_NP_SCU_PCIC); -+ writel(val, base + REG_NP_SCU_SSTR); -+ val = readl(base + REG_NP_SCU_PCIC); -+ writel(val | 3, base + REG_NP_SCU_PCIC); - -- return en7581_reset_register(pdev); -+ return en7581_reset_register(&pdev->dev, base); - } - - static int en7523_clk_probe(struct platform_device *pdev) diff --git a/target/linux/econet/patches-6.12/014-v6.14-PCI-mediatek-gen3-Move-reset-delay-in-mtk_pcie_en758.patch b/target/linux/econet/patches-6.12/014-v6.14-PCI-mediatek-gen3-Move-reset-delay-in-mtk_pcie_en758.patch deleted file mode 100644 index 44664202a8..0000000000 --- a/target/linux/econet/patches-6.12/014-v6.14-PCI-mediatek-gen3-Move-reset-delay-in-mtk_pcie_en758.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 90d4e466c9ea2010f33880a36317a8486ccbe082 Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Wed, 8 Jan 2025 10:50:43 +0100 -Subject: [PATCH 1/3] PCI: mediatek-gen3: Move reset delay in - mtk_pcie_en7581_power_up() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Airoha EN7581 has a hw bug asserting/releasing PCIE_PE_RSTB signal -causing occasional PCIe link down issues. In order to overcome the -problem, PCIe block is reset using REG_PCI_CONTROL (0x88) and -REG_RESET_CONTROL (0x834) registers available in the clock module -running clk_bulk_prepare_enable() in mtk_pcie_en7581_power_up(). - -In order to make the code more readable, move the wait for the time -needed to complete the PCIe reset from en7581_pci_enable() to -mtk_pcie_en7581_power_up(). - -Reduce reset timeout from 250ms to the standard PCIE_T_PVPERL_MS value -(100ms) since it has no impact on the driver behavior. - -Link: https://lore.kernel.org/r/20250108-pcie-en7581-fixes-v6-4-21ac939a3b9b@kernel.org -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Krzysztof Wilczyński -Reviewed-by: AngeloGioacchino Del Regno -Reviewed-by: Manivannan Sadhasivam -Acked-by: Stephen Boyd ---- - drivers/clk/clk-en7523.c | 1 - - 1 file changed, 1 deletion(-) - ---- a/drivers/clk/clk-en7523.c -+++ b/drivers/clk/clk-en7523.c -@@ -478,7 +478,6 @@ static int en7581_pci_enable(struct clk_ - REG_PCI_CONTROL_PERSTOUT; - val = readl(np_base + REG_PCI_CONTROL); - writel(val | mask, np_base + REG_PCI_CONTROL); -- msleep(250); - - return 0; - } diff --git a/target/linux/econet/patches-6.12/015-v6.14-clk-en7523-Rework-clock-handling-for-different-clock.patch b/target/linux/econet/patches-6.12/015-v6.14-clk-en7523-Rework-clock-handling-for-different-clock.patch deleted file mode 100644 index a33e842b9e..0000000000 --- a/target/linux/econet/patches-6.12/015-v6.14-clk-en7523-Rework-clock-handling-for-different-clock.patch +++ /dev/null @@ -1,83 +0,0 @@ -From e4a9748e7103c47e575459db2b6a77d14f34da2b Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Tue, 14 Jan 2025 00:10:02 +0100 -Subject: [PATCH 2/3] clk: en7523: Rework clock handling for different clock - numbers - -Airoha EN7581 SoC have additional clock compared to EN7523 but current -driver permits to only support up to EN7523 clock numbers. - -To handle this, rework the clock handling and permit to declare the -clocks number in match_data and alloca clk_data based on the compatible -match_data. - -Signed-off-by: Christian Marangi -Link: https://lore.kernel.org/r/20250113231030.6735-2-ansuelsmth@gmail.com -Signed-off-by: Stephen Boyd ---- - drivers/clk/clk-en7523.c | 14 ++++++++------ - 1 file changed, 8 insertions(+), 6 deletions(-) - ---- a/drivers/clk/clk-en7523.c -+++ b/drivers/clk/clk-en7523.c -@@ -75,6 +75,7 @@ struct en_rst_data { - }; - - struct en_clk_soc_data { -+ u32 num_clocks; - const struct clk_ops pcie_ops; - int (*hw_init)(struct platform_device *pdev, - struct clk_hw_onecell_data *clk_data); -@@ -503,8 +504,6 @@ static void en7523_register_clocks(struc - u32 rate; - int i; - -- clk_data->num = EN7523_NUM_CLOCKS; -- - for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) { - const struct en_clk_desc *desc = &en7523_base_clks[i]; - u32 reg = desc->div_reg ? desc->div_reg : desc->base_reg; -@@ -586,8 +585,6 @@ static void en7581_register_clocks(struc - - hw = en7523_register_pcie_clk(dev, base); - clk_data->hws[EN7523_CLK_PCIE] = hw; -- -- clk_data->num = EN7523_NUM_CLOCKS; - } - - static int en7523_reset_update(struct reset_controller_dev *rcdev, -@@ -701,13 +698,15 @@ static int en7523_clk_probe(struct platf - struct clk_hw_onecell_data *clk_data; - int r; - -+ soc_data = device_get_match_data(&pdev->dev); -+ - clk_data = devm_kzalloc(&pdev->dev, -- struct_size(clk_data, hws, EN7523_NUM_CLOCKS), -+ struct_size(clk_data, hws, soc_data->num_clocks), - GFP_KERNEL); - if (!clk_data) - return -ENOMEM; - -- soc_data = device_get_match_data(&pdev->dev); -+ clk_data->num = soc_data->num_clocks; - r = soc_data->hw_init(pdev, clk_data); - if (r) - return r; -@@ -716,6 +715,7 @@ static int en7523_clk_probe(struct platf - } - - static const struct en_clk_soc_data en7523_data = { -+ .num_clocks = ARRAY_SIZE(en7523_base_clks) + 1, - .pcie_ops = { - .is_enabled = en7523_pci_is_enabled, - .prepare = en7523_pci_prepare, -@@ -725,6 +725,8 @@ static const struct en_clk_soc_data en75 - }; - - static const struct en_clk_soc_data en7581_data = { -+ /* We increment num_clocks by 1 to account for additional PCIe clock */ -+ .num_clocks = ARRAY_SIZE(en7581_base_clks) + 1, - .pcie_ops = { - .is_enabled = en7581_pci_is_enabled, - .enable = en7581_pci_enable, diff --git a/target/linux/econet/patches-6.12/016-v6.14-clk-en7523-Add-clock-for-eMMC-for-EN7581.patch b/target/linux/econet/patches-6.12/016-v6.14-clk-en7523-Add-clock-for-eMMC-for-EN7581.patch deleted file mode 100644 index 35d34a5ccf..0000000000 --- a/target/linux/econet/patches-6.12/016-v6.14-clk-en7523-Add-clock-for-eMMC-for-EN7581.patch +++ /dev/null @@ -1,41 +0,0 @@ -From bfe257f9780d8f77045a7da6ec959ee0659d2f98 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Tue, 14 Jan 2025 00:10:05 +0100 -Subject: [PATCH 3/3] clk: en7523: Add clock for eMMC for EN7581 - -Add clock for eMMC for EN7581. This is used to give info of the current -eMMC source clock and to switch it from 200MHz or 150MHz. - -Signed-off-by: Christian Marangi -Link: https://lore.kernel.org/r/20250113231030.6735-5-ansuelsmth@gmail.com -Signed-off-by: Stephen Boyd ---- - drivers/clk/clk-en7523.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - ---- a/drivers/clk/clk-en7523.c -+++ b/drivers/clk/clk-en7523.c -@@ -91,6 +91,7 @@ static const u32 emi7581_base[] = { 5400 - static const u32 bus7581_base[] = { 600000000, 540000000 }; - static const u32 npu7581_base[] = { 800000000, 750000000, 720000000, 600000000 }; - static const u32 crypto_base[] = { 540000000, 480000000 }; -+static const u32 emmc7581_base[] = { 200000000, 150000000 }; - - static const struct en_clk_desc en7523_base_clks[] = { - { -@@ -281,6 +282,15 @@ static const struct en_clk_desc en7581_b - .base_shift = 0, - .base_values = crypto_base, - .n_base_values = ARRAY_SIZE(crypto_base), -+ }, { -+ .id = EN7581_CLK_EMMC, -+ .name = "emmc", -+ -+ .base_reg = REG_CRYPTO_CLKSRC2, -+ .base_bits = 1, -+ .base_shift = 12, -+ .base_values = emmc7581_base, -+ .n_base_values = ARRAY_SIZE(emmc7581_base), - } - }; - diff --git a/target/linux/econet/patches-6.12/019-v6.13-dt-bindings-clock-airoha-Update-reg-mapping-for-EN75.patch b/target/linux/econet/patches-6.12/019-v6.13-dt-bindings-clock-airoha-Update-reg-mapping-for-EN75.patch deleted file mode 100644 index a4af01dd20..0000000000 --- a/target/linux/econet/patches-6.12/019-v6.13-dt-bindings-clock-airoha-Update-reg-mapping-for-EN75.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 0f7c637d1103d79829dec198e5f1b678c1feb5f2 Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Tue, 12 Nov 2024 01:08:48 +0100 -Subject: [PATCH] dt-bindings: clock: airoha: Update reg mapping for EN7581 - SoC. - -clk-en7523 driver for EN7581 SoC is mapping all the scu memory region -while it is configuring the chip-scu one via a syscon. Update the reg -mapping definition for this device. This patch does not introduce any -backward incompatibility since the dts for EN7581 SoC is not upstream -yet. - -Signed-off-by: Lorenzo Bianconi -Link: https://lore.kernel.org/r/20241112-clk-en7581-syscon-v2-1-8ada5e394ae4@kernel.org -Reviewed-by: Rob Herring (Arm) -Signed-off-by: Stephen Boyd ---- - .../bindings/clock/airoha,en7523-scu.yaml | 23 +++++++------------ - 1 file changed, 8 insertions(+), 15 deletions(-) - ---- a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml -+++ b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml -@@ -34,8 +34,10 @@ properties: - - airoha,en7581-scu - - reg: -- minItems: 2 -- maxItems: 4 -+ items: -+ - description: scu base address -+ - description: misc scu base address -+ minItems: 1 - - "#clock-cells": - description: -@@ -60,9 +62,7 @@ allOf: - then: - properties: - reg: -- items: -- - description: scu base address -- - description: misc scu base address -+ minItems: 2 - - - if: - properties: -@@ -71,11 +71,7 @@ allOf: - then: - properties: - reg: -- items: -- - description: scu base address -- - description: misc scu base address -- - description: reset base address -- - description: pb scu base address -+ maxItems: 1 - - additionalProperties: false - -@@ -95,12 +91,9 @@ examples: - #address-cells = <2>; - #size-cells = <2>; - -- scuclk: clock-controller@1fa20000 { -+ scuclk: clock-controller@1fb00000 { - compatible = "airoha,en7581-scu"; -- reg = <0x0 0x1fa20000 0x0 0x400>, -- <0x0 0x1fb00000 0x0 0x90>, -- <0x0 0x1fb00830 0x0 0x8>, -- <0x0 0x1fbe3400 0x0 0xfc>; -+ reg = <0x0 0x1fb00000 0x0 0x970>; - #clock-cells = <1>; - #reset-cells = <1>; - }; diff --git a/target/linux/econet/patches-6.12/021-v6.14-dt-bindings-clock-drop-NUM_CLOCKS-define-for-EN7581.patch b/target/linux/econet/patches-6.12/021-v6.14-dt-bindings-clock-drop-NUM_CLOCKS-define-for-EN7581.patch deleted file mode 100644 index a6594ebac8..0000000000 --- a/target/linux/econet/patches-6.12/021-v6.14-dt-bindings-clock-drop-NUM_CLOCKS-define-for-EN7581.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 02d3b7557ce28c373ea1e925ae16ab5988284313 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Tue, 14 Jan 2025 00:10:03 +0100 -Subject: [PATCH 1/2] dt-bindings: clock: drop NUM_CLOCKS define for EN7581 - -Drop NUM_CLOCKS define for EN7581 include. This is not a binding and -should not be placed here. Value is derived internally in the user -driver. - -Signed-off-by: Christian Marangi -Acked-by: Krzysztof Kozlowski -Link: https://lore.kernel.org/r/20250113231030.6735-3-ansuelsmth@gmail.com -Signed-off-by: Stephen Boyd ---- - include/dt-bindings/clock/en7523-clk.h | 2 -- - 1 file changed, 2 deletions(-) - ---- a/include/dt-bindings/clock/en7523-clk.h -+++ b/include/dt-bindings/clock/en7523-clk.h -@@ -12,6 +12,4 @@ - #define EN7523_CLK_CRYPTO 6 - #define EN7523_CLK_PCIE 7 - --#define EN7523_NUM_CLOCKS 8 -- - #endif /* _DT_BINDINGS_CLOCK_AIROHA_EN7523_H_ */ diff --git a/target/linux/econet/patches-6.12/022-v6.14-dt-bindings-clock-add-ID-for-eMMC-for-EN7581.patch b/target/linux/econet/patches-6.12/022-v6.14-dt-bindings-clock-add-ID-for-eMMC-for-EN7581.patch deleted file mode 100644 index f500a79808..0000000000 --- a/target/linux/econet/patches-6.12/022-v6.14-dt-bindings-clock-add-ID-for-eMMC-for-EN7581.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 82108ad3285f58f314ad41398f44017c7dbe44de Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Tue, 14 Jan 2025 00:10:04 +0100 -Subject: [PATCH 2/2] dt-bindings: clock: add ID for eMMC for EN7581 - -Add ID for eMMC for EN7581. This is to control clock selection of eMMC -between 200MHz and 150MHz. - -Signed-off-by: Christian Marangi -Acked-by: Conor Dooley -Link: https://lore.kernel.org/r/20250113231030.6735-4-ansuelsmth@gmail.com -Signed-off-by: Stephen Boyd ---- - include/dt-bindings/clock/en7523-clk.h | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/include/dt-bindings/clock/en7523-clk.h -+++ b/include/dt-bindings/clock/en7523-clk.h -@@ -12,4 +12,6 @@ - #define EN7523_CLK_CRYPTO 6 - #define EN7523_CLK_PCIE 7 - -+#define EN7581_CLK_EMMC 8 -+ - #endif /* _DT_BINDINGS_CLOCK_AIROHA_EN7523_H_ */ diff --git a/target/linux/econet/patches-6.12/913-pcie-fix-bogus-prefetch-window.patch b/target/linux/econet/patches-6.12/913-pcie-fix-bogus-prefetch-window.patch deleted file mode 100644 index 872843549d..0000000000 --- a/target/linux/econet/patches-6.12/913-pcie-fix-bogus-prefetch-window.patch +++ /dev/null @@ -1,38 +0,0 @@ -Subject: [PATCH] PCI: Skip bridge window reads when window is not supported - -pci_read_bridge_io() and pci_read_bridge_mmio_pref() read bridge window -registers unconditionally. If the registers are hardwired to zero -(not implemented), both base and limit will be 0. Since (0 <= 0) is -true, a bogus window [mem 0x00000000-0x000fffff] or [io 0x0000-0x0fff] -gets created. - -pci_read_bridge_windows() already detects unsupported windows by -testing register writability and sets io_window/pref_window flags -accordingly. Check these flags at the start of pci_read_bridge_io() -and pci_read_bridge_mmio_pref() to skip reading registers when the -window is not supported. - -Suggested-by: Bjorn Helgaas -Signed-off-by: Ahmed Naseef ---- a/drivers/pci/probe.c -+++ b/drivers/pci/probe.c -@@ -349,6 +349,9 @@ static void pci_read_bridge_io(struct pc - unsigned long io_mask, io_granularity, base, limit; - struct pci_bus_region region; - -+ if (!dev->io_window) -+ return; -+ - io_mask = PCI_IO_RANGE_MASK; - io_granularity = 0x1000; - if (dev->io_window_1k) { -@@ -410,6 +413,9 @@ static void pci_read_bridge_mmio_pref(st - pci_bus_addr_t base, limit; - struct pci_bus_region region; - -+ if (!dev->pref_window) -+ return; -+ - pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo); - pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo); - base64 = (mem_base_lo & PCI_PREF_RANGE_MASK) << 16; diff --git a/target/linux/econet/patches-6.12/017-v6.19rc1-clk-en7523-Add-reset-controller-support-for-EN7523-S.patch b/target/linux/econet/patches-6.18/017-v6.19rc1-clk-en7523-Add-reset-controller-support-for-EN7523-S.patch similarity index 100% rename from target/linux/econet/patches-6.12/017-v6.19rc1-clk-en7523-Add-reset-controller-support-for-EN7523-S.patch rename to target/linux/econet/patches-6.18/017-v6.19rc1-clk-en7523-Add-reset-controller-support-for-EN7523-S.patch diff --git a/target/linux/econet/patches-6.12/018-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch b/target/linux/econet/patches-6.18/018-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch similarity index 89% rename from target/linux/econet/patches-6.12/018-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch rename to target/linux/econet/patches-6.18/018-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch index ef56753c9b..cf8041c111 100644 --- a/target/linux/econet/patches-6.12/018-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch +++ b/target/linux/econet/patches-6.18/018-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch @@ -17,15 +17,15 @@ Signed-off-by: Stephen Boyd --- a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml +++ b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml @@ -64,8 +64,6 @@ allOf: - - description: scu base address - - description: misc scu base address + reg: + minItems: 2 - '#reset-cells': false - - if: properties: compatible: -@@ -89,6 +87,7 @@ examples: +@@ -85,6 +83,7 @@ examples: reg = <0x1fa20000 0x400>, <0x1fb00000 0x1000>; #clock-cells = <1>; diff --git a/target/linux/econet/patches-6.12/020-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch b/target/linux/econet/patches-6.18/020-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch similarity index 100% rename from target/linux/econet/patches-6.12/020-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch rename to target/linux/econet/patches-6.18/020-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch diff --git a/target/linux/econet/patches-6.12/029-05-v6.19-spi-airoha-remove-unnecessary-restriction-length.patch b/target/linux/econet/patches-6.18/029-05-v6.19-spi-airoha-remove-unnecessary-restriction-length.patch similarity index 100% rename from target/linux/econet/patches-6.12/029-05-v6.19-spi-airoha-remove-unnecessary-restriction-length.patch rename to target/linux/econet/patches-6.18/029-05-v6.19-spi-airoha-remove-unnecessary-restriction-length.patch diff --git a/target/linux/econet/patches-6.12/029-06-v6.19-spi-airoha-remove-unnecessary-switch-to-non-dma-mode.patch b/target/linux/econet/patches-6.18/029-06-v6.19-spi-airoha-remove-unnecessary-switch-to-non-dma-mode.patch similarity index 100% rename from target/linux/econet/patches-6.12/029-06-v6.19-spi-airoha-remove-unnecessary-switch-to-non-dma-mode.patch rename to target/linux/econet/patches-6.18/029-06-v6.19-spi-airoha-remove-unnecessary-switch-to-non-dma-mode.patch diff --git a/target/linux/econet/patches-6.12/029-07-v6.19-spi-airoha-unify-dirmap-read-write-code.patch b/target/linux/econet/patches-6.18/029-07-v6.19-spi-airoha-unify-dirmap-read-write-code.patch similarity index 100% rename from target/linux/econet/patches-6.12/029-07-v6.19-spi-airoha-unify-dirmap-read-write-code.patch rename to target/linux/econet/patches-6.18/029-07-v6.19-spi-airoha-unify-dirmap-read-write-code.patch diff --git a/target/linux/econet/patches-6.12/029-08-v6.19-spi-airoha-support-of-dualio-quadio-flash-reading-co.patch b/target/linux/econet/patches-6.18/029-08-v6.19-spi-airoha-support-of-dualio-quadio-flash-reading-co.patch similarity index 100% rename from target/linux/econet/patches-6.12/029-08-v6.19-spi-airoha-support-of-dualio-quadio-flash-reading-co.patch rename to target/linux/econet/patches-6.18/029-08-v6.19-spi-airoha-support-of-dualio-quadio-flash-reading-co.patch diff --git a/target/linux/econet/patches-6.12/029-09-v6.19-spi-airoha-avoid-setting-of-page-oob-sizes-in-REG_SP.patch b/target/linux/econet/patches-6.18/029-09-v6.19-spi-airoha-avoid-setting-of-page-oob-sizes-in-REG_SP.patch similarity index 100% rename from target/linux/econet/patches-6.12/029-09-v6.19-spi-airoha-avoid-setting-of-page-oob-sizes-in-REG_SP.patch rename to target/linux/econet/patches-6.18/029-09-v6.19-spi-airoha-avoid-setting-of-page-oob-sizes-in-REG_SP.patch diff --git a/target/linux/econet/patches-6.12/029-10-v6.19-spi-airoha-reduce-the-number-of-modification-of-REG_.patch b/target/linux/econet/patches-6.18/029-10-v6.19-spi-airoha-reduce-the-number-of-modification-of-REG_.patch similarity index 100% rename from target/linux/econet/patches-6.12/029-10-v6.19-spi-airoha-reduce-the-number-of-modification-of-REG_.patch rename to target/linux/econet/patches-6.18/029-10-v6.19-spi-airoha-reduce-the-number-of-modification-of-REG_.patch diff --git a/target/linux/econet/patches-6.12/029-11-v6.19-spi-airoha-set-custom-sector-size-equal-to-flash-pag.patch b/target/linux/econet/patches-6.18/029-11-v6.19-spi-airoha-set-custom-sector-size-equal-to-flash-pag.patch similarity index 100% rename from target/linux/econet/patches-6.12/029-11-v6.19-spi-airoha-set-custom-sector-size-equal-to-flash-pag.patch rename to target/linux/econet/patches-6.18/029-11-v6.19-spi-airoha-set-custom-sector-size-equal-to-flash-pag.patch diff --git a/target/linux/econet/patches-6.12/029-12-v6.19-spi-airoha-avoid-reading-flash-page-settings-from-SN.patch b/target/linux/econet/patches-6.18/029-12-v6.19-spi-airoha-avoid-reading-flash-page-settings-from-SN.patch similarity index 100% rename from target/linux/econet/patches-6.12/029-12-v6.19-spi-airoha-avoid-reading-flash-page-settings-from-SN.patch rename to target/linux/econet/patches-6.18/029-12-v6.19-spi-airoha-avoid-reading-flash-page-settings-from-SN.patch diff --git a/target/linux/econet/patches-6.12/029-13-v6.19-spi-airoha-buffer-must-be-0xff-ed-before-writing.patch b/target/linux/econet/patches-6.18/029-13-v6.19-spi-airoha-buffer-must-be-0xff-ed-before-writing.patch similarity index 100% rename from target/linux/econet/patches-6.12/029-13-v6.19-spi-airoha-buffer-must-be-0xff-ed-before-writing.patch rename to target/linux/econet/patches-6.18/029-13-v6.19-spi-airoha-buffer-must-be-0xff-ed-before-writing.patch diff --git a/target/linux/econet/patches-6.12/100-econet-add-en7528-soc.patch b/target/linux/econet/patches-6.18/100-econet-add-en7528-soc.patch similarity index 98% rename from target/linux/econet/patches-6.12/100-econet-add-en7528-soc.patch rename to target/linux/econet/patches-6.18/100-econet-add-en7528-soc.patch index f11c6d329d..edff2c57a6 100644 --- a/target/linux/econet/patches-6.12/100-econet-add-en7528-soc.patch +++ b/target/linux/econet/patches-6.18/100-econet-add-en7528-soc.patch @@ -14,7 +14,7 @@ This adds boot support for the EN7528 SoC family: Signed-off-by: Ahmed Naseef --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig -@@ -391,13 +391,13 @@ config MACH_DECSTATION +@@ -392,13 +392,13 @@ config MACH_DECSTATION config ECONET bool "EcoNet MIPS family" select BOOT_RAW diff --git a/target/linux/econet/patches-6.12/101-econet-timer-add-en7528-support.patch b/target/linux/econet/patches-6.18/101-econet-timer-add-en7528-support.patch similarity index 99% rename from target/linux/econet/patches-6.12/101-econet-timer-add-en7528-support.patch rename to target/linux/econet/patches-6.18/101-econet-timer-add-en7528-support.patch index 3d86414591..f0d6ec59a6 100644 --- a/target/linux/econet/patches-6.12/101-econet-timer-add-en7528-support.patch +++ b/target/linux/econet/patches-6.18/101-econet-timer-add-en7528-support.patch @@ -120,7 +120,7 @@ Signed-off-by: Ahmed Naseef for_each_possible_cpu(i) { struct clock_event_device *cd = &per_cpu(econet_timer_pcpu, i); -- cd->rating = 310, +- cd->rating = 310; - cd->features = CLOCK_EVT_FEAT_ONESHOT | - CLOCK_EVT_FEAT_C3STOP | - CLOCK_EVT_FEAT_PERCPU; diff --git a/target/linux/econet/patches-6.12/300-spi-Add-support-for-the-Airoha-EN7523-SoC-SPI-contro.patch b/target/linux/econet/patches-6.18/300-spi-Add-support-for-the-Airoha-EN7523-SoC-SPI-contro.patch similarity index 98% rename from target/linux/econet/patches-6.12/300-spi-Add-support-for-the-Airoha-EN7523-SoC-SPI-contro.patch rename to target/linux/econet/patches-6.18/300-spi-Add-support-for-the-Airoha-EN7523-SoC-SPI-contro.patch index d3f3054fe7..a312ff0ad6 100644 --- a/target/linux/econet/patches-6.12/300-spi-Add-support-for-the-Airoha-EN7523-SoC-SPI-contro.patch +++ b/target/linux/econet/patches-6.18/300-spi-Add-support-for-the-Airoha-EN7523-SoC-SPI-contro.patch @@ -1,6 +1,6 @@ --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig -@@ -370,6 +370,12 @@ config SPI_DLN2 +@@ -404,6 +404,12 @@ config SPI_DLN2 This driver can also be built as a module. If so, the module will be called spi-dln2. @@ -15,7 +15,7 @@ depends on ARCH_EP93XX || COMPILE_TEST --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile -@@ -52,6 +52,7 @@ obj-$(CONFIG_SPI_DW_BT1) += spi-dw-bt1. +@@ -56,6 +56,7 @@ obj-$(CONFIG_SPI_DW_BT1) += spi-dw-bt1. obj-$(CONFIG_SPI_DW_MMIO) += spi-dw-mmio.o obj-$(CONFIG_SPI_DW_PCI) += spi-dw-pci.o obj-$(CONFIG_SPI_EP93XX) += spi-ep93xx.o @@ -292,7 +292,7 @@ + struct spi_controller *ctrl; + int err; + -+ ctrl = devm_spi_alloc_master(&pdev->dev, 0); ++ ctrl = devm_spi_alloc_host(&pdev->dev, 0); + if (!ctrl) { + dev_err(&pdev->dev, "Error allocating SPI controller\n"); + return -ENOMEM; diff --git a/target/linux/econet/patches-6.12/301-spi-Airoha-adapt-to-support-en75-mips.patch b/target/linux/econet/patches-6.18/301-spi-Airoha-adapt-to-support-en75-mips.patch similarity index 97% rename from target/linux/econet/patches-6.12/301-spi-Airoha-adapt-to-support-en75-mips.patch rename to target/linux/econet/patches-6.18/301-spi-Airoha-adapt-to-support-en75-mips.patch index 888df7552e..12d511466a 100644 --- a/target/linux/econet/patches-6.12/301-spi-Airoha-adapt-to-support-en75-mips.patch +++ b/target/linux/econet/patches-6.18/301-spi-Airoha-adapt-to-support-en75-mips.patch @@ -12,7 +12,7 @@ Signed-off-by: Caleb James DeLisle --- --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig -@@ -372,7 +372,7 @@ config SPI_DLN2 +@@ -406,7 +406,7 @@ config SPI_DLN2 config SPI_AIROHA_EN7523 bool "Airoha EN7523 SPI controller support" diff --git a/target/linux/econet/patches-6.12/303-spi-airoha-snfi-enable-for-econet.patch b/target/linux/econet/patches-6.18/303-spi-airoha-snfi-enable-for-econet.patch similarity index 92% rename from target/linux/econet/patches-6.12/303-spi-airoha-snfi-enable-for-econet.patch rename to target/linux/econet/patches-6.18/303-spi-airoha-snfi-enable-for-econet.patch index 8556633d01..ec80c11804 100644 --- a/target/linux/econet/patches-6.12/303-spi-airoha-snfi-enable-for-econet.patch +++ b/target/linux/econet/patches-6.18/303-spi-airoha-snfi-enable-for-econet.patch @@ -10,7 +10,7 @@ performance compared to the manual mode spi-en7523 driver. Signed-off-by: Ahmed Naseef --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig -@@ -59,7 +59,7 @@ comment "SPI Master Controller Drivers" +@@ -62,7 +62,7 @@ comment "SPI Master Controller Drivers" config SPI_AIROHA_SNFI tristate "Airoha SPI NAND Flash Interface" diff --git a/target/linux/econet/patches-6.12/310-usb-enable-econet-usb.patch b/target/linux/econet/patches-6.18/310-usb-enable-econet-usb.patch similarity index 93% rename from target/linux/econet/patches-6.12/310-usb-enable-econet-usb.patch rename to target/linux/econet/patches-6.18/310-usb-enable-econet-usb.patch index a550bbfae5..a81f957ceb 100644 --- a/target/linux/econet/patches-6.12/310-usb-enable-econet-usb.patch +++ b/target/linux/econet/patches-6.18/310-usb-enable-econet-usb.patch @@ -1,6 +1,6 @@ --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig -@@ -391,6 +391,7 @@ config MACH_DECSTATION +@@ -392,6 +392,7 @@ config MACH_DECSTATION config ECONET bool "EcoNet MIPS family" select BOOT_RAW diff --git a/target/linux/econet/patches-6.12/320-gpio-en7523-enable-for-econet-mips.patch b/target/linux/econet/patches-6.18/320-gpio-en7523-enable-for-econet-mips.patch similarity index 92% rename from target/linux/econet/patches-6.12/320-gpio-en7523-enable-for-econet-mips.patch rename to target/linux/econet/patches-6.18/320-gpio-en7523-enable-for-econet-mips.patch index 09e86ff5c9..307b5c0b79 100644 --- a/target/linux/econet/patches-6.12/320-gpio-en7523-enable-for-econet-mips.patch +++ b/target/linux/econet/patches-6.18/320-gpio-en7523-enable-for-econet-mips.patch @@ -6,7 +6,7 @@ MIPS SoC. Allow building the driver when ECONET is selected. Signed-off-by: Ahmed Naseef --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig -@@ -271,7 +271,7 @@ config GPIO_EM +@@ -293,7 +293,7 @@ config GPIO_EM config GPIO_EN7523 tristate "Airoha GPIO support" diff --git a/target/linux/econet/patches-6.12/886-uart-add-en7523-support.patch b/target/linux/econet/patches-6.18/886-uart-add-en7523-support.patch similarity index 90% rename from target/linux/econet/patches-6.12/886-uart-add-en7523-support.patch rename to target/linux/econet/patches-6.18/886-uart-add-en7523-support.patch index 486208f71a..8d691ce0ec 100644 --- a/target/linux/econet/patches-6.12/886-uart-add-en7523-support.patch +++ b/target/linux/econet/patches-6.18/886-uart-add-en7523-support.patch @@ -97,7 +97,7 @@ +EXPORT_SYMBOL_GPL(en7523_set_uart_baud_rate); --- a/drivers/tty/serial/8250/8250_of.c +++ b/drivers/tty/serial/8250/8250_of.c -@@ -341,6 +341,7 @@ static const struct of_device_id of_plat +@@ -353,6 +353,7 @@ static const struct of_device_id of_plat { .compatible = "ti,da830-uart", .data = (void *)PORT_DA830, }, { .compatible = "nuvoton,wpcm450-uart", .data = (void *)PORT_NPCM, }, { .compatible = "nuvoton,npcm750-uart", .data = (void *)PORT_NPCM, }, @@ -107,7 +107,7 @@ MODULE_DEVICE_TABLE(of, of_platform_serial_table); --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c -@@ -319,6 +319,14 @@ static const struct serial8250_config ua +@@ -311,6 +311,14 @@ static const struct serial8250_config ua .rxtrig_bytes = {1, 8, 16, 30}, .flags = UART_CAP_FIFO | UART_CAP_AFE, }, @@ -122,22 +122,21 @@ }; /* Uart divisor latch read */ -@@ -2841,6 +2849,12 @@ serial8250_do_set_termios(struct uart_po - - serial8250_set_divisor(port, baud, quot, frac); - +@@ -2785,6 +2793,11 @@ serial8250_do_set_termios(struct uart_po + serial8250_set_ier(port, termios); + serial8250_set_efr(port, termios); + serial8250_set_divisor(port, baud, quot, frac); +#ifdef CONFIG_SERIAL_8250_AIROHA -+ /* Airoha SoCs have custom registers for baud rate settings */ -+ if (port->type == PORT_AIROHA) -+ en7523_set_uart_baud_rate(port, baud); ++ /* Airoha SoCs have custom registers for baud rate settings */ ++ if (port->type == PORT_AIROHA) ++ en7523_set_uart_baud_rate(port, baud); +#endif -+ - /* - * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR - * is written without DLAB set, this mode will be disabled. + serial8250_set_fcr(port, termios); + serial8250_set_mctrl(port, port->mctrl); + } --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig -@@ -355,6 +355,16 @@ config SERIAL_8250_ACORN +@@ -356,6 +356,16 @@ config SERIAL_8250_ACORN system, say Y to this option. The driver can handle 1, 2, or 3 port cards. If unsure, say N. @@ -201,6 +200,6 @@ unsigned int quot); int fsl8250_handle_irq(struct uart_port *port); +int en7523_set_uart_baud_rate(struct uart_port *port, unsigned int baud); + void serial8250_handle_irq_locked(struct uart_port *port, unsigned int iir); int serial8250_handle_irq(struct uart_port *port, unsigned int iir); u16 serial8250_rx_chars(struct uart_8250_port *up, u16 lsr); - void serial8250_read_char(struct uart_8250_port *up, u16 lsr); diff --git a/target/linux/econet/patches-6.12/887-uart-airoha-add-econet-support.patch b/target/linux/econet/patches-6.18/887-uart-airoha-add-econet-support.patch similarity index 93% rename from target/linux/econet/patches-6.12/887-uart-airoha-add-econet-support.patch rename to target/linux/econet/patches-6.18/887-uart-airoha-add-econet-support.patch index b25d02e969..560b020ab6 100644 --- a/target/linux/econet/patches-6.12/887-uart-airoha-add-econet-support.patch +++ b/target/linux/econet/patches-6.18/887-uart-airoha-add-econet-support.patch @@ -7,7 +7,7 @@ the Airoha UART driver for EcoNet platforms. Signed-off-by: Ahmed Naseef --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig -@@ -357,7 +357,7 @@ config SERIAL_8250_ACORN +@@ -358,7 +358,7 @@ config SERIAL_8250_ACORN config SERIAL_8250_AIROHA tristate "Airoha UART support" diff --git a/target/linux/econet/patches-6.12/901-nand-enable-en75-bbt.patch b/target/linux/econet/patches-6.18/901-nand-enable-en75-bbt.patch similarity index 96% rename from target/linux/econet/patches-6.12/901-nand-enable-en75-bbt.patch rename to target/linux/econet/patches-6.18/901-nand-enable-en75-bbt.patch index 91e184bd96..569e37d736 100644 --- a/target/linux/econet/patches-6.12/901-nand-enable-en75-bbt.patch +++ b/target/linux/econet/patches-6.18/901-nand-enable-en75-bbt.patch @@ -14,9 +14,9 @@ Signed-off-by: Caleb James DeLisle obj-$(CONFIG_MTD_NAND_ECC_MEDIATEK) += ecc-mtk.o -obj-$(CONFIG_MTD_NAND_MTK_BMT) += mtk_bmt.o mtk_bmt_v2.o mtk_bmt_bbt.o mtk_bmt_nmbm.o +obj-$(CONFIG_MTD_NAND_MTK_BMT) += mtk_bmt.o mtk_bmt_v2.o mtk_bmt_bbt.o mtk_bmt_nmbm.o en75_bmt.o + obj-$(CONFIG_MTD_NAND_ECC_REALTEK) += ecc-realtek.o obj-$(CONFIG_SPI_QPIC_SNAND) += qpic_common.o obj-$(CONFIG_MTD_NAND_QCOM) += qpic_common.o - obj-y += onenand/ --- a/drivers/mtd/nand/mtk_bmt.h +++ b/drivers/mtd/nand/mtk_bmt.h @@ -77,6 +77,7 @@ extern struct bmt_desc bmtd; diff --git a/target/linux/econet/patches-6.12/902-snand-mtk-bmt-support.patch b/target/linux/econet/patches-6.18/902-snand-mtk-bmt-support.patch similarity index 66% rename from target/linux/econet/patches-6.12/902-snand-mtk-bmt-support.patch rename to target/linux/econet/patches-6.18/902-snand-mtk-bmt-support.patch index 2dc81292ec..804542b9f5 100644 --- a/target/linux/econet/patches-6.12/902-snand-mtk-bmt-support.patch +++ b/target/linux/econet/patches-6.18/902-snand-mtk-bmt-support.patch @@ -6,9 +6,9 @@ #include +#include - static int spinand_read_reg_op(struct spinand_device *spinand, u8 reg, u8 *val) + int spinand_read_reg_op(struct spinand_device *spinand, u8 reg, u8 *val) { -@@ -1604,6 +1605,7 @@ static int spinand_probe(struct spi_mem +@@ -1718,6 +1719,7 @@ static int spinand_probe(struct spi_mem if (ret) return ret; @@ -16,7 +16,7 @@ ret = mtd_device_register(mtd, NULL, 0); if (ret) goto err_spinand_cleanup; -@@ -1611,6 +1613,7 @@ static int spinand_probe(struct spi_mem +@@ -1725,6 +1727,7 @@ static int spinand_probe(struct spi_mem return 0; err_spinand_cleanup: @@ -24,7 +24,7 @@ spinand_cleanup(spinand); return ret; -@@ -1629,6 +1632,7 @@ static int spinand_remove(struct spi_mem +@@ -1743,6 +1746,7 @@ static int spinand_remove(struct spi_mem if (ret) return ret; diff --git a/target/linux/econet/patches-6.12/910-dt-bindings-clock-reset-add-econet-en751221-bindings.patch b/target/linux/econet/patches-6.18/910-v7.1-dt-bindings-clock-reset-add-econet-en751221-bindings.patch similarity index 55% rename from target/linux/econet/patches-6.12/910-dt-bindings-clock-reset-add-econet-en751221-bindings.patch rename to target/linux/econet/patches-6.18/910-v7.1-dt-bindings-clock-reset-add-econet-en751221-bindings.patch index 37dc36cacc..e2780081cb 100644 --- a/target/linux/econet/patches-6.12/910-dt-bindings-clock-reset-add-econet-en751221-bindings.patch +++ b/target/linux/econet/patches-6.18/910-v7.1-dt-bindings-clock-reset-add-econet-en751221-bindings.patch @@ -1,22 +1,23 @@ -From f3fa5911b1f094e164c497f7b10d94d92852e285 Mon Sep 17 00:00:00 2001 +From 35af99f7482673bf5f5391fd33caf266f4f62aeb Mon Sep 17 00:00:00 2001 From: Caleb James DeLisle -Date: Wed, 14 Jan 2026 17:54:05 +0000 -Subject: [PATCH] dt-bindings: clock, reset: Add econet EN751221 bindings +Date: Thu, 12 Mar 2026 16:24:48 +0000 +Subject: [PATCH] dt-bindings: clock, reset: Add econet EN751221 -Add clock and reset bindings for EN751221 based on the Airoha EN7523 SCU -driver. +Add clock and reset bindings for EN751221 as well as a "chip-scu" which is +an additional regmap that is used by the clock driver as well as others. +This split of the SCU across two register areas is the same as the Airoha +AN758x family. Signed-off-by: Caleb James DeLisle +Reviewed-by: Rob Herring (Arm) +Signed-off-by: Stephen Boyd --- -The EN751221 has the same bifurcation of SCU as EN7581 so we use -the same chip-scu as airoha,en7581-chip-scu. ---- - .../bindings/clock/airoha,en7523-scu.yaml | 17 +++++++- - .../mips/econet,en751221-chip-scu.yaml | 42 +++++++++++++++++++ - .../dt-bindings/clock/econet,en751221-scu.h | 14 +++++++ - .../dt-bindings/reset/econet,en751221-scu.h | 41 ++++++++++++++++++ - 4 files changed, 113 insertions(+), 1 deletion(-) - create mode 100644 Documentation/devicetree/bindings/mips/econet,en751221-chip-scu.yaml + .../bindings/clock/airoha,en7523-scu.yaml | 6 ++- + .../devicetree/bindings/mfd/syscon.yaml | 2 + + MAINTAINERS | 2 + + .../dt-bindings/clock/econet,en751221-scu.h | 12 +++++ + .../dt-bindings/reset/econet,en751221-scu.h | 49 +++++++++++++++++++ + 5 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 include/dt-bindings/clock/econet,en751221-scu.h create mode 100644 include/dt-bindings/reset/econet,en751221-scu.h @@ -30,82 +31,54 @@ the same chip-scu as airoha,en7581-chip-scu. reg: items: -@@ -67,7 +68,10 @@ allOf: +@@ -67,7 +68,9 @@ allOf: - if: properties: compatible: - const: airoha,en7581-scu -+ items: -+ - enum: -+ - airoha,en7581-scu -+ - econet,en751221-scu ++ enum: ++ - airoha,en7581-scu ++ - econet,en751221-scu then: properties: reg: -@@ -98,3 +102,14 @@ examples: +@@ -98,3 +101,4 @@ examples: #reset-cells = <1>; }; }; + -+ - | -+ soc { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ scuclk: clock-controller@1fb00000 { -+ compatible = "econet,en751221-scu"; -+ reg = <0x1fb00000 0x970>; -+ }; -+ }; -\ No newline at end of file ---- /dev/null -+++ b/Documentation/devicetree/bindings/mips/econet,en751221-chip-scu.yaml -@@ -0,0 +1,42 @@ -+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/arm/airoha,en7581-chip-scu.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: EcoNet Chip SCU Controller for EN751221 SoC -+ -+maintainers: -+ - Caleb James DeLisle -+ -+description: -+ The EcoNet chip-scu block provides a configuration interface for clock, -+ io-muxing and other functionalities used by multiple controllers (e.g. clock, -+ pinctrl, ecc) on EN751221 SoC. -+ -+properties: -+ compatible: -+ items: -+ - enum: +--- a/Documentation/devicetree/bindings/mfd/syscon.yaml ++++ b/Documentation/devicetree/bindings/mfd/syscon.yaml +@@ -61,6 +61,7 @@ select: + - cirrus,ep7209-syscon2 + - cirrus,ep7209-syscon3 + - cnxt,cx92755-uc + - econet,en751221-chip-scu -+ - const: syscon -+ -+ reg: -+ maxItems: 1 -+ -+required: -+ - compatible -+ - reg -+ -+additionalProperties: false -+ -+examples: -+ - | -+ soc { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ syscon@1fa20000 { -+ compatible = "econet,en751221-chip-scu", "syscon"; -+ reg = <0x1fa20000 0x388>; -+ }; -+ }; + - freecom,fsg-cs2-system-controller + - fsl,imx93-aonmix-ns-syscfg + - fsl,imx93-wakeupmix-syscfg +@@ -169,6 +170,7 @@ properties: + - cirrus,ep7209-syscon2 + - cirrus,ep7209-syscon3 + - cnxt,cx92755-uc ++ - econet,en751221-chip-scu + - freecom,fsg-cs2-system-controller + - fsl,imx93-aonmix-ns-syscfg + - fsl,imx93-wakeupmix-syscfg +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -8839,6 +8839,8 @@ F: arch/mips/boot/dts/econet/ + F: arch/mips/econet/ + F: drivers/clocksource/timer-econet-en751221.c + F: drivers/irqchip/irq-econet-en751221.c ++F: include/dt-bindings/clock/econet,en751221-scu.h ++F: include/dt-bindings/reset/econet,en751221-scu.h + + ECRYPT FILE SYSTEM + M: Tyler Hicks --- /dev/null +++ b/include/dt-bindings/clock/econet,en751221-scu.h -@@ -0,0 +1,15 @@ +@@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ + +#ifndef _DT_BINDINGS_CLOCK_ECONET_EN751221_SCU_H_ @@ -115,13 +88,9 @@ the same chip-scu as airoha,en7581-chip-scu. +#define EN751221_CLK_SPI 1 +#define EN751221_CLK_BUS 2 +#define EN751221_CLK_CPU 3 -+#define EN751221_CLK_HPT 4 -+#define EN751221_CLK_GSW 5 -+ -+#define EN751221_MAX_CLKS 6 ++#define EN751221_CLK_GSW 4 + +#endif /* _DT_BINDINGS_CLOCK_ECONET_EN751221_SCU_H_ */ -\ No newline at end of file --- /dev/null +++ b/include/dt-bindings/reset/econet,en751221-scu.h @@ -0,0 +1,49 @@ diff --git a/target/linux/econet/patches-6.12/911-clk-airoha-add-econet-en751221-clock-reset-support-t.patch b/target/linux/econet/patches-6.18/911-v7.1-clk-airoha-add-econet-en751221-clock-reset-support-t.patch similarity index 87% rename from target/linux/econet/patches-6.12/911-clk-airoha-add-econet-en751221-clock-reset-support-t.patch rename to target/linux/econet/patches-6.18/911-v7.1-clk-airoha-add-econet-en751221-clock-reset-support-t.patch index 021043a13d..4630e7eed1 100644 --- a/target/linux/econet/patches-6.12/911-clk-airoha-add-econet-en751221-clock-reset-support-t.patch +++ b/target/linux/econet/patches-6.18/911-v7.1-clk-airoha-add-econet-en751221-clock-reset-support-t.patch @@ -1,6 +1,6 @@ -From 1dfb29374a040ba80d378b3465f4e0bcb67f4ba3 Mon Sep 17 00:00:00 2001 +From d8b034525fd9541f23c5a3c54cd1dbe716570e97 Mon Sep 17 00:00:00 2001 From: Caleb James DeLisle -Date: Wed, 14 Jan 2026 18:06:13 +0000 +Date: Thu, 12 Mar 2026 16:24:49 +0000 Subject: [PATCH] clk: airoha: Add econet EN751221 clock/reset support to en7523-scu @@ -11,14 +11,16 @@ each clock is derived differently. This clock driver will probably work correctly on EN751627, EN7528, and EN7580. Signed-off-by: Caleb James DeLisle +Reviewed-by: Brian Masney +Signed-off-by: Stephen Boyd --- drivers/clk/Kconfig | 6 +- - drivers/clk/clk-en7523.c | 182 +++++++++++++++++++++++++++++++++++++++ - 2 files changed, 185 insertions(+), 3 deletions(-) + drivers/clk/clk-en7523.c | 223 ++++++++++++++++++++++++++++++++++++++- + 2 files changed, 221 insertions(+), 8 deletions(-) --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig -@@ -210,13 +210,13 @@ config COMMON_CLK_CS2000_CP +@@ -218,13 +218,13 @@ config COMMON_CLK_CS2000_CP If you say yes here you get support for the CS2000 clock multiplier. config COMMON_CLK_EN7523 @@ -53,7 +55,7 @@ Signed-off-by: Caleb James DeLisle #define RST_NR_PER_BANK 32 -@@ -33,15 +36,47 @@ +@@ -33,15 +36,50 @@ #define REG_RESET_CONTROL_PCIEHB BIT(29) #define REG_RESET_CONTROL_PCIE1 BIT(27) #define REG_RESET_CONTROL_PCIE2 BIT(26) @@ -67,19 +69,22 @@ Signed-off-by: Caleb James DeLisle #define REG_CRYPTO_CLKSRC2 0x20c +/* EN751221 */ +#define EN751221_REG_SPI_DIV 0x0cc -+#define EN751221_REG_SPI_DIV_MASK GENMASK(31,8) ++#define EN751221_REG_SPI_DIV_MASK GENMASK(31, 8) +#define EN751221_SPI_BASE 500000000 +#define EN751221_SPI_BASE_EN7526C 400000000 ++#define EN751221_SPI_DIV_DEFAULT 40 +#define EN751221_REG_BUS 0x284 -+#define EN751221_REG_BUS_MASK GENMASK(21,12) ++#define EN751221_REG_BUS_MASK GENMASK(21, 12) +#define EN751221_REG_SSR3 0x094 -+#define EN751221_REG_SSR3_GSW_MASK GENMASK(9,8) ++#define EN751221_REG_SSR3_GSW_MASK GENMASK(9, 8) #define REG_RST_CTRL2 0x830 #define REG_RST_CTRL1 0x834 +#define EN751221_REG_RST_DMT 0x84 +#define EN751221_REG_RST_USB 0xec + ++#define EN751221_MAX_CLKS 5 ++ +enum en_hir { + HIR_UNKNOWN = -1, + HIR_TC3169 = 0, @@ -101,7 +106,7 @@ Signed-off-by: Caleb James DeLisle struct en_clk_desc { int id; -@@ -93,6 +128,8 @@ static const u32 bus7581_base[] = { 6000 +@@ -93,6 +131,8 @@ static const u32 bus7581_base[] = { 6000 static const u32 npu7581_base[] = { 800000000, 750000000, 720000000, 600000000 }; static const u32 crypto_base[] = { 540000000, 480000000 }; static const u32 emmc7581_base[] = { 200000000, 150000000 }; @@ -110,7 +115,7 @@ Signed-off-by: Caleb James DeLisle static const struct en_clk_desc en7523_base_clks[] = { { -@@ -300,6 +337,13 @@ static const u16 en7581_rst_ofs[] = { +@@ -300,6 +340,13 @@ static const u16 en7581_rst_ofs[] = { REG_RST_CTRL1, }; @@ -124,7 +129,7 @@ Signed-off-by: Caleb James DeLisle static const u16 en7523_rst_map[] = { /* RST_CTRL2 */ [EN7523_XPON_PHY_RST] = 0, -@@ -405,8 +449,61 @@ static const u16 en7581_rst_map[] = { +@@ -405,8 +452,61 @@ static const u16 en7581_rst_map[] = { [EN7581_XPON_MAC_RST] = RST_NR_PER_BANK + 31, }; @@ -187,7 +192,7 @@ Signed-off-by: Caleb James DeLisle static u32 en7523_get_base_rate(const struct en_clk_desc *desc, u32 val) { -@@ -604,7 +701,8 @@ static int en7523_clk_hw_init(struct pla +@@ -604,7 +704,8 @@ static int en7523_clk_hw_init(struct pla en7523_register_clocks(&pdev->dev, clk_data, base, np_base); return en7581_reset_register(&pdev->dev, np_base, en7523_rst_map, @@ -197,7 +202,7 @@ Signed-off-by: Caleb James DeLisle } static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data, -@@ -705,7 +803,8 @@ static const struct reset_control_ops en +@@ -705,7 +806,8 @@ static const struct reset_control_ops en }; static int en7581_reset_register(struct device *dev, void __iomem *base, @@ -207,7 +212,7 @@ Signed-off-by: Caleb James DeLisle { struct en_rst_data *rst_data; -@@ -713,7 +812,7 @@ static int en7581_reset_register(struct +@@ -713,7 +815,7 @@ static int en7581_reset_register(struct if (!rst_data) return -ENOMEM; @@ -216,7 +221,7 @@ Signed-off-by: Caleb James DeLisle rst_data->idx_map = rst_map; rst_data->base = base; -@@ -752,7 +851,123 @@ static int en7581_clk_hw_init(struct pla +@@ -752,7 +854,107 @@ static int en7581_clk_hw_init(struct pla writel(val | 3, base + REG_NP_SCU_PCIC); return en7581_reset_register(&pdev->dev, base, en7581_rst_map, @@ -230,7 +235,9 @@ Signed-off-by: Caleb James DeLisle + u32 val = FIELD_GET(REG_HIR_MASK, readl(np_base + REG_HIR)); + + if (val < HIR_MAX) -+ return (enum en_hir) val; ++ return (enum en_hir)val; ++ ++ pr_warn("Unable to determine EcoNet SoC\n"); + + return HIR_UNKNOWN; +} @@ -241,6 +248,9 @@ Signed-off-by: Caleb James DeLisle +{ + struct clk_hw *hw; + ++ if (WARN_ON_ONCE(key >= EN751221_MAX_CLKS)) ++ return; ++ + hw = clk_hw_register_fixed_rate(dev, name, NULL, 0, rate); + if (IS_ERR(hw)) + pr_err("Failed to register clk %s: %pe\n", name, hw); @@ -274,7 +284,7 @@ Signed-off-by: Caleb James DeLisle + } else { + div = FIELD_GET(EN751221_REG_SPI_DIV_MASK, div) * 2; + if (!div) -+ div = 40; ++ div = EN751221_SPI_DIV_DEFAULT; + + en751221_try_register_clk(dev, EN751221_CLK_SPI, clk_data, + "spi", rate / div); @@ -291,27 +301,6 @@ Signed-off-by: Caleb James DeLisle + en751221_try_register_clk(dev, EN751221_CLK_CPU, clk_data, "cpu", + rate * 4); + -+ /* HPT */ -+ switch (hid) { -+ case HIR_EN751221: -+ case HIR_EN751627: -+ case HIR_EN7526C: -+ case HIR_EN7580: -+ case HIR_EN7528: -+ rate = 200000000; -+ break; -+ case HIR_MT7505: -+ rate = 100000000; -+ break; -+ case HIR_MT751020: -+ rate = 800000000 / 3; -+ break; -+ default: -+ rate = 250000000; -+ } -+ en751221_try_register_clk(dev, EN751221_CLK_HPT, clk_data, "hpt", -+ rate); -+ + /* GSW */ + rate = FIELD_GET(EN751221_REG_SSR3_GSW_MASK, + readl(np_base + EN751221_REG_SSR3)); @@ -341,7 +330,7 @@ Signed-off-by: Caleb James DeLisle } static int en7523_clk_probe(struct platform_device *pdev) -@@ -799,9 +1014,20 @@ static const struct en_clk_soc_data en75 +@@ -799,9 +1001,20 @@ static const struct en_clk_soc_data en75 .hw_init = en7581_clk_hw_init, }; diff --git a/target/linux/econet/patches-6.12/912-pcie-add-en7528-pcie-and-phy-support.patch b/target/linux/econet/patches-6.18/912-pcie-add-en7528-pcie-and-phy-support.patch similarity index 93% rename from target/linux/econet/patches-6.12/912-pcie-add-en7528-pcie-and-phy-support.patch rename to target/linux/econet/patches-6.18/912-pcie-add-en7528-pcie-and-phy-support.patch index ee8d1bdab9..0a320436cf 100644 --- a/target/linux/econet/patches-6.12/912-pcie-add-en7528-pcie-and-phy-support.patch +++ b/target/linux/econet/patches-6.18/912-pcie-add-en7528-pcie-and-phy-support.patch @@ -1,6 +1,6 @@ --- a/drivers/pci/controller/Kconfig +++ b/drivers/pci/controller/Kconfig -@@ -187,7 +187,7 @@ config PCI_MVEBU +@@ -193,7 +193,7 @@ config PCI_MVEBU config PCIE_MEDIATEK tristate "MediaTek PCIe controller" @@ -8,7 +8,7 @@ + depends on ARCH_AIROHA || ARCH_MEDIATEK || ECONET || COMPILE_TEST depends on OF depends on PCI_MSI - help + select IRQ_MSI_LIB --- a/arch/mips/econet/Kconfig +++ b/arch/mips/econet/Kconfig @@ -14,7 +14,9 @@ choice @@ -35,7 +35,7 @@ select SYS_SUPPORTS_HIGHMEM --- a/drivers/pci/controller/pcie-mediatek.c +++ b/drivers/pci/controller/pcie-mediatek.c -@@ -76,6 +76,7 @@ +@@ -77,6 +77,7 @@ #define PCIE_CONF_VEND_ID 0x100 #define PCIE_CONF_DEVICE_ID 0x102 @@ -43,7 +43,7 @@ #define PCIE_CONF_CLASS_ID 0x106 #define PCIE_INT_MASK 0x420 -@@ -88,6 +89,11 @@ +@@ -89,6 +90,11 @@ #define MSI_MASK BIT(23) #define MTK_MSI_IRQS_NUM 32 @@ -55,7 +55,7 @@ #define PCIE_AHB_TRANS_BASE0_L 0x438 #define PCIE_AHB_TRANS_BASE0_H 0x43c #define AHB2PCIE_SIZE(x) ((x) & GENMASK(4, 0)) -@@ -750,6 +756,86 @@ static int mtk_pcie_startup_port_v2(stru +@@ -746,6 +752,86 @@ static int mtk_pcie_startup_port_v2(stru return 0; } @@ -142,7 +142,7 @@ static void __iomem *mtk_pcie_map_bus(struct pci_bus *bus, unsigned int devfn, int where) { -@@ -1116,6 +1202,20 @@ static int mtk_pcie_probe(struct platfor +@@ -1107,6 +1193,20 @@ static int mtk_pcie_probe(struct platfor if (err) goto put_resources; @@ -163,7 +163,7 @@ return 0; put_resources: -@@ -1225,12 +1325,19 @@ static const struct mtk_pcie_soc mtk_pci +@@ -1216,12 +1316,19 @@ static const struct mtk_pcie_soc mtk_pci .setup_irq = mtk_pcie_setup_irq, }; @@ -185,9 +185,9 @@ MODULE_DEVICE_TABLE(of, mtk_pcie_ids); --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig -@@ -82,6 +82,17 @@ config PHY_AIROHA_PCIE - This driver create the basic PHY instance and provides initialize - callback for PCIe GEN3 port. +@@ -123,6 +123,17 @@ config PHY_NXP_PTN3222 + schemes. It supports all three USB 2.0 data rates: Low Speed, Full + Speed and High Speed. +config PHY_EN7528_PCIE + tristate "EcoNet EN7528 PCIe PHY Driver" @@ -205,14 +205,14 @@ source "drivers/phy/broadcom/Kconfig" --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile -@@ -11,6 +11,7 @@ obj-$(CONFIG_PHY_XGENE) += phy-xgene.o - obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o +@@ -14,6 +14,7 @@ obj-$(CONFIG_PHY_PISTACHIO_USB) += phy- + obj-$(CONFIG_PHY_SNPS_EUSB2) += phy-snps-eusb2.o obj-$(CONFIG_USB_LGM_PHY) += phy-lgm-usb.o obj-$(CONFIG_PHY_AIROHA_PCIE) += phy-airoha-pcie.o +obj-$(CONFIG_PHY_EN7528_PCIE) += phy-en7528-pcie.o - obj-y += allwinner/ \ + obj-$(CONFIG_PHY_NXP_PTN3222) += phy-nxp-ptn3222.o + obj-$(CONFIG_GENERIC_PHY) += allwinner/ \ amlogic/ \ - broadcom/ \ --- /dev/null +++ b/drivers/phy/phy-en7528-pcie.c @@ -0,0 +1,155 @@ diff --git a/target/linux/econet/patches-6.18/913-v7.1-PCI-Prevent-assignment-to-unsupported-bridge-windows.patch b/target/linux/econet/patches-6.18/913-v7.1-PCI-Prevent-assignment-to-unsupported-bridge-windows.patch new file mode 100644 index 0000000000..8c12e61245 --- /dev/null +++ b/target/linux/econet/patches-6.18/913-v7.1-PCI-Prevent-assignment-to-unsupported-bridge-windows.patch @@ -0,0 +1,66 @@ +From 92427ab4378faa168d6953d0f8574b8fc1edcc14 Mon Sep 17 00:00:00 2001 +From: Ahmed Naseef +Date: Thu, 12 Mar 2026 16:53:32 +0000 +Subject: [PATCH] PCI: Prevent assignment to unsupported bridge windows + +Previously, pci_read_bridge_io() and pci_read_bridge_mmio_pref() +unconditionally set resource type flags (IORESOURCE_IO or IORESOURCE_MEM | +IORESOURCE_PREFETCH) when reading bridge window registers. For windows that +are not implemented in hardware, this may cause the allocator to assign +space for a window that doesn't exist. + +For example, the EcoNET EN7528 SoC Root Port doesn't support the +prefetchable window, but since a downstream device had a prefetchable BAR, +the allocator mistakenly assigned a prefetchable window: + + pci 0001:00:01.0: [14c3:0811] type 01 class 0x060400 PCIe Root Port + pci 0001:00:01.0: PCI bridge to [bus 01-ff] + pci 0001:00:01.0: bridge window [mem 0x28000000-0x280fffff]: assigned + pci 0001:00:01.0: bridge window [mem 0x28100000-0x282fffff pref]: assigned + pci 0001:01:00.0: BAR 0 [mem 0x28100000-0x281fffff 64bit pref]: assigned + +pci_read_bridge_windows() already detects unsupported windows by testing +register writability and sets dev->io_window/pref_window accordingly. + +Check dev->io_window/pref_window so we don't set the resource flags for +unsupported windows, which prevents the allocator from assigning space to +them. + +After this commit, the prefetchable BAR is correctly allocated from the +non-prefetchable window: + + pci 0001:00:01.0: bridge window [mem 0x28000000-0x281fffff]: assigned + pci 0001:01:00.0: BAR 0 [mem 0x28000000-0x280fffff 64bit pref]: assigned + +Suggested-by: Bjorn Helgaas +Link: https://lore.kernel.org/all/20260113210259.GA715789@bhelgaas/ +Signed-off-by: Ahmed Naseef +Signed-off-by: Caleb James DeLisle +Signed-off-by: Bjorn Helgaas +Link: https://patch.msgid.link/20260312165332.569772-4-cjd@cjdns.fr +--- + drivers/pci/probe.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/pci/probe.c ++++ b/drivers/pci/probe.c +@@ -396,6 +396,9 @@ static void pci_read_bridge_io(struct pc + unsigned long io_mask, io_granularity, base, limit; + struct pci_bus_region region; + ++ if (!dev->io_window) ++ return; ++ + io_mask = PCI_IO_RANGE_MASK; + io_granularity = 0x1000; + if (dev->io_window_1k) { +@@ -466,6 +469,9 @@ static void pci_read_bridge_mmio_pref(st + pci_bus_addr_t base, limit; + struct pci_bus_region region; + ++ if (!dev->pref_window) ++ return; ++ + pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo); + pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo); + base64 = (mem_base_lo & PCI_PREF_RANGE_MASK) << 16; diff --git a/target/linux/econet/patches-6.12/914-phy-add-en7528-usb-phy-driver.patch b/target/linux/econet/patches-6.18/914-phy-add-en7528-usb-phy-driver.patch similarity index 98% rename from target/linux/econet/patches-6.12/914-phy-add-en7528-usb-phy-driver.patch rename to target/linux/econet/patches-6.18/914-phy-add-en7528-usb-phy-driver.patch index 308703c630..0d3f4506f4 100644 --- a/target/linux/econet/patches-6.12/914-phy-add-en7528-usb-phy-driver.patch +++ b/target/linux/econet/patches-6.18/914-phy-add-en7528-usb-phy-driver.patch @@ -9,7 +9,7 @@ and the Airoha AN7581 USB PHY driver by Christian Marangi. Signed-off-by: Ahmed Naseef --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig -@@ -93,6 +93,17 @@ config PHY_EN7528_PCIE +@@ -134,6 +134,17 @@ config PHY_EN7528_PCIE This driver provides PHY initialization for the two PCIe ports on EN7528 SoC. @@ -29,14 +29,14 @@ Signed-off-by: Ahmed Naseef source "drivers/phy/broadcom/Kconfig" --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile -@@ -12,6 +12,7 @@ obj-$(CONFIG_PHY_PISTACHIO_USB) += phy- +@@ -15,6 +15,7 @@ obj-$(CONFIG_PHY_SNPS_EUSB2) += phy-snp obj-$(CONFIG_USB_LGM_PHY) += phy-lgm-usb.o obj-$(CONFIG_PHY_AIROHA_PCIE) += phy-airoha-pcie.o obj-$(CONFIG_PHY_EN7528_PCIE) += phy-en7528-pcie.o +obj-$(CONFIG_PHY_EN7528_USB) += phy-en7528-usb.o - obj-y += allwinner/ \ + obj-$(CONFIG_PHY_NXP_PTN3222) += phy-nxp-ptn3222.o + obj-$(CONFIG_GENERIC_PHY) += allwinner/ \ amlogic/ \ - broadcom/ \ --- /dev/null +++ b/drivers/phy/phy-en7528-usb.c @@ -0,0 +1,316 @@ diff --git a/target/linux/econet/patches-6.12/915-usb-xhci-mtk-add-en7528-ltssm-quirk.patch b/target/linux/econet/patches-6.18/915-usb-xhci-mtk-add-en7528-ltssm-quirk.patch similarity index 100% rename from target/linux/econet/patches-6.12/915-usb-xhci-mtk-add-en7528-ltssm-quirk.patch rename to target/linux/econet/patches-6.18/915-usb-xhci-mtk-add-en7528-ltssm-quirk.patch diff --git a/target/linux/generic/backport-6.12/601-11-v6.14-net-mvpp2-implement-pcs_inband_caps-method.patch b/target/linux/generic/backport-6.12/601-11-v6.14-net-mvpp2-implement-pcs_inband_caps-method.patch index 846d9df36d..c0ab7ac5e2 100644 --- a/target/linux/generic/backport-6.12/601-11-v6.14-net-mvpp2-implement-pcs_inband_caps-method.patch +++ b/target/linux/generic/backport-6.12/601-11-v6.14-net-mvpp2-implement-pcs_inband_caps-method.patch @@ -16,7 +16,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -@@ -6237,19 +6237,26 @@ static const struct phylink_pcs_ops mvpp +@@ -6256,19 +6256,26 @@ static const struct phylink_pcs_ops mvpp .pcs_config = mvpp2_xlg_pcs_config, }; @@ -51,7 +51,7 @@ Signed-off-by: Jakub Kicinski } static void mvpp2_gmac_pcs_get_state(struct phylink_pcs *pcs, -@@ -6356,7 +6363,7 @@ static void mvpp2_gmac_pcs_an_restart(st +@@ -6375,7 +6382,7 @@ static void mvpp2_gmac_pcs_an_restart(st } static const struct phylink_pcs_ops mvpp2_phylink_gmac_pcs_ops = { diff --git a/target/linux/generic/backport-6.12/720-09-v6.14-net-phy-Constify-struct-mdio_device_id.patch b/target/linux/generic/backport-6.12/720-09-v6.14-net-phy-Constify-struct-mdio_device_id.patch index f54f471ab6..d09e95681e 100644 --- a/target/linux/generic/backport-6.12/720-09-v6.14-net-phy-Constify-struct-mdio_device_id.patch +++ b/target/linux/generic/backport-6.12/720-09-v6.14-net-phy-Constify-struct-mdio_device_id.patch @@ -458,7 +458,7 @@ Signed-off-by: Jakub Kicinski { } --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c -@@ -5835,7 +5835,7 @@ MODULE_DESCRIPTION("Micrel PHY driver"); +@@ -5836,7 +5836,7 @@ MODULE_DESCRIPTION("Micrel PHY driver"); MODULE_AUTHOR("David J. Choi"); MODULE_LICENSE("GPL"); diff --git a/target/linux/generic/backport-6.12/730-03-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch b/target/linux/generic/backport-6.12/730-03-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch index 95e8638c39..d009115686 100644 --- a/target/linux/generic/backport-6.12/730-03-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch +++ b/target/linux/generic/backport-6.12/730-03-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch @@ -19,7 +19,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c -@@ -3382,11 +3382,17 @@ static int of_phy_led(struct phy_device +@@ -3385,11 +3385,17 @@ static int of_phy_led(struct phy_device if (index > U8_MAX) return -EINVAL; diff --git a/target/linux/generic/backport-6.18/300-v7.2-MIPS-smp-report-dying-CPU-to-RCU-in-stop_this_cpu.patch b/target/linux/generic/backport-6.18/300-v7.2-MIPS-smp-report-dying-CPU-to-RCU-in-stop_this_cpu.patch new file mode 100644 index 0000000000..8f419e2fe4 --- /dev/null +++ b/target/linux/generic/backport-6.18/300-v7.2-MIPS-smp-report-dying-CPU-to-RCU-in-stop_this_cpu.patch @@ -0,0 +1,66 @@ +From 9f3f3bdc6d9dac1a5a8262ee7ad0f2ff1527a7e7 Mon Sep 17 00:00:00 2001 +From: Jonas Jelonek +Date: Mon, 8 Jun 2026 09:37:29 +0000 +Subject: MIPS: smp: report dying CPU to RCU in stop_this_cpu() + +smp_send_stop() parks all secondary CPUs in stop_this_cpu(). The function +marks the CPU offline for the scheduler via set_cpu_online(false) but +never informs RCU, so RCU keeps expecting a quiescent state from CPUs +that are now spinning forever with interrupts disabled. + +As long as nothing waits for an RCU grace period after smp_send_stop() +this is harmless, which is why it went unnoticed. Since commit +91840be8f710 ("irq_work: Fix use-after-free in irq_work_single() on PREEMPT_RT") +however, irq_work_sync() calls synchronize_rcu() on architectures without +an irq_work self-IPI, i.e. where arch_irq_work_has_interrupt() returns +false. That is the asm-generic default used by MIPS. Any irq_work_sync() +issued in the reboot/shutdown path after smp_send_stop() then blocks on +a grace period that can never complete, hanging the reboot: + + WARNING: CPU: 0 PID: 15 at kernel/irq_work.c:144 irq_work_queue_on + ... + rcu: INFO: rcu_sched detected stalls on CPUs/tasks: + rcu: Offline CPU 1 blocking current GP. + rcu: Offline CPU 2 blocking current GP. + rcu: Offline CPU 3 blocking current GP. + +This issue was noticed on several Realtek MIPS switch SoCs (MIPS +interAptiv) and came up during kernel bump downstream in OpenWrt from +6.18.33 to 6.18.34, after the backport of the patch to the 6.18 stable +branch. The patch also has been backported all the way back to 6.1. + +Call rcutree_report_cpu_dead() once interrupts are disabled, mirroring the +generic CPU-hotplug offline path, so RCU stops waiting on the parked CPUs +and grace periods can still complete. MIPS shuts down all CPUs here +without going through the CPU-hotplug mechanism, so this report is not +otherwise issued. Reporting a dying CPU to RCU outside the regular hotplug +offline path is not unprecedented: arm64 does the same in cpu_die_early(). +There it is an exception for a CPU that was coming online and is aborting +bringup, rather than the default shutdown action as on MIPS. + +Fixes: 91840be8f710 ("irq_work: Fix use-after-free in irq_work_single() on PREEMPT_RT") +CC: stable@vger.kernel.org +Signed-off-by: Jonas Jelonek +Signed-off-by: Thomas Bogendoerfer +--- + arch/mips/kernel/smp.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/mips/kernel/smp.c ++++ b/arch/mips/kernel/smp.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -422,6 +423,7 @@ static void stop_this_cpu(void *dummy) + set_cpu_online(smp_processor_id(), false); + calculate_cpu_foreign_map(); + local_irq_disable(); ++ rcutree_report_cpu_dead(); + while (1); + } + diff --git a/target/linux/generic/backport-6.18/435-v6.19-mtd-spinand-add-support-for-FudanMicro-FM25S01BI3.patch b/target/linux/generic/backport-6.18/435-v6.19-mtd-spinand-add-support-for-FudanMicro-FM25S01BI3.patch new file mode 100644 index 0000000000..7355efe36b --- /dev/null +++ b/target/linux/generic/backport-6.18/435-v6.19-mtd-spinand-add-support-for-FudanMicro-FM25S01BI3.patch @@ -0,0 +1,115 @@ +From f6dffe2a9ed1bdcee1879e2728310fb1e08602cf Mon Sep 17 00:00:00 2001 +From: Mikhail Zhilkin +Date: Thu, 27 Nov 2025 22:59:00 +0300 +Subject: mtd: spinand: add support for FudanMicro FM25S01BI3 + +Add support for FudanMicro FM25S01BI3 SPI NAND. + +Link: https://www.fmsh.com/nvm/FM25S01BI3_ds_eng.pdf + +Signed-off-by: Mikhail Zhilkin +Signed-off-by: Miquel Raynal +--- + drivers/mtd/nand/spi/fmsh.c | 72 +++++++++++++++++++++++++++++++++++++ + 1 file changed, 72 insertions(+) + +--- a/drivers/mtd/nand/spi/fmsh.c ++++ b/drivers/mtd/nand/spi/fmsh.c +@@ -9,6 +9,13 @@ + #include + #include + ++#define FM25S01BI3_STATUS_ECC_MASK (7 << 4) ++ #define FM25S01BI3_STATUS_ECC_NO_BITFLIPS (0 << 4) ++ #define FM25S01BI3_STATUS_ECC_1_3_BITFLIPS (1 << 4) ++ #define FM25S01BI3_STATUS_ECC_UNCOR_ERROR (2 << 4) ++ #define FM25S01BI3_STATUS_ECC_4_6_BITFLIPS (3 << 4) ++ #define FM25S01BI3_STATUS_ECC_7_8_BITFLIPS (5 << 4) ++ + #define SPINAND_MFR_FMSH 0xA1 + + static SPINAND_OP_VARIANTS(read_cache_variants, +@@ -45,11 +52,66 @@ static int fm25s01a_ooblayout_free(struc + return 0; + } + ++static int fm25s01bi3_ecc_get_status(struct spinand_device *spinand, ++ u8 status) ++{ ++ switch (status & FM25S01BI3_STATUS_ECC_MASK) { ++ case FM25S01BI3_STATUS_ECC_NO_BITFLIPS: ++ return 0; ++ ++ case FM25S01BI3_STATUS_ECC_UNCOR_ERROR: ++ return -EBADMSG; ++ ++ case FM25S01BI3_STATUS_ECC_1_3_BITFLIPS: ++ return 3; ++ ++ case FM25S01BI3_STATUS_ECC_4_6_BITFLIPS: ++ return 6; ++ ++ case FM25S01BI3_STATUS_ECC_7_8_BITFLIPS: ++ return 8; ++ ++ default: ++ break; ++ } ++ ++ return -EINVAL; ++} ++ ++static int fm25s01bi3_ooblayout_ecc(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ if (section) ++ return -ERANGE; ++ ++ region->offset = 64; ++ region->length = 64; ++ ++ return 0; ++} ++ ++static int fm25s01bi3_ooblayout_free(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ if (section > 3) ++ return -ERANGE; ++ ++ region->offset = (16 * section) + 4; ++ region->length = 12; ++ ++ return 0; ++} ++ + static const struct mtd_ooblayout_ops fm25s01a_ooblayout = { + .ecc = fm25s01a_ooblayout_ecc, + .free = fm25s01a_ooblayout_free, + }; + ++static const struct mtd_ooblayout_ops fm25s01bi3_ooblayout = { ++ .ecc = fm25s01bi3_ooblayout_ecc, ++ .free = fm25s01bi3_ooblayout_free, ++}; ++ + static const struct spinand_info fmsh_spinand_table[] = { + SPINAND_INFO("FM25S01A", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE4), +@@ -60,6 +122,16 @@ static const struct spinand_info fmsh_sp + &update_cache_variants), + 0, + SPINAND_ECCINFO(&fm25s01a_ooblayout, NULL)), ++ SPINAND_INFO("FM25S01BI3", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xd4), ++ NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), ++ NAND_ECCREQ(8, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&fm25s01bi3_ooblayout, ++ fm25s01bi3_ecc_get_status)), + }; + + static const struct spinand_manufacturer_ops fmsh_spinand_manuf_ops = { diff --git a/target/linux/generic/backport-6.18/601-v7.1-net-add-netdev_from_priv-helper.patch b/target/linux/generic/backport-6.18/601-v7.1-net-add-netdev_from_priv-helper.patch new file mode 100644 index 0000000000..3586c3f36f --- /dev/null +++ b/target/linux/generic/backport-6.18/601-v7.1-net-add-netdev_from_priv-helper.patch @@ -0,0 +1,35 @@ +From eb37011395f12138056a4d124159f1a8436662d3 Mon Sep 17 00:00:00 2001 +From: Qingfang Deng +Date: Fri, 20 Mar 2026 15:56:03 +0800 +Subject: [PATCH] net: add netdev_from_priv() helper + +Add a helper to get netdev from private data pointer, so drivers won't +have to store redundant netdev in priv. + +Signed-off-by: Qingfang Deng +Link: https://patch.msgid.link/20260320075605.490832-1-dqfext@gmail.com +Signed-off-by: Jakub Kicinski +--- + include/linux/netdevice.h | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -2750,6 +2750,17 @@ static inline void *netdev_priv(const st + return (void *)dev->priv; + } + ++/** ++ * netdev_from_priv() - get network device from priv ++ * @priv: network device private data ++ * ++ * Returns: net_device to which @priv belongs ++ */ ++static inline struct net_device *netdev_from_priv(const void *priv) ++{ ++ return container_of(priv, struct net_device, priv); ++} ++ + /* Set the sysfs physical device reference for the network logical device + * if set prior to registration will cause a symlink during initialization. + */ diff --git a/target/linux/generic/pending-6.18/704-netfilter-flowtable-fix-offloaded-ct-timeout-never-b.patch b/target/linux/generic/backport-6.18/704-v7.2-netfilter-flowtable-fix-offloaded-ct-timeout-never-b.patch similarity index 92% rename from target/linux/generic/pending-6.18/704-netfilter-flowtable-fix-offloaded-ct-timeout-never-b.patch rename to target/linux/generic/backport-6.18/704-v7.2-netfilter-flowtable-fix-offloaded-ct-timeout-never-b.patch index 852a0d43d4..22cd634071 100644 --- a/target/linux/generic/pending-6.18/704-netfilter-flowtable-fix-offloaded-ct-timeout-never-b.patch +++ b/target/linux/generic/backport-6.18/704-v7.2-netfilter-flowtable-fix-offloaded-ct-timeout-never-b.patch @@ -1,7 +1,7 @@ +From 53b3e60edb674b442b2b3bbdba484667b0f47a5d Mon Sep 17 00:00:00 2001 From: Adrian Bente Date: Thu, 28 May 2026 10:08:51 +0300 -Subject: [PATCH v2 net] netfilter: flowtable: fix offloaded ct timeout never being extended -Message-ID: <20260528070851.3913-1-adibente@gmail.com> +Subject: [PATCH] netfilter: flowtable: fix offloaded ct timeout never being extended OpenWrt has recently migrated many platforms to kernel 6.18. On the MediaTek platform, which supports hardware network offloading, WiFi @@ -29,10 +29,11 @@ snapshot and compare against that same absolute snapshot in the cmpxchg, so the timeout extension actually takes effect while the datapath remains authoritative if it updates ct->timeout concurrently. -Suggested-by: Florian Westphal Fixes: 03428ca5cee9 ("netfilter: conntrack: rework offload nf_conn timeout extension logic") Cc: stable@vger.kernel.org +Suggested-by: Florian Westphal Signed-off-by: Adrian Bente +Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_flow_table_core.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/target/linux/generic/backport-6.18/711-v7.2-net-phy-sfp-detect-presence-via-I2C-when-no-MOD_DEF0-GPIO.patch b/target/linux/generic/backport-6.18/711-v7.2-net-phy-sfp-detect-presence-via-I2C-when-no-MOD_DEF0-GPIO.patch new file mode 100644 index 0000000000..30787e6a27 --- /dev/null +++ b/target/linux/generic/backport-6.18/711-v7.2-net-phy-sfp-detect-presence-via-I2C-when-no-MOD_DEF0-GPIO.patch @@ -0,0 +1,156 @@ +From 8ac44d24c3a148c4177bd3ad790c377279f4674f Mon Sep 17 00:00:00 2001 +From: Greg Patrick +Date: Thu, 11 Jun 2026 17:53:41 +0000 +Subject: [PATCH] net: phy: sfp: detect presence via I2C when no MOD_DEF0 GPIO + +An SFP cage (compatible "sff,sfp") whose MOD_DEF0 signal is not wired to a +GPIO currently falls back to sff_gpio_get_state(), which unconditionally +reports the module as present. An empty cage therefore fails its probe and +is parked in SFP_MOD_ERROR forever; because SFP_F_PRESENT never deasserts +there is no REMOVE event to recover the state machine, so a module inserted +after boot is never detected, and empty cages spam -EIO at boot. + +This affects boards that route none of the cage presence signal to a +software-readable input. On the NicGiga S100-0800S-M (RTL9303, 8x SFP+) the +cage I2C bus is the switch's SMBus master; TX_DISABLE is driven via a +PCA9534 I/O expander, but no MOD_ABS/MOD_DEF0 line reaches a readable GPIO +(the RTL9303 gpio0 lines read stuck-low, the single PCA9534 is fully +consumed by TX_DISABLE, and there is no RTL8231). The Horaco ZX-SW82TS-L2P +(RTL9302D, 2x SFP+) is independently affected in the same way. + +For such an SFP cage, derive presence from a throttled single-byte I2C read +of the module EEPROM instead: a successful read asserts SFP_F_PRESENT, +R_PROBE_ABSENT consecutive failures clear it (to ride out a transient error +on a live module). The existing poll then emits SFP_E_INSERT / SFP_E_REMOVE +normally, giving working hot-plug and silencing the boot-time -EIO spam on +empty cages. Presence is re-probed every T_PROBE_PRESENT, so insertion is +detected within that interval and removal within +T_PROBE_PRESENT * R_PROBE_ABSENT. + +A soldered-down module (compatible "sff,sff") has no presence signal and is +genuinely always present, so it continues to use sff_gpio_get_state(); the +new path is gated on the cage type advertising SFP_F_PRESENT. + +Signed-off-by: Greg Patrick +Tested-by: Manuel Stocker +Reviewed-by: Maxime Chevallier +Tested-by: Maxime Chevallier +Link: https://patch.msgid.link/20260611175341.2223184-1-gregspatrick@hotmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/sfp.c | 83 +++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 80 insertions(+), 3 deletions(-) + +--- a/drivers/net/phy/sfp.c ++++ b/drivers/net/phy/sfp.c +@@ -206,6 +206,16 @@ static const enum gpiod_flags gpio_flags + #define T_PROBE_RETRY_SLOW msecs_to_jiffies(5000) + #define R_PROBE_RETRY_SLOW 12 + ++/* Polling interval and consecutive-failure threshold for the I2C presence ++ * probe used on boards without a MOD_DEF0 GPIO (see sfp_i2c_get_state()). ++ * A single successful read asserts presence immediately; R_PROBE_ABSENT ++ * consecutive failures are required to declare a live module removed, to ride ++ * out a transient I2C error. Insertion is thus detected within ++ * T_PROBE_PRESENT and removal within T_PROBE_PRESENT * R_PROBE_ABSENT. ++ */ ++#define T_PROBE_PRESENT msecs_to_jiffies(500) ++#define R_PROBE_ABSENT 3 ++ + /* SFP modules appear to always have their PHY configured for bus address + * 0x56 (which with mdio-i2c, translates to a PHY address of 22). + * RollBall SFPs access phy via SFP Enhanced Digital Diagnostic Interface +@@ -249,6 +259,13 @@ struct sfp { + + bool need_poll; + ++ /* I2C-probed presence, for boards without a MOD_DEF0 GPIO. ++ * Access rules: st_mutex held (updated from the poll/state machine). ++ */ ++ bool i2c_present; ++ u8 i2c_present_nak; ++ unsigned long i2c_present_next; ++ + /* Access rules: + * state_hw_drive: st_mutex held + * state_hw_mask: st_mutex held +@@ -861,6 +878,45 @@ static int sfp_read(struct sfp *sfp, boo + return sfp->read(sfp, a2, addr, buf, len); + } + ++/* Probe whether a module is physically present by attempting a single-byte ++ * I2C read of the EEPROM identifier (an empty cage NAKs). Used as the presence ++ * source on boards that do not wire MOD_DEF0 to a GPIO. ++ */ ++static bool sfp_module_present_i2c(struct sfp *sfp) ++{ ++ u8 id; ++ ++ return sfp_read(sfp, false, SFP_PHYS_ID, &id, sizeof(id)) == sizeof(id); ++} ++ ++/* get_state variant for boards without a MOD_DEF0 GPIO. Instead of assuming ++ * the module is always present, derive SFP_F_PRESENT from a throttled I2C ++ * probe so that hot-insertion and removal are detected. A single ACK asserts ++ * presence; R_PROBE_ABSENT consecutive failures clear it, to ride out a ++ * transient I2C error on a live module. ++ */ ++static unsigned int sfp_i2c_get_state(struct sfp *sfp) ++{ ++ unsigned int state = sfp_gpio_get_state(sfp); ++ ++ if (time_after_eq(jiffies, sfp->i2c_present_next)) { ++ if (sfp_module_present_i2c(sfp)) { ++ sfp->i2c_present = true; ++ sfp->i2c_present_nak = 0; ++ } else if (sfp->i2c_present && ++ ++sfp->i2c_present_nak >= R_PROBE_ABSENT) { ++ sfp->i2c_present = false; ++ sfp->i2c_present_nak = 0; ++ } ++ sfp->i2c_present_next = jiffies + T_PROBE_PRESENT; ++ } ++ ++ if (sfp->i2c_present) ++ state |= SFP_F_PRESENT; ++ ++ return state; ++} ++ + static int sfp_write(struct sfp *sfp, bool a2, u8 addr, void *buf, size_t len) + { + return sfp->write(sfp, a2, addr, buf, len); +@@ -3159,9 +3215,30 @@ static int sfp_probe(struct platform_dev + sfp->get_state = sfp_gpio_get_state; + sfp->set_state = sfp_gpio_set_state; + +- /* Modules that have no detect signal are always present */ +- if (!(sfp->gpio[GPIO_MODDEF0])) +- sfp->get_state = sff_gpio_get_state; ++ /* An SFP cage with no MOD_DEF0 GPIO has no hardware presence signal. ++ * Assuming the module is always present traps an empty cage in ++ * MOD_ERROR and never detects hot-insertion, so derive presence from a ++ * throttled I2C probe and poll for changes instead. sfp_i2c_configure() ++ * has already set i2c_max_block_size; seed i2c_block_size so the ++ * presence read does not issue a zero-length transfer before the first ++ * EEPROM read. Seed i2c_present_next to jiffies so the first probe ++ * happens immediately (a zero value would be in the past relative to ++ * the negative INITIAL_JIFFIES at boot and delay detection). ++ * ++ * A soldered-down module (sff,sff) has no presence signal and is ++ * genuinely always present, so it keeps the always-present behaviour; ++ * the I2C probe is gated on the cage type advertising SFP_F_PRESENT. ++ */ ++ if (!sfp->gpio[GPIO_MODDEF0]) { ++ if (sff->gpios & SFP_F_PRESENT) { ++ sfp->get_state = sfp_i2c_get_state; ++ sfp->i2c_block_size = sfp->i2c_max_block_size; ++ sfp->i2c_present_next = jiffies; ++ sfp->need_poll = true; ++ } else { ++ sfp->get_state = sff_gpio_get_state; ++ } ++ } + + device_property_read_u32(&pdev->dev, "maximum-power-milliwatt", + &sfp->max_power_mW); diff --git a/target/linux/generic/backport-6.18/746-v7.1-r8152-Add-support-for-5Gbit-Link-Speeds-and-EEE.patch b/target/linux/generic/backport-6.18/746-v7.1-r8152-Add-support-for-5Gbit-Link-Speeds-and-EEE.patch index 49bac39bcf..851333aab4 100644 --- a/target/linux/generic/backport-6.18/746-v7.1-r8152-Add-support-for-5Gbit-Link-Speeds-and-EEE.patch +++ b/target/linux/generic/backport-6.18/746-v7.1-r8152-Add-support-for-5Gbit-Link-Speeds-and-EEE.patch @@ -221,7 +221,7 @@ Signed-off-by: Paolo Abeni eee->eee_enabled = tp->eee_en; if (speed & _1000bps) -@@ -9381,6 +9440,11 @@ static int rtl8152_probe_once(struct usb +@@ -9386,6 +9445,11 @@ static int rtl8152_probe_once(struct usb } else { tp->speed = SPEED_1000; } diff --git a/target/linux/generic/backport-6.18/747-v7.1-r8152-Add-support-for-the-RTL8157-hardware.patch b/target/linux/generic/backport-6.18/747-v7.1-r8152-Add-support-for-the-RTL8157-hardware.patch index 459c2dba11..e1da5c1321 100644 --- a/target/linux/generic/backport-6.18/747-v7.1-r8152-Add-support-for-the-RTL8157-hardware.patch +++ b/target/linux/generic/backport-6.18/747-v7.1-r8152-Add-support-for-the-RTL8157-hardware.patch @@ -1535,7 +1535,7 @@ Signed-off-by: Paolo Abeni default: version = RTL_VER_UNKNOWN; dev_info(&udev->dev, "Unknown version 0x%04x\n", ocp_data); -@@ -9411,6 +9954,7 @@ static int rtl8152_probe_once(struct usb +@@ -9416,6 +9959,7 @@ static int rtl8152_probe_once(struct usb case RTL_VER_12: case RTL_VER_13: case RTL_VER_15: @@ -1543,7 +1543,7 @@ Signed-off-by: Paolo Abeni netdev->max_mtu = size_to_mtu(16 * 1024); break; case RTL_VER_01: -@@ -9571,6 +10115,7 @@ static const struct usb_device_id rtl815 +@@ -9576,6 +10120,7 @@ static const struct usb_device_id rtl815 { USB_DEVICE(VENDOR_ID_REALTEK, 0x8153) }, { USB_DEVICE(VENDOR_ID_REALTEK, 0x8155) }, { USB_DEVICE(VENDOR_ID_REALTEK, 0x8156) }, diff --git a/target/linux/generic/config-6.12 b/target/linux/generic/config-6.12 index 6aabd22cac..dab1c0bfec 100644 --- a/target/linux/generic/config-6.12 +++ b/target/linux/generic/config-6.12 @@ -363,6 +363,8 @@ CONFIG_ARM64_CNP=y # CONFIG_ARM64_ERRATUM_2966298 is not set # CONFIG_ARM64_ERRATUM_3117295 is not set # CONFIG_ARM64_ERRATUM_3194386 is not set +# CONFIG_ARM64_ERRATUM_4118414 is not set +# CONFIG_ARM64_ERRATUM_4193714 is not set # CONFIG_ARM64_ERRATUM_819472 is not set # CONFIG_ARM64_ERRATUM_824069 is not set # CONFIG_ARM64_ERRATUM_826319 is not set @@ -2171,6 +2173,7 @@ CONFIG_FS_STACK=y # CONFIG_FUSION_SPI is not set CONFIG_FUTEX=y CONFIG_FUTEX_PI=y +# CONFIG_FWNODE_PCS is not set # CONFIG_FW_CFG_SYSFS is not set # CONFIG_FW_DEVLINK_SYNC_STATE_TIMEOUT is not set CONFIG_FW_LOADER=y @@ -2179,7 +2182,6 @@ CONFIG_FW_LOADER=y CONFIG_FW_LOADER_USER_HELPER=y CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y # CONFIG_FW_UPLOAD is not set -# CONFIG_FWNODE_PCS is not set # CONFIG_FXAS21002C is not set # CONFIG_FXLS8962AF_I2C is not set # CONFIG_FXLS8962AF_SPI is not set diff --git a/target/linux/generic/config-6.18 b/target/linux/generic/config-6.18 index 71e42b022c..1556d09423 100644 --- a/target/linux/generic/config-6.18 +++ b/target/linux/generic/config-6.18 @@ -397,6 +397,7 @@ CONFIG_ARM64_CNP=y # CONFIG_ARM64_ERRATUM_2966298 is not set # CONFIG_ARM64_ERRATUM_3117295 is not set # CONFIG_ARM64_ERRATUM_3194386 is not set +# CONFIG_ARM64_ERRATUM_4118414 is not set # CONFIG_ARM64_ERRATUM_819472 is not set # CONFIG_ARM64_ERRATUM_824069 is not set # CONFIG_ARM64_ERRATUM_826319 is not set @@ -1637,7 +1638,6 @@ CONFIG_DQL=y # CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D is not set # CONFIG_DRM_PANEL_HIMAX_HX8279 is not set # CONFIG_DRM_PANEL_HIMAX_HX83102 is not set -# CONFIG_DRM_PANEL_HIMAX_HX83112B is not set # CONFIG_DRM_PANEL_HIMAX_HX83112A is not set # CONFIG_DRM_PANEL_HIMAX_HX83112B is not set # CONFIG_DRM_PANEL_HIMAX_HX8394 is not set @@ -1677,7 +1677,6 @@ CONFIG_DQL=y # CONFIG_DRM_PANEL_NOVATEK_NT36672E is not set # CONFIG_DRM_PANEL_NOVATEK_NT37801 is not set # CONFIG_DRM_PANEL_NOVATEK_NT39016 is not set -# CONFIG_DRM_PANEL_NOVATEK_NT37801 is not set # CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO is not set # CONFIG_DRM_PANEL_ORISETECH_OTA5601A is not set # CONFIG_DRM_PANEL_ORISETECH_OTM8009A is not set @@ -1707,7 +1706,6 @@ CONFIG_DQL=y # CONFIG_DRM_PANEL_SAMSUNG_S6E63M0 is not set # CONFIG_DRM_PANEL_SAMSUNG_S6E88A0_AMS427AP24 is not set # CONFIG_DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01 is not set -# CONFIG_DRM_PANEL_SAMSUNG_S6E88A0_AMS427AP24 is not set # CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0 is not set # CONFIG_DRM_PANEL_SAMSUNG_S6E8AA5X01_AMS561RA01 is not set # CONFIG_DRM_PANEL_SAMSUNG_SOFEF00 is not set @@ -1777,7 +1775,6 @@ CONFIG_DQL=y # CONFIG_DRM_TI_TDP158 is not set # CONFIG_DRM_TI_TFP410 is not set # CONFIG_DRM_TI_TPD12S015 is not set -# CONFIG_DRM_TI_TDP158 is not set # CONFIG_DRM_TOSHIBA_TC358762 is not set # CONFIG_DRM_TOSHIBA_TC358764 is not set # CONFIG_DRM_TOSHIBA_TC358767 is not set @@ -2274,6 +2271,7 @@ CONFIG_FUTEX=y CONFIG_FUTEX_PI=y CONFIG_FUTEX_PRIVATE_HASH=y # CONFIG_FWCTL is not set +# CONFIG_FWNODE_PCS is not set # CONFIG_FW_CFG_SYSFS is not set # CONFIG_FW_DEVLINK_SYNC_STATE_TIMEOUT is not set CONFIG_FW_LOADER=y @@ -2282,7 +2280,6 @@ CONFIG_FW_LOADER=y CONFIG_FW_LOADER_USER_HELPER=y CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y # CONFIG_FW_UPLOAD is not set -# CONFIG_FWNODE_PCS is not set # CONFIG_FXAS21002C is not set # CONFIG_FXLS8962AF_I2C is not set # CONFIG_FXLS8962AF_SPI is not set diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm63xx.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm63xx.c index 3a4b8a754f..e66e730991 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm63xx.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm63xx.c @@ -127,7 +127,7 @@ static int bcm63xx_parse_partitions(struct mtd_info *master, if (mtd_check_rootfs_magic(master, rootfs_offset, NULL)) pr_warn("rootfs magic not found\n"); - parts = kzalloc(BCM63XX_NR_PARTS * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(BCM63XX_NR_PARTS, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; @@ -176,11 +176,4 @@ static struct mtd_part_parser mtdsplit_bcm63xx_parser = { .type = MTD_PARSER_TYPE_FIRMWARE, }; -static int __init mtdsplit_bcm63xx_init(void) -{ - register_mtd_parser(&mtdsplit_bcm63xx_parser); - - return 0; -} - -module_init(mtdsplit_bcm63xx_init); +module_mtd_part_parser(mtdsplit_bcm63xx_parser); diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm_wfi.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm_wfi.c index 1cafc91fde..41e87e3b5c 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm_wfi.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm_wfi.c @@ -200,7 +200,7 @@ static int parse_bcm_wfi(struct mtd_info *master, if (ret) return ret; - parts = kzalloc(num_parts * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(num_parts, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; @@ -348,7 +348,7 @@ static int mtdsplit_parse_bcm_wfi_split(struct mtd_info *master, kfree(buf); if (ret > 0) { - parts = kzalloc((ret + 1) * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(ret + 1, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; @@ -362,7 +362,7 @@ static int mtdsplit_parse_bcm_wfi_split(struct mtd_info *master, *pparts = parts; } else { - parts = kzalloc(BCM_WFI_SPLIT_PARTS * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(BCM_WFI_SPLIT_PARTS, sizeof(*parts), GFP_KERNEL); parts[0].name = PART_IMAGE_1; parts[0].offset = img1_off; @@ -480,7 +480,7 @@ static int mtdsplit_parse_ser_wfi(struct mtd_info *master, kfree(buf); if (ret > 0) { - parts = kzalloc((ret + 1) * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(ret + 1, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; @@ -494,7 +494,7 @@ static int mtdsplit_parse_ser_wfi(struct mtd_info *master, *pparts = parts; } else { - parts = kzalloc(BCM_WFI_SPLIT_PARTS * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(BCM_WFI_SPLIT_PARTS, sizeof(*parts), GFP_KERNEL); parts[0].name = PART_IMAGE_1; parts[0].offset = img1_off; @@ -532,4 +532,12 @@ static int __init mtdsplit_bcm_wfi_init(void) return 0; } +static void __exit mtdsplit_bcm_wfi_exit(void) +{ + deregister_mtd_parser(&mtdsplit_bcm_wfi_parser); + deregister_mtd_parser(&mtdsplit_bcm_wfi_split_parser); + deregister_mtd_parser(&mtdsplit_ser_wfi_parser); +} + module_init(mtdsplit_bcm_wfi_init); +module_exit(mtdsplit_bcm_wfi_exit); diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_brnimage.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_brnimage.c index 3f2d79601a..f029f726de 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_brnimage.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_brnimage.c @@ -71,7 +71,7 @@ static int mtdsplit_parse_brnimage(struct mtd_info *master, */ rootfs_size = master->size - rootfs_offset - BRNIMAGE_FOOTER_SIZE; - parts = kzalloc(BRNIMAGE_NR_PARTS * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(BRNIMAGE_NR_PARTS, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; @@ -94,11 +94,4 @@ static struct mtd_part_parser mtdsplit_brnimage_parser = { .type = MTD_PARSER_TYPE_FIRMWARE, }; -static int __init mtdsplit_brnimage_init(void) -{ - register_mtd_parser(&mtdsplit_brnimage_parser); - - return 0; -} - -subsys_initcall(mtdsplit_brnimage_init); +module_mtd_part_parser(mtdsplit_brnimage_parser); diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_cfe_bootfs.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_cfe_bootfs.c index a3474c9dc2..c9d68f1393 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_cfe_bootfs.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_cfe_bootfs.c @@ -54,7 +54,7 @@ static int mtdsplit_cfe_bootfs_parse(struct mtd_info *mtd, if (err) return err; - parts = kzalloc(NR_PARTS * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(NR_PARTS, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_elf.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_elf.c index db29054357..ca85ea8e5d 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_elf.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_elf.c @@ -244,7 +244,7 @@ static int mtdsplit_parse_elf(struct mtd_info *mtd, return -ENOENT; } - parts = kzalloc(ELF_NR_PARTS * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(ELF_NR_PARTS, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; @@ -277,11 +277,4 @@ static struct mtd_part_parser mtdsplit_elf_parser = { .type = MTD_PARSER_TYPE_FIRMWARE, }; -static int __init mtdsplit_elf_init(void) -{ - register_mtd_parser(&mtdsplit_elf_parser); - - return 0; -} - -subsys_initcall(mtdsplit_elf_init); +module_mtd_part_parser(mtdsplit_elf_parser); diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_eva.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_eva.c index 55004a6d36..93fe5b5e74 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_eva.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_eva.c @@ -64,7 +64,7 @@ static int mtdsplit_parse_eva(struct mtd_info *master, if (err) return err; - parts = kzalloc(EVA_NR_PARTS * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(EVA_NR_PARTS, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; @@ -93,11 +93,4 @@ static struct mtd_part_parser mtdsplit_eva_parser = { .type = MTD_PARSER_TYPE_FIRMWARE, }; -static int __init mtdsplit_eva_init(void) -{ - register_mtd_parser(&mtdsplit_eva_parser); - - return 0; -} - -subsys_initcall(mtdsplit_eva_init); +module_mtd_part_parser(mtdsplit_eva_parser); diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_fit.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_fit.c index b2042808e6..2afc19d09f 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_fit.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_fit.c @@ -272,7 +272,7 @@ mtdsplit_fit_parse(struct mtd_info *mtd, rootfs_size = mtd->size - rootfs_offset; - parts = kzalloc(2 * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(2, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; @@ -351,15 +351,4 @@ static struct mtd_part_parser uimage_parser = { .type = MTD_PARSER_TYPE_FIRMWARE, }; -/************************************************** - * Init - **************************************************/ - -static int __init mtdsplit_fit_init(void) -{ - register_mtd_parser(&uimage_parser); - - return 0; -} - -module_init(mtdsplit_fit_init); +module_mtd_part_parser(uimage_parser); diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_h3c_vfs.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_h3c_vfs.c index a7b2b6ea7e..3bb585d344 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_h3c_vfs.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_h3c_vfs.c @@ -140,7 +140,7 @@ static int mtdsplit_h3c_vfs_parse(struct mtd_info *mtd, if (err) return err; - parts = kzalloc(NR_PARTS * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(NR_PARTS, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_jimage.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_jimage.c index a0ea81cfd6..c921593b98 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_jimage.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_jimage.c @@ -108,7 +108,7 @@ static int __mtdsplit_parse_jimage(struct mtd_info *master, enum mtdsplit_part_type type; nr_parts = 2; - parts = kzalloc(nr_parts * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(nr_parts, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; @@ -270,15 +270,4 @@ static struct mtd_part_parser jimage_generic_parser = { .type = MTD_PARSER_TYPE_FIRMWARE, }; -/************************************************** - * Init - **************************************************/ - -static int __init mtdsplit_jimage_init(void) -{ - register_mtd_parser(&jimage_generic_parser); - - return 0; -} - -module_init(mtdsplit_jimage_init); +module_mtd_part_parser(jimage_generic_parser); diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_lzma.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_lzma.c index 6dcffd0420..71e01ac7ea 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_lzma.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_lzma.c @@ -69,7 +69,7 @@ static int mtdsplit_parse_lzma(struct mtd_info *master, if (err) return err; - parts = kzalloc(LZMA_NR_PARTS * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(LZMA_NR_PARTS, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; @@ -99,11 +99,4 @@ static struct mtd_part_parser mtdsplit_lzma_parser = { .type = MTD_PARSER_TYPE_FIRMWARE, }; -static int __init mtdsplit_lzma_init(void) -{ - register_mtd_parser(&mtdsplit_lzma_parser); - - return 0; -} - -subsys_initcall(mtdsplit_lzma_init); +module_mtd_part_parser(mtdsplit_lzma_parser); diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_minor.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_minor.c index bf1959f50a..55cb9ce25b 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_minor.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_minor.c @@ -88,7 +88,7 @@ static int mtdsplit_parse_minor(struct mtd_info *master, if (err) return err; - parts = kzalloc(MINOR_NR_PARTS * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(MINOR_NR_PARTS, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; @@ -118,11 +118,4 @@ static struct mtd_part_parser mtdsplit_minor_parser = { .type = MTD_PARSER_TYPE_FIRMWARE, }; -static int __init mtdsplit_minor_init(void) -{ - register_mtd_parser(&mtdsplit_minor_parser); - - return 0; -} - -subsys_initcall(mtdsplit_minor_init); +module_mtd_part_parser(mtdsplit_minor_parser); diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_owrt_prolog.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_owrt_prolog.c index 78c9c4dae0..c675aff9f3 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_owrt_prolog.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_owrt_prolog.c @@ -95,7 +95,7 @@ static int mtdsplit_parse_owrt_prolog(struct mtd_info *master, if (ret) return ret; - parts = kzalloc(OWRT_PROLOG_NR_PARTS * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(OWRT_PROLOG_NR_PARTS, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; @@ -124,11 +124,4 @@ static struct mtd_part_parser mtdsplit_owrt_prolog_parser = { .type = MTD_PARSER_TYPE_FIRMWARE, }; -static int __init mtdsplit_owrt_prolog_init(void) -{ - register_mtd_parser(&mtdsplit_owrt_prolog_parser); - - return 0; -} - -subsys_initcall(mtdsplit_owrt_prolog_init); +module_mtd_part_parser(mtdsplit_owrt_prolog_parser); diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_seama.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_seama.c index 5d49171b1f..5c39397730 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_seama.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_seama.c @@ -75,7 +75,7 @@ static int mtdsplit_parse_seama(struct mtd_info *master, return err; } - parts = kzalloc(SEAMA_NR_PARTS * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(SEAMA_NR_PARTS, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; @@ -108,11 +108,4 @@ static struct mtd_part_parser mtdsplit_seama_parser = { .type = MTD_PARSER_TYPE_FIRMWARE, }; -static int __init mtdsplit_seama_init(void) -{ - register_mtd_parser(&mtdsplit_seama_parser); - - return 0; -} - -subsys_initcall(mtdsplit_seama_init); +module_mtd_part_parser(mtdsplit_seama_parser); diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_squashfs.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_squashfs.c index f6353da65b..ba929c5e38 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_squashfs.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_squashfs.c @@ -62,11 +62,4 @@ static struct mtd_part_parser mtdsplit_squashfs_parser = { .type = MTD_PARSER_TYPE_ROOTFS, }; -static int __init mtdsplit_squashfs_init(void) -{ - register_mtd_parser(&mtdsplit_squashfs_parser); - - return 0; -} - -subsys_initcall(mtdsplit_squashfs_init); +module_mtd_part_parser(mtdsplit_squashfs_parser); diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_tplink.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_tplink.c index 8909c107a0..03cc7dd2f3 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_tplink.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_tplink.c @@ -137,7 +137,7 @@ static int mtdsplit_parse_tplink(struct mtd_info *master, return err; } - parts = kzalloc(TPLINK_NR_PARTS * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(TPLINK_NR_PARTS, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; @@ -166,11 +166,4 @@ static struct mtd_part_parser mtdsplit_tplink_parser = { .type = MTD_PARSER_TYPE_FIRMWARE, }; -static int __init mtdsplit_tplink_init(void) -{ - register_mtd_parser(&mtdsplit_tplink_parser); - - return 0; -} - -subsys_initcall(mtdsplit_tplink_init); +module_mtd_part_parser(mtdsplit_tplink_parser); diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_trx.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_trx.c index 46a93ba38e..869b92cdf1 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_trx.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_trx.c @@ -71,7 +71,7 @@ mtdsplit_parse_trx(struct mtd_info *master, int ret; nr_parts = 2; - parts = kzalloc(nr_parts * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(nr_parts, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; @@ -145,11 +145,4 @@ static struct mtd_part_parser trx_parser = { .type = MTD_PARSER_TYPE_FIRMWARE, }; -static int __init mtdsplit_trx_init(void) -{ - register_mtd_parser(&trx_parser); - - return 0; -} - -module_init(mtdsplit_trx_init); +module_mtd_part_parser(trx_parser); diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_uimage.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_uimage.c index fe824cbda6..a2d2ba1622 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_uimage.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_uimage.c @@ -139,7 +139,7 @@ static int __mtdsplit_parse_uimage(struct mtd_info *master, enum mtdsplit_part_type type; nr_parts = 2; - parts = kzalloc(nr_parts * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(nr_parts, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; @@ -269,15 +269,4 @@ static struct mtd_part_parser uimage_generic_parser = { .type = MTD_PARSER_TYPE_FIRMWARE, }; -/************************************************** - * Init - **************************************************/ - -static int __init mtdsplit_uimage_init(void) -{ - register_mtd_parser(&uimage_generic_parser); - - return 0; -} - -module_init(mtdsplit_uimage_init); +module_mtd_part_parser(uimage_generic_parser); diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_wrgg.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_wrgg.c index dfd6058ae7..319990a876 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_wrgg.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_wrgg.c @@ -102,7 +102,7 @@ static int mtdsplit_parse_wrgg(struct mtd_info *master, if (err) return err; - parts = kzalloc(WRGG_NR_PARTS * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(WRGG_NR_PARTS, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; @@ -132,11 +132,4 @@ static struct mtd_part_parser mtdsplit_wrgg_parser = { .type = MTD_PARSER_TYPE_FIRMWARE, }; -static int __init mtdsplit_wrgg_init(void) -{ - register_mtd_parser(&mtdsplit_wrgg_parser); - - return 0; -} - -subsys_initcall(mtdsplit_wrgg_init); +module_mtd_part_parser(mtdsplit_wrgg_parser); diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.c b/target/linux/generic/files/drivers/net/phy/ar8216.c index 71bf0bf04d..a01590c9eb 100644 --- a/target/linux/generic/files/drivers/net/phy/ar8216.c +++ b/target/linux/generic/files/drivers/net/phy/ar8216.c @@ -2310,16 +2310,14 @@ next_attempt: static int ar8xxx_mib_init(struct ar8xxx_priv *priv) { - unsigned int len; - if (!ar8xxx_has_mib_counters(priv)) return 0; - BUG_ON(!priv->chip->mib_decs || !priv->chip->num_mibs); + if (WARN_ON(!priv->chip->mib_decs || !priv->chip->num_mibs)) + return -EINVAL; - len = priv->dev.ports * priv->chip->num_mibs * - sizeof(*priv->mib_stats); - priv->mib_stats = kzalloc(len, GFP_KERNEL); + priv->mib_stats = kcalloc(array_size(priv->dev.ports, priv->chip->num_mibs), + sizeof(*priv->mib_stats), GFP_KERNEL); if (!priv->mib_stats) return -ENOMEM; diff --git a/target/linux/generic/files/drivers/net/phy/b53/b53_common.c b/target/linux/generic/files/drivers/net/phy/b53/b53_common.c index 1130afdd9c..0a698cca78 100644 --- a/target/linux/generic/files/drivers/net/phy/b53/b53_common.c +++ b/target/linux/generic/files/drivers/net/phy/b53/b53_common.c @@ -566,6 +566,7 @@ static int b53_configure_ports_of(struct b53_device *dev) } } + of_node_put(dn); return 0; } diff --git a/target/linux/generic/files/drivers/net/phy/rtl8306.c b/target/linux/generic/files/drivers/net/phy/rtl8306.c index a4b26642e2..b91c493689 100644 --- a/target/linux/generic/files/drivers/net/phy/rtl8306.c +++ b/target/linux/generic/files/drivers/net/phy/rtl8306.c @@ -266,7 +266,8 @@ rtl_set_page(struct rtl_priv *priv, unsigned int page) if (priv->page == page) return; - BUG_ON(page > RTL8306_NUM_PAGES); + if (WARN_ON_ONCE(page > RTL8306_NUM_PAGES)) + return; pgsel = bus->read(bus, 0, RTL8306_REG_PAGE); pgsel &= ~(RTL8306_REG_PAGE_LO | RTL8306_REG_PAGE_HI); if (page & (1 << 0)) @@ -320,7 +321,8 @@ rtl_get(struct switch_dev *dev, enum rtl_regidx s) const struct rtl_reg *r = &rtl_regs[s]; u16 val; - BUG_ON(s >= ARRAY_SIZE(rtl_regs)); + if (WARN_ON_ONCE(s >= ARRAY_SIZE(rtl_regs))) + return 0; if (r->bits == 0) /* unimplemented */ return 0; @@ -343,7 +345,8 @@ rtl_set(struct switch_dev *dev, enum rtl_regidx s, unsigned int val) const struct rtl_reg *r = &rtl_regs[s]; u16 mask = 0xffff; - BUG_ON(s >= ARRAY_SIZE(rtl_regs)); + if (WARN_ON_ONCE(s >= ARRAY_SIZE(rtl_regs))) + return -EINVAL; if (r->bits == 0) /* unimplemented */ return 0; @@ -895,19 +898,19 @@ rtl8306_config_init(struct phy_device *pdev) switch(chiptype) { case 0: case 2: - strncpy(priv->hwname, RTL_NAME_S, sizeof(priv->hwname)); + strscpy(priv->hwname, RTL_NAME_S, sizeof(priv->hwname)); priv->type = RTL_TYPE_S; break; case 1: - strncpy(priv->hwname, RTL_NAME_SD, sizeof(priv->hwname)); + strscpy(priv->hwname, RTL_NAME_SD, sizeof(priv->hwname)); priv->type = RTL_TYPE_SD; break; case 3: - strncpy(priv->hwname, RTL_NAME_SDM, sizeof(priv->hwname)); + strscpy(priv->hwname, RTL_NAME_SDM, sizeof(priv->hwname)); priv->type = RTL_TYPE_SDM; break; default: - strncpy(priv->hwname, RTL_NAME_UNKNOWN, sizeof(priv->hwname)); + strscpy(priv->hwname, RTL_NAME_UNKNOWN, sizeof(priv->hwname)); break; } diff --git a/target/linux/generic/files/drivers/net/phy/rtl8366_smi.c b/target/linux/generic/files/drivers/net/phy/rtl8366_smi.c index aa8ef0bba2..84c6e7eca2 100644 --- a/target/linux/generic/files/drivers/net/phy/rtl8366_smi.c +++ b/target/linux/generic/files/drivers/net/phy/rtl8366_smi.c @@ -257,7 +257,8 @@ static int __rtl8366_mdio_read_reg(struct rtl8366_smi *smi, u32 addr, u32 *data) u32 phy_id = smi->phy_id; struct mii_bus *mbus = smi->ext_mbus; - BUG_ON(in_interrupt()); + if (WARN_ON(in_interrupt())) + return -EPERM; mutex_lock(&mbus->mdio_lock); /* Write Start command to register 29 */ @@ -279,7 +280,7 @@ static int __rtl8366_mdio_read_reg(struct rtl8366_smi *smi, u32 addr, u32 *data) mbus->write(mbus, phy_id, MDC_MDIO_CTRL1_REG, MDC_MDIO_READ_OP); /* Write Start command to register 29 */ - mbus->write(smi->ext_mbus, phy_id, MDC_MDIO_START_REG, MDC_MDIO_START_OP); + mbus->write(mbus, phy_id, MDC_MDIO_START_REG, MDC_MDIO_START_OP); /* Read data from register 25 */ *data = mbus->read(mbus, phy_id, MDC_MDIO_DATA_READ_REG); @@ -294,7 +295,8 @@ static int __rtl8366_mdio_write_reg(struct rtl8366_smi *smi, u32 addr, u32 data) u32 phy_id = smi->phy_id; struct mii_bus *mbus = smi->ext_mbus; - BUG_ON(in_interrupt()); + if (WARN_ON(in_interrupt())) + return -EPERM; mutex_lock(&mbus->mdio_lock); @@ -1344,7 +1346,8 @@ struct rtl8366_smi *rtl8366_smi_alloc(struct device *parent) { struct rtl8366_smi *smi; - BUG_ON(!parent); + if (WARN_ON(!parent)) + return NULL; smi = kzalloc(sizeof(*smi), GFP_KERNEL); if (!smi) { diff --git a/target/linux/generic/files/drivers/net/phy/rtl8367b.c b/target/linux/generic/files/drivers/net/phy/rtl8367b.c index d3dc6af39a..850392cc7c 100644 --- a/target/linux/generic/files/drivers/net/phy/rtl8367b.c +++ b/target/linux/generic/files/drivers/net/phy/rtl8367b.c @@ -565,7 +565,11 @@ static int rtl8367b_init_regs(struct rtl8366_smi *smi) count = ARRAY_SIZE(rtl8367c_initvals); if ((smi->rtl8367b_chip == RTL8367B_CHIP_RTL8367S_VB) && (smi->emu_vlanmc == NULL)) { smi->emu_vlanmc = kzalloc(sizeof(struct rtl8366_vlan_mc) * smi->num_vlan_mc, GFP_KERNEL); - dev_info(smi->parent, "alloc vlan mc emulator"); + if (!smi->emu_vlanmc) { + dev_err(smi->parent, "failed to allocate vlan mc emulator\n"); + return -ENOMEM; + } + dev_info(smi->parent, "alloc vlan mc emulator\n"); } break; default: @@ -1586,6 +1590,7 @@ static void rtl8367b_remove(struct platform_device *pdev) rtl8367b_switch_cleanup(smi); platform_set_drvdata(pdev, NULL); rtl8366_smi_cleanup(smi); + kfree(smi->emu_vlanmc); kfree(smi); } } diff --git a/target/linux/generic/files/drivers/net/phy/swconfig.c b/target/linux/generic/files/drivers/net/phy/swconfig.c index f902ddc918..d57c112802 100644 --- a/target/linux/generic/files/drivers/net/phy/swconfig.c +++ b/target/linux/generic/files/drivers/net/phy/swconfig.c @@ -1114,7 +1114,8 @@ register_switch(struct switch_dev *dev, struct net_device *netdev) if (!dev->alias) dev->alias = netdev->name; } - BUG_ON(!dev->alias); + if (WARN_ON(!dev->alias)) + return -EINVAL; /* Make sure swdev_id doesn't overflow */ if (swdev_id == INT_MAX) { @@ -1122,12 +1123,10 @@ register_switch(struct switch_dev *dev, struct net_device *netdev) } if (dev->ports > 0) { - dev->portbuf = kzalloc(sizeof(struct switch_port) * - dev->ports, GFP_KERNEL); + dev->portbuf = kcalloc(dev->ports, sizeof(struct switch_port), GFP_KERNEL); if (!dev->portbuf) return -ENOMEM; - dev->portmap = kzalloc(sizeof(struct switch_portmap) * - dev->ports, GFP_KERNEL); + dev->portmap = kcalloc(dev->ports, sizeof(struct switch_portmap), GFP_KERNEL); if (!dev->portmap) { kfree(dev->portbuf); return -ENOMEM; diff --git a/target/linux/generic/files/drivers/net/phy/swconfig_leds.c b/target/linux/generic/files/drivers/net/phy/swconfig_leds.c index 1fcd4432b5..b0970b00e8 100644 --- a/target/linux/generic/files/drivers/net/phy/swconfig_leds.c +++ b/target/linux/generic/files/drivers/net/phy/swconfig_leds.c @@ -237,8 +237,7 @@ static ssize_t swconfig_trig_mode_store(struct device *dev, char *p, *token; /* take a copy since we don't want to trash the inbound buffer when using strsep */ - strncpy(copybuf, buf, sizeof(copybuf)); - copybuf[sizeof(copybuf) - 1] = 0; + strscpy(copybuf, buf, sizeof(copybuf)); p = copybuf; while ((token = strsep(&p, " \t\n")) != NULL) { diff --git a/target/linux/generic/hack-6.12/421-drivers-mtd-parsers-add-nvmem-support-to-cmdlinepart.patch b/target/linux/generic/hack-6.12/421-drivers-mtd-parsers-add-nvmem-support-to-cmdlinepart.patch index 190fecc1a0..9f8f8c112c 100644 --- a/target/linux/generic/hack-6.12/421-drivers-mtd-parsers-add-nvmem-support-to-cmdlinepart.patch +++ b/target/linux/generic/hack-6.12/421-drivers-mtd-parsers-add-nvmem-support-to-cmdlinepart.patch @@ -27,7 +27,7 @@ Signed-off-by: Ansuel Smith /* special size referring to all the remaining space in a partition */ #define SIZE_REMAINING ULLONG_MAX -@@ -315,6 +316,68 @@ static int mtdpart_setup_real(char *s) +@@ -315,6 +316,67 @@ static int mtdpart_setup_real(char *s) return 0; } @@ -37,7 +37,6 @@ Signed-off-by: Ansuel Smith +{ + struct device_node *mtd_node; + struct device_node *ofpart_node; -+ struct device_node *pp; + struct mtd_partition part; + const char *partname; + @@ -47,7 +46,7 @@ Signed-off-by: Ansuel Smith + + ofpart_node = of_get_child_by_name(mtd_node, "partitions"); + -+ for_each_child_of_node(ofpart_node, pp) { ++ for_each_child_of_node_scoped(ofpart_node, pp) { + const __be32 *reg; + int len; + int a_cells, s_cells; @@ -71,7 +70,7 @@ Signed-off-by: Ansuel Smith + + part.offset = of_read_number(reg, a_cells); + part.size = of_read_number(reg + a_cells, s_cells); -+ part.of_node = pp; ++ part.of_node = of_node_get(pp); + + partname = of_get_property(pp, "label", &len); + if (!partname) @@ -96,7 +95,7 @@ Signed-off-by: Ansuel Smith /* * Main function to be called from the MTD mapping driver/device to * obtain the partitioning information. At this point the command line -@@ -330,6 +393,7 @@ static int parse_cmdline_partitions(stru +@@ -330,6 +392,7 @@ static int parse_cmdline_partitions(stru int i, err; struct cmdline_mtd_partition *part; const char *mtd_id = master->name; @@ -104,7 +103,7 @@ Signed-off-by: Ansuel Smith /* parse command line */ if (!cmdline_parsed) { -@@ -374,6 +438,13 @@ static int parse_cmdline_partitions(stru +@@ -374,6 +437,13 @@ static int parse_cmdline_partitions(stru sizeof(*part->parts) * (part->num_parts - i)); i--; } diff --git a/target/linux/generic/hack-6.12/780-usb-net-MeigLink_modem_support.patch b/target/linux/generic/hack-6.12/780-usb-net-MeigLink_modem_support.patch index eff038fbd0..feeb329ca1 100644 --- a/target/linux/generic/hack-6.12/780-usb-net-MeigLink_modem_support.patch +++ b/target/linux/generic/hack-6.12/780-usb-net-MeigLink_modem_support.patch @@ -32,7 +32,7 @@ Subject: [PATCH] net/usb/qmi_wwan: add MeigLink modem support {QMI_FIXED_INTF(0x0408, 0xea42, 4)}, /* Yota / Megafon M100-1 */ --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c -@@ -247,6 +247,11 @@ static void option_instat_callback(struc +@@ -248,6 +248,11 @@ static void option_instat_callback(struc #define UBLOX_PRODUCT_R410M 0x90b2 /* These Yuga products use Qualcomm's vendor ID */ #define YUGA_PRODUCT_CLM920_NC5 0x9625 @@ -44,7 +44,7 @@ Subject: [PATCH] net/usb/qmi_wwan: add MeigLink modem support #define QUECTEL_VENDOR_ID 0x2c7c /* These Quectel products use Quectel's vendor ID */ -@@ -1156,6 +1161,11 @@ static const struct usb_device_id option +@@ -1159,6 +1164,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) }, @@ -56,7 +56,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), -@@ -1197,6 +1207,11 @@ static const struct usb_device_id option +@@ -1200,6 +1210,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.12/800-GPIO-add-named-gpio-exports.patch b/target/linux/generic/hack-6.12/800-GPIO-add-named-gpio-exports.patch index fe2b19c563..367ad69664 100644 --- a/target/linux/generic/hack-6.12/800-GPIO-add-named-gpio-exports.patch +++ b/target/linux/generic/hack-6.12/800-GPIO-add-named-gpio-exports.patch @@ -15,7 +15,7 @@ Signed-off-by: John Crispin #include "gpiolib.h" #include "gpiolib-of.h" -@@ -1205,3 +1207,73 @@ void of_gpiochip_remove(struct gpio_chip +@@ -1205,3 +1207,72 @@ void of_gpiochip_remove(struct gpio_chip of_node_put(np); } @@ -30,11 +30,10 @@ Signed-off-by: John Crispin +static int of_gpio_export_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; -+ struct device_node *cnp; + u32 val; + int nb = 0; + -+ for_each_child_of_node(np, cnp) { ++ for_each_child_of_node_scoped(np, cnp) { + const char *name = NULL; + int gpio; + bool dmc; diff --git a/target/linux/generic/hack-6.12/901-debloat_sock_diag.patch b/target/linux/generic/hack-6.12/901-debloat_sock_diag.patch index 17a22d0528..0091ec29bb 100644 --- a/target/linux/generic/hack-6.12/901-debloat_sock_diag.patch +++ b/target/linux/generic/hack-6.12/901-debloat_sock_diag.patch @@ -83,7 +83,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 *, -@@ -2342,9 +2359,11 @@ static void __sk_free(struct sock *sk) +@@ -2347,9 +2364,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.12/902-debloat_proc.patch b/target/linux/generic/hack-6.12/902-debloat_proc.patch index fe45d47ec5..7beda5de63 100644 --- a/target/linux/generic/hack-6.12/902-debloat_proc.patch +++ b/target/linux/generic/hack-6.12/902-debloat_proc.patch @@ -331,7 +331,7 @@ Signed-off-by: Felix Fietkau --- a/net/core/sock.c +++ b/net/core/sock.c -@@ -4285,6 +4285,8 @@ static __net_initdata struct pernet_oper +@@ -4294,6 +4294,8 @@ static __net_initdata struct pernet_oper static int __init proto_init(void) { diff --git a/target/linux/generic/hack-6.12/920-device_tree_cmdline.patch b/target/linux/generic/hack-6.12/920-device_tree_cmdline.patch index 4763e82421..2f89dcec70 100644 --- a/target/linux/generic/hack-6.12/920-device_tree_cmdline.patch +++ b/target/linux/generic/hack-6.12/920-device_tree_cmdline.patch @@ -15,7 +15,7 @@ Subject: [PATCH] of/ftd: add device tree cmdline strscpy(cmdline, p, min(l, COMMAND_LINE_SIZE)); + p = of_get_flat_dt_prop(node, "bootargs-append", &l); + if (p != NULL && l > 0) -+ strlcat(cmdline, p, min_t(int, strlen(cmdline) + (int)l, COMMAND_LINE_SIZE)); ++ strlcat(cmdline, p, COMMAND_LINE_SIZE); handle_cmdline: /* diff --git a/target/linux/generic/hack-6.18/400-mtd-spinand-Support-fmsh.patch b/target/linux/generic/hack-6.18/400-mtd-spinand-Support-fmsh.patch index 77272004c6..6ea49f7c5f 100644 --- a/target/linux/generic/hack-6.18/400-mtd-spinand-Support-fmsh.patch +++ b/target/linux/generic/hack-6.18/400-mtd-spinand-Support-fmsh.patch @@ -17,8 +17,8 @@ Signed-off-by: Jon Lin --- a/drivers/mtd/nand/spi/fmsh.c +++ b/drivers/mtd/nand/spi/fmsh.c -@@ -50,6 +50,144 @@ static const struct mtd_ooblayout_ops fm - .free = fm25s01a_ooblayout_free, +@@ -188,6 +188,115 @@ static const struct mtd_ooblayout_ops fm + .free = fm25s01bi3_ooblayout_free, }; +static int fm25s01_ooblayout_ecc(struct mtd_info *mtd, int section, @@ -129,43 +129,14 @@ Signed-off-by: Jon Lin + else + return -EBADMSG; +} -+ -+static int fm25g02b_ooblayout_ecc(struct mtd_info *mtd, int section, -+ struct mtd_oob_region *region) -+{ -+ if (section >= 8) -+ return -ERANGE; -+ -+ region->offset = 64 + section * 8; -+ region->length = 8; -+ -+ return 0; -+} -+ -+static int fm25g02b_ooblayout_free(struct mtd_info *mtd, int section, -+ struct mtd_oob_region *region) -+{ -+ if (section) -+ return -ERANGE; -+ -+ region->offset = 2; -+ region->length = 62; -+ -+ return 0; -+} -+ -+static const struct mtd_ooblayout_ops fm25g02b_ooblayout = { -+ .ecc = fm25g02b_ooblayout_ecc, -+ .free = fm25g02b_ooblayout_free, -+}; + static const struct spinand_info fmsh_spinand_table[] = { - SPINAND_INFO("FM25S01A", - SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE4), -@@ -60,6 +198,69 @@ static const struct spinand_info fmsh_sp - &update_cache_variants), - 0, - SPINAND_ECCINFO(&fm25s01a_ooblayout, NULL)), + SPINAND_INFO("FM25G01B", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xd1), +@@ -228,6 +337,51 @@ static const struct spinand_info fmsh_sp + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&fm25s01bi3_ooblayout, + fm25s01bi3_ecc_get_status)), + SPINAND_INFO("FM25S02A", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE5), + NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 2, 1, 1), @@ -193,15 +164,6 @@ Signed-off-by: Jon Lin + &update_cache_variants), + 0, + SPINAND_ECCINFO(&fm25s01_ooblayout, NULL)), -+ SPINAND_INFO("FM25S01BI3", -+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xD4), -+ NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), -+ NAND_ECCREQ(8, 512), -+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, -+ &write_cache_variants, -+ &update_cache_variants), -+ SPINAND_HAS_QE_BIT, -+ SPINAND_ECCINFO(&fm25s01_ooblayout, fm25s01bi3_ecc_ecc_get_status)), + SPINAND_INFO("FM25S02BI3-DND-A-G3", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xD6), + NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), @@ -211,15 +173,6 @@ Signed-off-by: Jon Lin + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&fm25s01_ooblayout, fm25s01bi3_ecc_ecc_get_status)), -+ SPINAND_INFO("FM25G02B", -+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xD2), -+ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), -+ NAND_ECCREQ(8, 528), -+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, -+ &write_cache_variants, -+ &update_cache_variants), -+ SPINAND_HAS_QE_BIT, -+ SPINAND_ECCINFO(&fm25g02b_ooblayout, fm25s01bi3_ecc_ecc_get_status)), + SPINAND_INFO("FM25G02D", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xF2), + NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1), diff --git a/target/linux/generic/hack-6.18/421-drivers-mtd-parsers-add-nvmem-support-to-cmdlinepart.patch b/target/linux/generic/hack-6.18/421-drivers-mtd-parsers-add-nvmem-support-to-cmdlinepart.patch index 190fecc1a0..9f8f8c112c 100644 --- a/target/linux/generic/hack-6.18/421-drivers-mtd-parsers-add-nvmem-support-to-cmdlinepart.patch +++ b/target/linux/generic/hack-6.18/421-drivers-mtd-parsers-add-nvmem-support-to-cmdlinepart.patch @@ -27,7 +27,7 @@ Signed-off-by: Ansuel Smith /* special size referring to all the remaining space in a partition */ #define SIZE_REMAINING ULLONG_MAX -@@ -315,6 +316,68 @@ static int mtdpart_setup_real(char *s) +@@ -315,6 +316,67 @@ static int mtdpart_setup_real(char *s) return 0; } @@ -37,7 +37,6 @@ Signed-off-by: Ansuel Smith +{ + struct device_node *mtd_node; + struct device_node *ofpart_node; -+ struct device_node *pp; + struct mtd_partition part; + const char *partname; + @@ -47,7 +46,7 @@ Signed-off-by: Ansuel Smith + + ofpart_node = of_get_child_by_name(mtd_node, "partitions"); + -+ for_each_child_of_node(ofpart_node, pp) { ++ for_each_child_of_node_scoped(ofpart_node, pp) { + const __be32 *reg; + int len; + int a_cells, s_cells; @@ -71,7 +70,7 @@ Signed-off-by: Ansuel Smith + + part.offset = of_read_number(reg, a_cells); + part.size = of_read_number(reg + a_cells, s_cells); -+ part.of_node = pp; ++ part.of_node = of_node_get(pp); + + partname = of_get_property(pp, "label", &len); + if (!partname) @@ -96,7 +95,7 @@ Signed-off-by: Ansuel Smith /* * Main function to be called from the MTD mapping driver/device to * obtain the partitioning information. At this point the command line -@@ -330,6 +393,7 @@ static int parse_cmdline_partitions(stru +@@ -330,6 +392,7 @@ static int parse_cmdline_partitions(stru int i, err; struct cmdline_mtd_partition *part; const char *mtd_id = master->name; @@ -104,7 +103,7 @@ Signed-off-by: Ansuel Smith /* parse command line */ if (!cmdline_parsed) { -@@ -374,6 +438,13 @@ static int parse_cmdline_partitions(stru +@@ -374,6 +437,13 @@ static int parse_cmdline_partitions(stru sizeof(*part->parts) * (part->num_parts - i)); i--; } diff --git a/target/linux/generic/hack-6.18/721-net-add-packet-mangeling.patch b/target/linux/generic/hack-6.18/721-net-add-packet-mangeling.patch index 0db4849715..3c19fe1782 100644 --- a/target/linux/generic/hack-6.18/721-net-add-packet-mangeling.patch +++ b/target/linux/generic/hack-6.18/721-net-add-packet-mangeling.patch @@ -97,7 +97,7 @@ Signed-off-by: Felix Fietkau help --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -3870,6 +3870,11 @@ static int xmit_one(struct sk_buff *skb, +@@ -3871,6 +3871,11 @@ static int xmit_one(struct sk_buff *skb, if (dev_nit_active_rcu(dev)) dev_queue_xmit_nit(skb, dev); diff --git a/target/linux/generic/hack-6.18/780-usb-net-MeigLink_modem_support.patch b/target/linux/generic/hack-6.18/780-usb-net-MeigLink_modem_support.patch index eff038fbd0..feeb329ca1 100644 --- a/target/linux/generic/hack-6.18/780-usb-net-MeigLink_modem_support.patch +++ b/target/linux/generic/hack-6.18/780-usb-net-MeigLink_modem_support.patch @@ -32,7 +32,7 @@ Subject: [PATCH] net/usb/qmi_wwan: add MeigLink modem support {QMI_FIXED_INTF(0x0408, 0xea42, 4)}, /* Yota / Megafon M100-1 */ --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c -@@ -247,6 +247,11 @@ static void option_instat_callback(struc +@@ -248,6 +248,11 @@ static void option_instat_callback(struc #define UBLOX_PRODUCT_R410M 0x90b2 /* These Yuga products use Qualcomm's vendor ID */ #define YUGA_PRODUCT_CLM920_NC5 0x9625 @@ -44,7 +44,7 @@ Subject: [PATCH] net/usb/qmi_wwan: add MeigLink modem support #define QUECTEL_VENDOR_ID 0x2c7c /* These Quectel products use Quectel's vendor ID */ -@@ -1156,6 +1161,11 @@ static const struct usb_device_id option +@@ -1159,6 +1164,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) }, @@ -56,7 +56,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), -@@ -1197,6 +1207,11 @@ static const struct usb_device_id option +@@ -1200,6 +1210,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.18/800-GPIO-add-named-gpio-exports.patch b/target/linux/generic/hack-6.18/800-GPIO-add-named-gpio-exports.patch index 63a49702f7..a18015d0b9 100644 --- a/target/linux/generic/hack-6.18/800-GPIO-add-named-gpio-exports.patch +++ b/target/linux/generic/hack-6.18/800-GPIO-add-named-gpio-exports.patch @@ -15,7 +15,7 @@ Signed-off-by: John Crispin #include "gpiolib.h" #include "gpiolib-of.h" -@@ -1302,3 +1304,73 @@ bool of_gpiochip_instance_match(struct g +@@ -1302,3 +1304,72 @@ bool of_gpiochip_instance_match(struct g return false; } @@ -30,11 +30,10 @@ Signed-off-by: John Crispin +static int of_gpio_export_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; -+ struct device_node *cnp; + u32 val; + int nb = 0; + -+ for_each_child_of_node(np, cnp) { ++ for_each_child_of_node_scoped(np, cnp) { + const char *name = NULL; + int gpio; + bool dmc; diff --git a/target/linux/generic/hack-6.18/901-debloat_sock_diag.patch b/target/linux/generic/hack-6.18/901-debloat_sock_diag.patch index 1308c0d971..69be731568 100644 --- a/target/linux/generic/hack-6.18/901-debloat_sock_diag.patch +++ b/target/linux/generic/hack-6.18/901-debloat_sock_diag.patch @@ -83,7 +83,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 *, -@@ -2406,9 +2423,11 @@ static void __sk_free(struct sock *sk) +@@ -2411,9 +2428,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.18/902-debloat_proc.patch b/target/linux/generic/hack-6.18/902-debloat_proc.patch index e6829065a4..4afc1e8c5a 100644 --- a/target/linux/generic/hack-6.18/902-debloat_proc.patch +++ b/target/linux/generic/hack-6.18/902-debloat_proc.patch @@ -331,7 +331,7 @@ Signed-off-by: Felix Fietkau --- a/net/core/sock.c +++ b/net/core/sock.c -@@ -4349,6 +4349,8 @@ static __net_initdata struct pernet_oper +@@ -4358,6 +4358,8 @@ static __net_initdata struct pernet_oper static int __init proto_init(void) { diff --git a/target/linux/generic/hack-6.18/920-device_tree_cmdline.patch b/target/linux/generic/hack-6.18/920-device_tree_cmdline.patch index 8bc6704d48..40c42e7bfb 100644 --- a/target/linux/generic/hack-6.18/920-device_tree_cmdline.patch +++ b/target/linux/generic/hack-6.18/920-device_tree_cmdline.patch @@ -15,7 +15,7 @@ Subject: [PATCH] of/ftd: add device tree cmdline strscpy(cmdline, p, min(l, COMMAND_LINE_SIZE)); + p = of_get_flat_dt_prop(node, "bootargs-append", &l); + if (p != NULL && l > 0) -+ strlcat(cmdline, p, min_t(int, strlen(cmdline) + (int)l, COMMAND_LINE_SIZE)); ++ strlcat(cmdline, p, COMMAND_LINE_SIZE); handle_cmdline: /* diff --git a/target/linux/generic/kernel-6.12 b/target/linux/generic/kernel-6.12 index 2c776bd716..424db9bb4e 100644 --- a/target/linux/generic/kernel-6.12 +++ b/target/linux/generic/kernel-6.12 @@ -1,2 +1,2 @@ -LINUX_VERSION-6.12 = .93 -LINUX_KERNEL_HASH-6.12.93 = 492648a87c0b69c5ac7f43be64792b9000e3439550d4e82e4a14710c49094fa3 +LINUX_VERSION-6.12 = .94 +LINUX_KERNEL_HASH-6.12.94 = e998a232b9418db3301cb58468e291a4f41d6ab8306029b30d991f56251dc8d2 diff --git a/target/linux/generic/kernel-6.18 b/target/linux/generic/kernel-6.18 index b268a2d8f1..efbfe51433 100644 --- a/target/linux/generic/kernel-6.18 +++ b/target/linux/generic/kernel-6.18 @@ -1,2 +1,2 @@ -LINUX_VERSION-6.18 = .35 -LINUX_KERNEL_HASH-6.18.35 = f78602932219125e211c5f5bfd84edcfd4ec5ce88fc944f8248413f665bef236 +LINUX_VERSION-6.18 = .37 +LINUX_KERNEL_HASH-6.18.37 = a83cd200e6646db52866b8309e9137b9e9048b613cbda10ced2b811aae125255 diff --git a/target/linux/generic/pending-6.12/103-kbuild-export-SUBARCH.patch b/target/linux/generic/pending-6.12/103-kbuild-export-SUBARCH.patch index f11976b9e3..a47479b7ca 100644 --- a/target/linux/generic/pending-6.12/103-kbuild-export-SUBARCH.patch +++ b/target/linux/generic/pending-6.12/103-kbuild-export-SUBARCH.patch @@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau --- a/Makefile +++ b/Makefile -@@ -593,7 +593,7 @@ export RUSTC_BOOTSTRAP := 1 +@@ -594,7 +594,7 @@ export RUSTC_BOOTSTRAP := 1 # Allows finding `.clippy.toml` in out-of-srctree builds. export CLIPPY_CONF_DIR := $(srctree) diff --git a/target/linux/generic/pending-6.12/430-mtd-add-myloader-partition-parser.patch b/target/linux/generic/pending-6.12/430-mtd-add-myloader-partition-parser.patch index 8ce112357a..a6b1c613f3 100644 --- a/target/linux/generic/pending-6.12/430-mtd-add-myloader-partition-parser.patch +++ b/target/linux/generic/pending-6.12/430-mtd-add-myloader-partition-parser.patch @@ -45,7 +45,7 @@ Signed-off-by: Adrian Schmutzler ofpart-$(CONFIG_MTD_OF_PARTS_BCM4908) += ofpart_bcm4908.o --- /dev/null +++ b/drivers/mtd/parsers/myloader.c -@@ -0,0 +1,181 @@ +@@ -0,0 +1,168 @@ +/* + * Parse MyLoader-style flash partition tables and produce a Linux partition + * array to match. @@ -149,8 +149,8 @@ Signed-off-by: Adrian Schmutzler + num_parts++; + } + -+ mtd_parts = kzalloc((num_parts * sizeof(*mtd_part) + -+ num_parts * PART_NAME_LEN), GFP_KERNEL); ++ mtd_parts = kzalloc(size_add(size_mul(num_parts, sizeof(*mtd_part)), ++ size_mul(num_parts, PART_NAME_LEN)), GFP_KERNEL); + + if (!mtd_parts) { + ret = -ENOMEM; @@ -160,7 +160,7 @@ Signed-off-by: Adrian Schmutzler + mtd_part = mtd_parts; + names = (char *)&mtd_parts[num_parts]; + -+ strncpy(names, "myloader", PART_NAME_LEN); ++ strscpy_pad(names, "myloader", PART_NAME_LEN); + mtd_part->name = names; + mtd_part->offset = 0; + mtd_part->size = offset; @@ -168,7 +168,7 @@ Signed-off-by: Adrian Schmutzler + mtd_part++; + names += PART_NAME_LEN; + -+ strncpy(names, "partition_table", PART_NAME_LEN); ++ strscpy_pad(names, "partition_table", PART_NAME_LEN); + mtd_part->name = names; + mtd_part->offset = offset; + mtd_part->size = blocklen; @@ -183,7 +183,7 @@ Signed-off-by: Adrian Schmutzler + continue; + + if ((buf->names[i][0]) && (buf->names[i][0] != '\xff')) -+ strncpy(names, buf->names[i], PART_NAME_LEN); ++ strscpy_pad(names, buf->names[i], PART_NAME_LEN); + else + snprintf(names, PART_NAME_LEN, "partition%d", i); + @@ -209,20 +209,7 @@ Signed-off-by: Adrian Schmutzler + .name = "MyLoader", +}; + -+static int __init myloader_mtd_parser_init(void) -+{ -+ register_mtd_parser(&myloader_mtd_parser); -+ -+ return 0; -+} -+ -+static void __exit myloader_mtd_parser_exit(void) -+{ -+ deregister_mtd_parser(&myloader_mtd_parser); -+} -+ -+module_init(myloader_mtd_parser_init); -+module_exit(myloader_mtd_parser_exit); ++module_mtd_part_parser(myloader_mtd_parser); + +MODULE_AUTHOR("Gabor Juhos "); +MODULE_DESCRIPTION("Parsing code for MyLoader partition tables"); diff --git a/target/linux/generic/pending-6.12/610-netfilter_match_bypass_default_checks.patch b/target/linux/generic/pending-6.12/610-netfilter_match_bypass_default_checks.patch deleted file mode 100644 index fd22200a84..0000000000 --- a/target/linux/generic/pending-6.12/610-netfilter_match_bypass_default_checks.patch +++ /dev/null @@ -1,110 +0,0 @@ -From: Felix Fietkau -Subject: kernel: add a new version of my netfilter speedup patches for linux 2.6.39 and 3.0 - -Signed-off-by: Felix Fietkau ---- - include/uapi/linux/netfilter_ipv4/ip_tables.h | 1 + - net/ipv4/netfilter/ip_tables.c | 37 +++++++++++++++++++++++++++ - 2 files changed, 38 insertions(+) - ---- a/include/uapi/linux/netfilter_ipv4/ip_tables.h -+++ b/include/uapi/linux/netfilter_ipv4/ip_tables.h -@@ -89,6 +89,7 @@ struct ipt_ip { - #define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */ - #define IPT_F_GOTO 0x02 /* Set if jump is a goto */ - #define IPT_F_MASK 0x03 /* All possible flag bits mask. */ -+#define IPT_F_NO_DEF_MATCH 0x80 /* Internal: no default match rules present */ - - /* Values for "inv" field in struct ipt_ip. */ - #define IPT_INV_VIA_IN 0x01 /* Invert the sense of IN IFACE. */ ---- a/net/ipv4/netfilter/ip_tables.c -+++ b/net/ipv4/netfilter/ip_tables.c -@@ -48,6 +48,9 @@ ip_packet_match(const struct iphdr *ip, - { - unsigned long ret; - -+ if (ipinfo->flags & IPT_F_NO_DEF_MATCH) -+ return true; -+ - if (NF_INVF(ipinfo, IPT_INV_SRCIP, - (ip->saddr & ipinfo->smsk.s_addr) != ipinfo->src.s_addr) || - NF_INVF(ipinfo, IPT_INV_DSTIP, -@@ -78,6 +81,29 @@ ip_packet_match(const struct iphdr *ip, - return true; - } - -+static void -+ip_checkdefault(struct ipt_ip *ip) -+{ -+ static const char iface_mask[IFNAMSIZ] = {}; -+ -+ if (ip->invflags || ip->flags & IPT_F_FRAG) -+ return; -+ -+ if (memcmp(ip->iniface_mask, iface_mask, IFNAMSIZ) != 0) -+ return; -+ -+ if (memcmp(ip->outiface_mask, iface_mask, IFNAMSIZ) != 0) -+ return; -+ -+ if (ip->smsk.s_addr || ip->dmsk.s_addr) -+ return; -+ -+ if (ip->proto) -+ return; -+ -+ ip->flags |= IPT_F_NO_DEF_MATCH; -+} -+ - static bool - ip_checkentry(const struct ipt_ip *ip) - { -@@ -523,6 +549,8 @@ find_check_entry(struct ipt_entry *e, st - struct xt_mtchk_param mtpar; - struct xt_entry_match *ematch; - -+ ip_checkdefault(&e->ip); -+ - if (!xt_percpu_counter_alloc(alloc_state, &e->counters)) - return -ENOMEM; - -@@ -817,6 +845,7 @@ copy_entries_to_user(unsigned int total_ - const struct xt_table_info *private = table->private; - int ret = 0; - const void *loc_cpu_entry; -+ u8 flags; - - counters = alloc_counters(table); - if (IS_ERR(counters)) -@@ -844,6 +873,14 @@ copy_entries_to_user(unsigned int total_ - goto free_counters; - } - -+ flags = e->ip.flags & IPT_F_MASK; -+ if (copy_to_user(userptr + off -+ + offsetof(struct ipt_entry, ip.flags), -+ &flags, sizeof(flags)) != 0) { -+ ret = -EFAULT; -+ goto free_counters; -+ } -+ - for (i = sizeof(struct ipt_entry); - i < e->target_offset; - i += m->u.match_size) { -@@ -1225,12 +1262,15 @@ compat_copy_entry_to_user(struct ipt_ent - compat_uint_t origsize; - const struct xt_entry_match *ematch; - int ret = 0; -+ u8 flags = e->ip.flags & IPT_F_MASK; - - origsize = *size; - ce = *dstptr; - if (copy_to_user(ce, e, sizeof(struct ipt_entry)) != 0 || - copy_to_user(&ce->counters, &counters[i], -- sizeof(counters[i])) != 0) -+ sizeof(counters[i])) != 0 || -+ copy_to_user(&ce->ip.flags, &flags, -+ sizeof(flags)) != 0) - return -EFAULT; - - *dstptr += sizeof(struct compat_ipt_entry); diff --git a/target/linux/generic/pending-6.12/611-netfilter_match_bypass_default_table.patch b/target/linux/generic/pending-6.12/611-netfilter_match_bypass_default_table.patch deleted file mode 100644 index 9f0efe4ec4..0000000000 --- a/target/linux/generic/pending-6.12/611-netfilter_match_bypass_default_table.patch +++ /dev/null @@ -1,106 +0,0 @@ -From: Felix Fietkau -Subject: netfilter: match bypass default table - -Signed-off-by: Felix Fietkau ---- - net/ipv4/netfilter/ip_tables.c | 79 +++++++++++++++++++++++++++++++----------- - 1 file changed, 58 insertions(+), 21 deletions(-) - ---- a/net/ipv4/netfilter/ip_tables.c -+++ b/net/ipv4/netfilter/ip_tables.c -@@ -244,6 +244,33 @@ struct ipt_entry *ipt_next_entry(const s - return (void *)entry + entry->next_offset; - } - -+static bool -+ipt_handle_default_rule(struct ipt_entry *e, unsigned int *verdict) -+{ -+ struct xt_entry_target *t; -+ struct xt_standard_target *st; -+ -+ if (e->target_offset != sizeof(struct ipt_entry)) -+ return false; -+ -+ if (!(e->ip.flags & IPT_F_NO_DEF_MATCH)) -+ return false; -+ -+ t = ipt_get_target(e); -+ if (t->u.kernel.target->target) -+ return false; -+ -+ st = (struct xt_standard_target *) t; -+ if (st->verdict == XT_RETURN) -+ return false; -+ -+ if (st->verdict >= 0) -+ return false; -+ -+ *verdict = (unsigned)(-st->verdict) - 1; -+ return true; -+} -+ - /* Returns one of the generic firewall policies, like NF_ACCEPT. */ - unsigned int - ipt_do_table(void *priv, -@@ -265,27 +292,28 @@ ipt_do_table(void *priv, - unsigned int addend; - - /* Initialization */ -+ WARN_ON(!(table->valid_hooks & (1 << hook))); -+ local_bh_disable(); -+ private = READ_ONCE(table->private); /* Address dependency. */ -+ cpu = smp_processor_id(); -+ table_base = private->entries; -+ -+ e = get_entry(table_base, private->hook_entry[hook]); -+ if (ipt_handle_default_rule(e, &verdict)) { -+ struct xt_counters *counter; -+ -+ counter = xt_get_this_cpu_counter(&e->counters); -+ ADD_COUNTER(*counter, skb->len, 1); -+ local_bh_enable(); -+ return verdict; -+ } -+ - stackidx = 0; - ip = ip_hdr(skb); - indev = state->in ? state->in->name : nulldevname; - outdev = state->out ? state->out->name : nulldevname; -- /* We handle fragments by dealing with the first fragment as -- * if it was a normal packet. All other fragments are treated -- * normally, except that they will NEVER match rules that ask -- * things we don't know, ie. tcp syn flag or ports). If the -- * rule is also a fragment-specific rule, non-fragments won't -- * match it. */ -- acpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET; -- acpar.thoff = ip_hdrlen(skb); -- acpar.hotdrop = false; -- acpar.state = state; - -- WARN_ON(!(table->valid_hooks & (1 << hook))); -- local_bh_disable(); - addend = xt_write_recseq_begin(); -- private = READ_ONCE(table->private); /* Address dependency. */ -- cpu = smp_processor_id(); -- table_base = private->entries; - jumpstack = (struct ipt_entry **)private->jumpstack[cpu]; - - /* Switch to alternate jumpstack if we're being invoked via TEE. -@@ -298,7 +326,16 @@ ipt_do_table(void *priv, - if (static_key_false(&xt_tee_enabled)) - jumpstack += private->stacksize * __this_cpu_read(nf_skb_duplicated); - -- e = get_entry(table_base, private->hook_entry[hook]); -+ /* We handle fragments by dealing with the first fragment as -+ * if it was a normal packet. All other fragments are treated -+ * normally, except that they will NEVER match rules that ask -+ * things we don't know, ie. tcp syn flag or ports). If the -+ * rule is also a fragment-specific rule, non-fragments won't -+ * match it. */ -+ acpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET; -+ acpar.thoff = ip_hdrlen(skb); -+ acpar.hotdrop = false; -+ acpar.state = state; - - do { - const struct xt_entry_target *t; diff --git a/target/linux/generic/pending-6.12/612-netfilter_match_reduce_memory_access.patch b/target/linux/generic/pending-6.12/612-netfilter_match_reduce_memory_access.patch deleted file mode 100644 index 7f291fc008..0000000000 --- a/target/linux/generic/pending-6.12/612-netfilter_match_reduce_memory_access.patch +++ /dev/null @@ -1,22 +0,0 @@ -From: Felix Fietkau -Subject: netfilter: reduce match memory access - -Signed-off-by: Felix Fietkau ---- - net/ipv4/netfilter/ip_tables.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/net/ipv4/netfilter/ip_tables.c -+++ b/net/ipv4/netfilter/ip_tables.c -@@ -51,9 +51,9 @@ ip_packet_match(const struct iphdr *ip, - if (ipinfo->flags & IPT_F_NO_DEF_MATCH) - return true; - -- if (NF_INVF(ipinfo, IPT_INV_SRCIP, -+ if (NF_INVF(ipinfo, IPT_INV_SRCIP, ipinfo->smsk.s_addr && - (ip->saddr & ipinfo->smsk.s_addr) != ipinfo->src.s_addr) || -- NF_INVF(ipinfo, IPT_INV_DSTIP, -+ NF_INVF(ipinfo, IPT_INV_DSTIP, ipinfo->dmsk.s_addr && - (ip->daddr & ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr)) - return false; - diff --git a/target/linux/generic/pending-6.12/681-net-remove-NETIF_F_GSO_FRAGLIST-from-NETIF_F_GSO_SOF.patch b/target/linux/generic/pending-6.12/681-net-remove-NETIF_F_GSO_FRAGLIST-from-NETIF_F_GSO_SOF.patch index 21f08fac78..800613b392 100644 --- a/target/linux/generic/pending-6.12/681-net-remove-NETIF_F_GSO_FRAGLIST-from-NETIF_F_GSO_SOF.patch +++ b/target/linux/generic/pending-6.12/681-net-remove-NETIF_F_GSO_FRAGLIST-from-NETIF_F_GSO_SOF.patch @@ -96,7 +96,7 @@ Signed-off-by: Felix Fietkau } --- a/net/core/sock.c +++ b/net/core/sock.c -@@ -2557,7 +2557,7 @@ void sk_setup_caps(struct sock *sk, stru +@@ -2562,7 +2562,7 @@ void sk_setup_caps(struct sock *sk, stru icsk->icsk_ack.dst_quick_ack = dst_metric(dst, RTAX_QUICKACK); } if (sk->sk_route_caps & NETIF_F_GSO) diff --git a/target/linux/generic/pending-6.12/703-phy-add-detach-callback-to-struct-phy_driver.patch b/target/linux/generic/pending-6.12/703-phy-add-detach-callback-to-struct-phy_driver.patch index 474470b806..5c8dbcc3fe 100644 --- a/target/linux/generic/pending-6.12/703-phy-add-detach-callback-to-struct-phy_driver.patch +++ b/target/linux/generic/pending-6.12/703-phy-add-detach-callback-to-struct-phy_driver.patch @@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c -@@ -2035,6 +2035,9 @@ void phy_detach(struct phy_device *phyde +@@ -2038,6 +2038,9 @@ void phy_detach(struct phy_device *phyde phydev->devlink = NULL; } diff --git a/target/linux/generic/pending-6.12/920-mangle_bootargs.patch b/target/linux/generic/pending-6.12/920-mangle_bootargs.patch index c3b2f9dd50..636bf8f90e 100644 --- a/target/linux/generic/pending-6.12/920-mangle_bootargs.patch +++ b/target/linux/generic/pending-6.12/920-mangle_bootargs.patch @@ -44,12 +44,12 @@ Signed-off-by: Imre Kaloz + rootdev = strstr(command_line, "root=/dev/mtdblock"); + + if (rootdev) -+ strncpy(rootdev, "mangled_rootblock=", 18); ++ memcpy(rootdev, "mangled_rootblock=", 18); + + rootfs = strstr(command_line, "rootfstype"); + + if (rootfs) -+ strncpy(rootfs, "mangled_fs", 10); ++ memcpy(rootfs, "mangled_fs", 10); + +} +#else diff --git a/target/linux/generic/pending-6.18/103-kbuild-export-SUBARCH.patch b/target/linux/generic/pending-6.18/103-kbuild-export-SUBARCH.patch index 8d204b98f6..0f0bd49092 100644 --- a/target/linux/generic/pending-6.18/103-kbuild-export-SUBARCH.patch +++ b/target/linux/generic/pending-6.18/103-kbuild-export-SUBARCH.patch @@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau --- a/Makefile +++ b/Makefile -@@ -628,7 +628,7 @@ export RUSTC_BOOTSTRAP := 1 +@@ -629,7 +629,7 @@ export RUSTC_BOOTSTRAP := 1 # Allows finding `.clippy.toml` in out-of-srctree builds. export CLIPPY_CONF_DIR := $(srctree) diff --git a/target/linux/generic/pending-6.18/331-MIPS-smp-report-dying-CPU-to-RCU-in-stop_this_cpu.patch b/target/linux/generic/pending-6.18/331-MIPS-smp-report-dying-CPU-to-RCU-in-stop_this_cpu.patch deleted file mode 100644 index fc8cf0f5da..0000000000 --- a/target/linux/generic/pending-6.18/331-MIPS-smp-report-dying-CPU-to-RCU-in-stop_this_cpu.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jonas Jelonek -Date: Thu, 04 Jun 2026 00:00:00 +0200 -Subject: [PATCH] MIPS: smp: report dying CPU to RCU in stop_this_cpu() - -smp_send_stop() parks all secondary CPUs in stop_this_cpu(). The function -marks the CPU offline for the scheduler via set_cpu_online(false) but never -informs RCU, so RCU keeps expecting a quiescent state from CPUs that are -now spinning forever with interrupts disabled. - -As long as nothing waits for an RCU grace period after smp_send_stop() this -is harmless, which is why it went unnoticed. Since v6.18.34, however, -irq_work_sync() calls synchronize_rcu() on architectures without an -irq_work self-IPI, i.e. where arch_irq_work_has_interrupt() returns false. -That is the asm-generic default used by MIPS. Any irq_work_sync() issued in -the reboot/shutdown path after smp_send_stop() then blocks on a grace period -that can never complete, hanging the reboot: - - WARNING: CPU: 0 PID: 15 at kernel/irq_work.c:144 irq_work_queue_on - ... - rcu: INFO: rcu_sched detected stalls on CPUs/tasks: - rcu: Offline CPU 1 blocking current GP. - rcu: Offline CPU 2 blocking current GP. - rcu: Offline CPU 3 blocking current GP. - -Call rcutree_report_cpu_dead() once interrupts are disabled, mirroring the -generic CPU-hotplug offline path (and arm64's stop handling), so RCU stops -waiting on the parked CPUs and grace periods can still complete. - -Fixes: 91840be8f710 ("irq_work: Fix use-after-free in irq_work_single() on PREEMPT_RT") -Signed-off-by: Jonas Jelonek ---- - arch/mips/kernel/smp.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/arch/mips/kernel/smp.c -+++ b/arch/mips/kernel/smp.c -@@ -20,6 +20,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -422,6 +423,7 @@ static void stop_this_cpu(void *dummy) - set_cpu_online(smp_processor_id(), false); - calculate_cpu_foreign_map(); - local_irq_disable(); -+ rcutree_report_cpu_dead(); - while (1); - } - diff --git a/target/linux/generic/pending-6.18/401-mtd-spinand-fmsh-add-support-for-FM25G0102B.patch b/target/linux/generic/pending-6.18/401-mtd-spinand-fmsh-add-support-for-FM25G0102B.patch new file mode 100644 index 0000000000..e3a5a10e5b --- /dev/null +++ b/target/linux/generic/pending-6.18/401-mtd-spinand-fmsh-add-support-for-FM25G0102B.patch @@ -0,0 +1,152 @@ +From: Ziyang Huang +To: miquel.raynal@bootlin.com +Subject: [PATCH v3] mtd: spinand: fmsh: add support for FM25G{01,02}B +Date: Sun, 31 May 2026 21:05:17 +0800 + +Add support for FudanMicro FM25G01B SPI NAND and FudanMicro FM25G02B SPI +NAND. + +FM25G01B datasheet: https://www.fmsh.com/nvm/FM25G01B_ds_eng.pdf +FM25G02B datasheet: https://www.fmsh.com/nvm/FM25G02B_ds_eng.pdf + +Signed-off-by: Ziyang Huang +Link: https://lore.kernel.org/all/SEYPR01MB58821E380C5DD8F7B3FFDA23C9142@SEYPR01MB5882.apcprd01.prod.exchangelabs.com/ +[Fix chip names in the commit message, mask macro in the switch operator] +Signed-off-by: Mikhail Zhilkin +--- +Changes since v2: + More verbose commit message. + Use only one section in fm25g01b_ooblayout_free(). + +Changes since v1: + Fix copy-paste issue. (Correct FM25G01B size.) + + drivers/mtd/nand/spi/fmsh.c | 96 +++++++++++++++++++++++++++++++++++++ + 1 file changed, 96 insertions(+) + +--- a/drivers/mtd/nand/spi/fmsh.c ++++ b/drivers/mtd/nand/spi/fmsh.c +@@ -9,6 +9,16 @@ + #include + #include + ++#define FM25G01B_STATUS_ECC_MASK (7 << 4) ++ #define FM25G01B_STATUS_ECC_NO_BITFLIPS (0 << 4) ++ #define FM25G01B_STATUS_ECC_1_3_BITFLIPS (1 << 4) ++ #define FM25G01B_STATUS_ECC_4_BITFLIPS (2 << 4) ++ #define FM25G01B_STATUS_ECC_5_BITFLIPS (3 << 4) ++ #define FM25G01B_STATUS_ECC_6_BITFLIPS (4 << 4) ++ #define FM25G01B_STATUS_ECC_7_BITFLIPS (5 << 4) ++ #define FM25G01B_STATUS_ECC_8_BITFLIPS (6 << 4) ++ #define FM25G01B_STATUS_ECC_UNCOR_ERROR (7 << 4) ++ + #define FM25S01BI3_STATUS_ECC_MASK (7 << 4) + #define FM25S01BI3_STATUS_ECC_NO_BITFLIPS (0 << 4) + #define FM25S01BI3_STATUS_ECC_1_3_BITFLIPS (1 << 4) +@@ -34,6 +44,67 @@ static SPINAND_OP_VARIANTS(update_cache_ + SPINAND_PROG_LOAD_1S_1S_4S_OP(false, 0, NULL, 0), + SPINAND_PROG_LOAD_1S_1S_1S_OP(false, 0, NULL, 0)); + ++ ++static int fm25g01b_ooblayout_ecc(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ if (section) ++ return -ERANGE; ++ ++ region->offset = 64; ++ region->length = 64; ++ ++ return 0; ++} ++ ++static int fm25g01b_ooblayout_free(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ if (section) ++ return -ERANGE; ++ ++ /* reserve 2 bytes for the BBM */ ++ region->offset = 2; ++ region->length = 62; ++ ++ return 0; ++} ++ ++static int fm25g01b_ecc_get_status(struct spinand_device *spinand, ++ u8 status) ++{ ++ switch (status & FM25G01B_STATUS_ECC_MASK) { ++ case FM25G01B_STATUS_ECC_NO_BITFLIPS: ++ return 0; ++ ++ case FM25G01B_STATUS_ECC_1_3_BITFLIPS: ++ return 3; ++ ++ case FM25G01B_STATUS_ECC_4_BITFLIPS: ++ return 4; ++ ++ case FM25G01B_STATUS_ECC_5_BITFLIPS: ++ return 5; ++ ++ case FM25G01B_STATUS_ECC_6_BITFLIPS: ++ return 6; ++ ++ case FM25G01B_STATUS_ECC_7_BITFLIPS: ++ return 7; ++ ++ case FM25G01B_STATUS_ECC_8_BITFLIPS: ++ return 8; ++ ++ case FM25G01B_STATUS_ECC_UNCOR_ERROR: ++ return -EBADMSG; ++ ++ default: ++ break; ++ } ++ ++ return -EINVAL; ++} ++ + static int fm25s01a_ooblayout_ecc(struct mtd_info *mtd, int section, + struct mtd_oob_region *region) + { +@@ -102,6 +173,11 @@ static int fm25s01bi3_ooblayout_free(str + return 0; + } + ++static const struct mtd_ooblayout_ops fm25g01b_ooblayout = { ++ .ecc = fm25g01b_ooblayout_ecc, ++ .free = fm25g01b_ooblayout_free, ++}; ++ + static const struct mtd_ooblayout_ops fm25s01a_ooblayout = { + .ecc = fm25s01a_ooblayout_ecc, + .free = fm25s01a_ooblayout_free, +@@ -113,6 +189,26 @@ static const struct mtd_ooblayout_ops fm + }; + + static const struct spinand_info fmsh_spinand_table[] = { ++ SPINAND_INFO("FM25G01B", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xd1), ++ NAND_MEMORG(1, 2048, 128, 64, 1024, 21, 1, 1, 1), ++ NAND_ECCREQ(8, 528), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&fm25g01b_ooblayout, ++ fm25g01b_ecc_get_status)), ++ SPINAND_INFO("FM25G02B", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xd2), ++ NAND_MEMORG(1, 2048, 128, 64, 2048, 41, 1, 1, 1), ++ NAND_ECCREQ(8, 528), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&fm25g01b_ooblayout, ++ fm25g01b_ecc_get_status)), + SPINAND_INFO("FM25S01A", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE4), + NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), diff --git a/target/linux/generic/pending-6.18/430-mtd-add-myloader-partition-parser.patch b/target/linux/generic/pending-6.18/430-mtd-add-myloader-partition-parser.patch index 8ce112357a..a6b1c613f3 100644 --- a/target/linux/generic/pending-6.18/430-mtd-add-myloader-partition-parser.patch +++ b/target/linux/generic/pending-6.18/430-mtd-add-myloader-partition-parser.patch @@ -45,7 +45,7 @@ Signed-off-by: Adrian Schmutzler ofpart-$(CONFIG_MTD_OF_PARTS_BCM4908) += ofpart_bcm4908.o --- /dev/null +++ b/drivers/mtd/parsers/myloader.c -@@ -0,0 +1,181 @@ +@@ -0,0 +1,168 @@ +/* + * Parse MyLoader-style flash partition tables and produce a Linux partition + * array to match. @@ -149,8 +149,8 @@ Signed-off-by: Adrian Schmutzler + num_parts++; + } + -+ mtd_parts = kzalloc((num_parts * sizeof(*mtd_part) + -+ num_parts * PART_NAME_LEN), GFP_KERNEL); ++ mtd_parts = kzalloc(size_add(size_mul(num_parts, sizeof(*mtd_part)), ++ size_mul(num_parts, PART_NAME_LEN)), GFP_KERNEL); + + if (!mtd_parts) { + ret = -ENOMEM; @@ -160,7 +160,7 @@ Signed-off-by: Adrian Schmutzler + mtd_part = mtd_parts; + names = (char *)&mtd_parts[num_parts]; + -+ strncpy(names, "myloader", PART_NAME_LEN); ++ strscpy_pad(names, "myloader", PART_NAME_LEN); + mtd_part->name = names; + mtd_part->offset = 0; + mtd_part->size = offset; @@ -168,7 +168,7 @@ Signed-off-by: Adrian Schmutzler + mtd_part++; + names += PART_NAME_LEN; + -+ strncpy(names, "partition_table", PART_NAME_LEN); ++ strscpy_pad(names, "partition_table", PART_NAME_LEN); + mtd_part->name = names; + mtd_part->offset = offset; + mtd_part->size = blocklen; @@ -183,7 +183,7 @@ Signed-off-by: Adrian Schmutzler + continue; + + if ((buf->names[i][0]) && (buf->names[i][0] != '\xff')) -+ strncpy(names, buf->names[i], PART_NAME_LEN); ++ strscpy_pad(names, buf->names[i], PART_NAME_LEN); + else + snprintf(names, PART_NAME_LEN, "partition%d", i); + @@ -209,20 +209,7 @@ Signed-off-by: Adrian Schmutzler + .name = "MyLoader", +}; + -+static int __init myloader_mtd_parser_init(void) -+{ -+ register_mtd_parser(&myloader_mtd_parser); -+ -+ return 0; -+} -+ -+static void __exit myloader_mtd_parser_exit(void) -+{ -+ deregister_mtd_parser(&myloader_mtd_parser); -+} -+ -+module_init(myloader_mtd_parser_init); -+module_exit(myloader_mtd_parser_exit); ++module_mtd_part_parser(myloader_mtd_parser); + +MODULE_AUTHOR("Gabor Juhos "); +MODULE_DESCRIPTION("Parsing code for MyLoader partition tables"); diff --git a/target/linux/generic/pending-6.18/610-netfilter_match_bypass_default_checks.patch b/target/linux/generic/pending-6.18/610-netfilter_match_bypass_default_checks.patch deleted file mode 100644 index fd22200a84..0000000000 --- a/target/linux/generic/pending-6.18/610-netfilter_match_bypass_default_checks.patch +++ /dev/null @@ -1,110 +0,0 @@ -From: Felix Fietkau -Subject: kernel: add a new version of my netfilter speedup patches for linux 2.6.39 and 3.0 - -Signed-off-by: Felix Fietkau ---- - include/uapi/linux/netfilter_ipv4/ip_tables.h | 1 + - net/ipv4/netfilter/ip_tables.c | 37 +++++++++++++++++++++++++++ - 2 files changed, 38 insertions(+) - ---- a/include/uapi/linux/netfilter_ipv4/ip_tables.h -+++ b/include/uapi/linux/netfilter_ipv4/ip_tables.h -@@ -89,6 +89,7 @@ struct ipt_ip { - #define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */ - #define IPT_F_GOTO 0x02 /* Set if jump is a goto */ - #define IPT_F_MASK 0x03 /* All possible flag bits mask. */ -+#define IPT_F_NO_DEF_MATCH 0x80 /* Internal: no default match rules present */ - - /* Values for "inv" field in struct ipt_ip. */ - #define IPT_INV_VIA_IN 0x01 /* Invert the sense of IN IFACE. */ ---- a/net/ipv4/netfilter/ip_tables.c -+++ b/net/ipv4/netfilter/ip_tables.c -@@ -48,6 +48,9 @@ ip_packet_match(const struct iphdr *ip, - { - unsigned long ret; - -+ if (ipinfo->flags & IPT_F_NO_DEF_MATCH) -+ return true; -+ - if (NF_INVF(ipinfo, IPT_INV_SRCIP, - (ip->saddr & ipinfo->smsk.s_addr) != ipinfo->src.s_addr) || - NF_INVF(ipinfo, IPT_INV_DSTIP, -@@ -78,6 +81,29 @@ ip_packet_match(const struct iphdr *ip, - return true; - } - -+static void -+ip_checkdefault(struct ipt_ip *ip) -+{ -+ static const char iface_mask[IFNAMSIZ] = {}; -+ -+ if (ip->invflags || ip->flags & IPT_F_FRAG) -+ return; -+ -+ if (memcmp(ip->iniface_mask, iface_mask, IFNAMSIZ) != 0) -+ return; -+ -+ if (memcmp(ip->outiface_mask, iface_mask, IFNAMSIZ) != 0) -+ return; -+ -+ if (ip->smsk.s_addr || ip->dmsk.s_addr) -+ return; -+ -+ if (ip->proto) -+ return; -+ -+ ip->flags |= IPT_F_NO_DEF_MATCH; -+} -+ - static bool - ip_checkentry(const struct ipt_ip *ip) - { -@@ -523,6 +549,8 @@ find_check_entry(struct ipt_entry *e, st - struct xt_mtchk_param mtpar; - struct xt_entry_match *ematch; - -+ ip_checkdefault(&e->ip); -+ - if (!xt_percpu_counter_alloc(alloc_state, &e->counters)) - return -ENOMEM; - -@@ -817,6 +845,7 @@ copy_entries_to_user(unsigned int total_ - const struct xt_table_info *private = table->private; - int ret = 0; - const void *loc_cpu_entry; -+ u8 flags; - - counters = alloc_counters(table); - if (IS_ERR(counters)) -@@ -844,6 +873,14 @@ copy_entries_to_user(unsigned int total_ - goto free_counters; - } - -+ flags = e->ip.flags & IPT_F_MASK; -+ if (copy_to_user(userptr + off -+ + offsetof(struct ipt_entry, ip.flags), -+ &flags, sizeof(flags)) != 0) { -+ ret = -EFAULT; -+ goto free_counters; -+ } -+ - for (i = sizeof(struct ipt_entry); - i < e->target_offset; - i += m->u.match_size) { -@@ -1225,12 +1262,15 @@ compat_copy_entry_to_user(struct ipt_ent - compat_uint_t origsize; - const struct xt_entry_match *ematch; - int ret = 0; -+ u8 flags = e->ip.flags & IPT_F_MASK; - - origsize = *size; - ce = *dstptr; - if (copy_to_user(ce, e, sizeof(struct ipt_entry)) != 0 || - copy_to_user(&ce->counters, &counters[i], -- sizeof(counters[i])) != 0) -+ sizeof(counters[i])) != 0 || -+ copy_to_user(&ce->ip.flags, &flags, -+ sizeof(flags)) != 0) - return -EFAULT; - - *dstptr += sizeof(struct compat_ipt_entry); diff --git a/target/linux/generic/pending-6.18/611-netfilter_match_bypass_default_table.patch b/target/linux/generic/pending-6.18/611-netfilter_match_bypass_default_table.patch deleted file mode 100644 index 8185a8b0df..0000000000 --- a/target/linux/generic/pending-6.18/611-netfilter_match_bypass_default_table.patch +++ /dev/null @@ -1,106 +0,0 @@ -From: Felix Fietkau -Subject: netfilter: match bypass default table - -Signed-off-by: Felix Fietkau ---- - net/ipv4/netfilter/ip_tables.c | 79 +++++++++++++++++++++++++++++++----------- - 1 file changed, 58 insertions(+), 21 deletions(-) - ---- a/net/ipv4/netfilter/ip_tables.c -+++ b/net/ipv4/netfilter/ip_tables.c -@@ -244,6 +244,33 @@ struct ipt_entry *ipt_next_entry(const s - return (void *)entry + entry->next_offset; - } - -+static bool -+ipt_handle_default_rule(struct ipt_entry *e, unsigned int *verdict) -+{ -+ struct xt_entry_target *t; -+ struct xt_standard_target *st; -+ -+ if (e->target_offset != sizeof(struct ipt_entry)) -+ return false; -+ -+ if (!(e->ip.flags & IPT_F_NO_DEF_MATCH)) -+ return false; -+ -+ t = ipt_get_target(e); -+ if (t->u.kernel.target->target) -+ return false; -+ -+ st = (struct xt_standard_target *) t; -+ if (st->verdict == XT_RETURN) -+ return false; -+ -+ if (st->verdict >= 0) -+ return false; -+ -+ *verdict = (unsigned)(-st->verdict) - 1; -+ return true; -+} -+ - /* Returns one of the generic firewall policies, like NF_ACCEPT. */ - unsigned int - ipt_do_table(void *priv, -@@ -265,27 +292,28 @@ ipt_do_table(void *priv, - unsigned int addend; - - /* Initialization */ -+ WARN_ON(!(table->valid_hooks & (1 << hook))); -+ local_bh_disable(); -+ private = READ_ONCE(table->private); /* Address dependency. */ -+ cpu = smp_processor_id(); -+ table_base = private->entries; -+ -+ e = get_entry(table_base, private->hook_entry[hook]); -+ if (ipt_handle_default_rule(e, &verdict)) { -+ struct xt_counters *counter; -+ -+ counter = xt_get_this_cpu_counter(&e->counters); -+ ADD_COUNTER(*counter, skb->len, 1); -+ local_bh_enable(); -+ return verdict; -+ } -+ - stackidx = 0; - ip = ip_hdr(skb); - indev = state->in ? state->in->name : nulldevname; - outdev = state->out ? state->out->name : nulldevname; -- /* We handle fragments by dealing with the first fragment as -- * if it was a normal packet. All other fragments are treated -- * normally, except that they will NEVER match rules that ask -- * things we don't know, ie. tcp syn flag or ports). If the -- * rule is also a fragment-specific rule, non-fragments won't -- * match it. */ -- acpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET; -- acpar.thoff = ip_hdrlen(skb); -- acpar.hotdrop = false; -- acpar.state = state; - -- WARN_ON(!(table->valid_hooks & (1 << hook))); -- local_bh_disable(); - addend = xt_write_recseq_begin(); -- private = READ_ONCE(table->private); /* Address dependency. */ -- cpu = smp_processor_id(); -- table_base = private->entries; - jumpstack = (struct ipt_entry **)private->jumpstack[cpu]; - - /* Switch to alternate jumpstack if we're being invoked via TEE. -@@ -298,7 +326,16 @@ ipt_do_table(void *priv, - if (static_key_false(&xt_tee_enabled)) - jumpstack += private->stacksize * current->in_nf_duplicate; - -- e = get_entry(table_base, private->hook_entry[hook]); -+ /* We handle fragments by dealing with the first fragment as -+ * if it was a normal packet. All other fragments are treated -+ * normally, except that they will NEVER match rules that ask -+ * things we don't know, ie. tcp syn flag or ports). If the -+ * rule is also a fragment-specific rule, non-fragments won't -+ * match it. */ -+ acpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET; -+ acpar.thoff = ip_hdrlen(skb); -+ acpar.hotdrop = false; -+ acpar.state = state; - - do { - const struct xt_entry_target *t; diff --git a/target/linux/generic/pending-6.18/612-netfilter_match_reduce_memory_access.patch b/target/linux/generic/pending-6.18/612-netfilter_match_reduce_memory_access.patch deleted file mode 100644 index 7f291fc008..0000000000 --- a/target/linux/generic/pending-6.18/612-netfilter_match_reduce_memory_access.patch +++ /dev/null @@ -1,22 +0,0 @@ -From: Felix Fietkau -Subject: netfilter: reduce match memory access - -Signed-off-by: Felix Fietkau ---- - net/ipv4/netfilter/ip_tables.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/net/ipv4/netfilter/ip_tables.c -+++ b/net/ipv4/netfilter/ip_tables.c -@@ -51,9 +51,9 @@ ip_packet_match(const struct iphdr *ip, - if (ipinfo->flags & IPT_F_NO_DEF_MATCH) - return true; - -- if (NF_INVF(ipinfo, IPT_INV_SRCIP, -+ if (NF_INVF(ipinfo, IPT_INV_SRCIP, ipinfo->smsk.s_addr && - (ip->saddr & ipinfo->smsk.s_addr) != ipinfo->src.s_addr) || -- NF_INVF(ipinfo, IPT_INV_DSTIP, -+ NF_INVF(ipinfo, IPT_INV_DSTIP, ipinfo->dmsk.s_addr && - (ip->daddr & ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr)) - return false; - diff --git a/target/linux/generic/pending-6.18/681-net-remove-NETIF_F_GSO_FRAGLIST-from-NETIF_F_GSO_SOF.patch b/target/linux/generic/pending-6.18/681-net-remove-NETIF_F_GSO_FRAGLIST-from-NETIF_F_GSO_SOF.patch index f3d96f6bb2..bf140cc4f0 100644 --- a/target/linux/generic/pending-6.18/681-net-remove-NETIF_F_GSO_FRAGLIST-from-NETIF_F_GSO_SOF.patch +++ b/target/linux/generic/pending-6.18/681-net-remove-NETIF_F_GSO_FRAGLIST-from-NETIF_F_GSO_SOF.patch @@ -96,7 +96,7 @@ Signed-off-by: Felix Fietkau } --- a/net/core/sock.c +++ b/net/core/sock.c -@@ -2620,7 +2620,7 @@ void sk_setup_caps(struct sock *sk, stru +@@ -2625,7 +2625,7 @@ void sk_setup_caps(struct sock *sk, stru icsk->icsk_ack.dst_quick_ack = dst_metric(dst, RTAX_QUICKACK); } if (sk->sk_route_caps & NETIF_F_GSO) diff --git a/target/linux/generic/pending-6.18/700-netfilter-nft_flow_offload-handle-netdevice-events-f.patch b/target/linux/generic/pending-6.18/700-netfilter-nft_flow_offload-handle-netdevice-events-f.patch index d37fbd7c22..246e1a4c6a 100644 --- a/target/linux/generic/pending-6.18/700-netfilter-nft_flow_offload-handle-netdevice-events-f.patch +++ b/target/linux/generic/pending-6.18/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 -@@ -805,6 +805,23 @@ static struct pernet_operations nf_flow_ +@@ -810,6 +810,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; -@@ -821,6 +838,10 @@ static int __init nf_flow_table_module_i +@@ -826,6 +843,10 @@ static int __init nf_flow_table_module_i if (ret) goto out_bpf; @@ -45,7 +45,7 @@ Signed-off-by: Pablo Neira Ayuso return 0; out_bpf: -@@ -832,6 +853,7 @@ out_offload: +@@ -837,6 +858,7 @@ out_offload: static void __exit nf_flow_table_module_exit(void) { diff --git a/target/linux/generic/pending-6.18/703-phy-add-detach-callback-to-struct-phy_driver.patch b/target/linux/generic/pending-6.18/703-phy-add-detach-callback-to-struct-phy_driver.patch index 97f7d3f3da..baa9dc7a52 100644 --- a/target/linux/generic/pending-6.18/703-phy-add-detach-callback-to-struct-phy_driver.patch +++ b/target/linux/generic/pending-6.18/703-phy-add-detach-callback-to-struct-phy_driver.patch @@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c -@@ -1836,6 +1836,9 @@ void phy_detach(struct phy_device *phyde +@@ -1839,6 +1839,9 @@ void phy_detach(struct phy_device *phyde phydev->devlink = NULL; } diff --git a/target/linux/generic/pending-6.18/750-net-sfp-add-quirk-for-QINIYEK-BJ-SFP-10G-T-copper-SF.patch b/target/linux/generic/pending-6.18/750-net-sfp-add-quirk-for-QINIYEK-BJ-SFP-10G-T-copper-SF.patch index 21ad584fdb..b09463fcdd 100644 --- a/target/linux/generic/pending-6.18/750-net-sfp-add-quirk-for-QINIYEK-BJ-SFP-10G-T-copper-SF.patch +++ b/target/linux/generic/pending-6.18/750-net-sfp-add-quirk-for-QINIYEK-BJ-SFP-10G-T-copper-SF.patch @@ -16,7 +16,7 @@ Signed-off-by: Daniel Golle --- a/drivers/net/phy/sfp.c +++ b/drivers/net/phy/sfp.c -@@ -585,6 +585,7 @@ static const struct sfp_quirk sfp_quirks +@@ -602,6 +602,7 @@ static const struct sfp_quirk sfp_quirks SFP_QUIRK_S("OEM", "SFP-2.5G-BX10-U", sfp_quirk_2500basex), SFP_QUIRK_F("OEM", "RTSFP-10", sfp_fixup_rollball_cc), SFP_QUIRK_F("OEM", "RTSFP-10G", sfp_fixup_rollball_cc), diff --git a/target/linux/generic/pending-6.18/751-net-sfp-add-quirk-for-TP-LINK-SM410U.patch b/target/linux/generic/pending-6.18/751-net-sfp-add-quirk-for-TP-LINK-SM410U.patch index b0b71cb917..c1f17ae69b 100644 --- a/target/linux/generic/pending-6.18/751-net-sfp-add-quirk-for-TP-LINK-SM410U.patch +++ b/target/linux/generic/pending-6.18/751-net-sfp-add-quirk-for-TP-LINK-SM410U.patch @@ -14,7 +14,7 @@ Signed-off-by: Daniel Golle --- a/drivers/net/phy/sfp.c +++ b/drivers/net/phy/sfp.c -@@ -591,6 +591,7 @@ static const struct sfp_quirk sfp_quirks +@@ -608,6 +608,7 @@ static const struct sfp_quirk sfp_quirks SFP_QUIRK_F("Turris", "RTSFP-10G", sfp_fixup_rollball), SFP_QUIRK_S("ZOERAX", "SFP-2.5G-T", sfp_quirk_oem_2_5g), diff --git a/target/linux/generic/pending-6.18/920-mangle_bootargs.patch b/target/linux/generic/pending-6.18/920-mangle_bootargs.patch index b91a9e10ac..57942caced 100644 --- a/target/linux/generic/pending-6.18/920-mangle_bootargs.patch +++ b/target/linux/generic/pending-6.18/920-mangle_bootargs.patch @@ -44,12 +44,12 @@ Signed-off-by: Imre Kaloz + rootdev = strstr(command_line, "root=/dev/mtdblock"); + + if (rootdev) -+ strncpy(rootdev, "mangled_rootblock=", 18); ++ memcpy(rootdev, "mangled_rootblock=", 18); + + rootfs = strstr(command_line, "rootfstype"); + + if (rootfs) -+ strncpy(rootfs, "mangled_fs", 10); ++ memcpy(rootfs, "mangled_fs", 10); + +} +#else diff --git a/target/linux/ipq40xx/dts/qcom-ipq4019-lbr20.dts b/target/linux/ipq40xx/dts/qcom-ipq4019-lbr20.dts index f4c71fb8dc..eeb7e5421f 100644 --- a/target/linux/ipq40xx/dts/qcom-ipq4019-lbr20.dts +++ b/target/linux/ipq40xx/dts/qcom-ipq4019-lbr20.dts @@ -11,7 +11,7 @@ compatible = "netgear,lbr20"; chosen { - bootargs-append = "ubi.mtd=ubi root=/dev/ubiblock0_0"; + bootargs-append = " ubi.mtd=ubi root=/dev/ubiblock0_0"; }; aliases { diff --git a/target/linux/ipq40xx/dts/qcom-ipq4019-rbx20.dtsi b/target/linux/ipq40xx/dts/qcom-ipq4019-rbx20.dtsi index 08d2c0e4a0..b0aa6df86a 100644 --- a/target/linux/ipq40xx/dts/qcom-ipq4019-rbx20.dtsi +++ b/target/linux/ipq40xx/dts/qcom-ipq4019-rbx20.dtsi @@ -8,7 +8,7 @@ / { chosen { - bootargs-append = "ubi.mtd=ubi root=/dev/ubiblock0_0"; + bootargs-append = " ubi.mtd=ubi root=/dev/ubiblock0_0"; }; aliases { diff --git a/target/linux/ipq40xx/dts/qcom-ipq4019-rtl30vw.dts b/target/linux/ipq40xx/dts/qcom-ipq4019-rtl30vw.dts index 0a8b366be6..47e8a81abf 100644 --- a/target/linux/ipq40xx/dts/qcom-ipq4019-rtl30vw.dts +++ b/target/linux/ipq40xx/dts/qcom-ipq4019-rtl30vw.dts @@ -23,7 +23,7 @@ }; chosen { - bootargs-append = "ubi.mtd=ubifs root=/dev/ubiblock0_0 rootfstype=squashfs ro"; + bootargs-append = " ubi.mtd=ubifs root=/dev/ubiblock0_0 rootfstype=squashfs ro"; }; led_spi { 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 87b938c815..171f5b732e 100644 --- a/target/linux/ipq806x/base-files/etc/board.d/02_network +++ b/target/linux/ipq806x/base-files/etc/board.d/02_network @@ -14,6 +14,11 @@ ipq806x_setup_interfaces() arris,tr4400-v2) ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" "eth2" ;; + aruba,ap-32x|\ + edgecore,ecw5410|\ + extreme,ap3935) + ucidef_set_interfaces_lan_wan "eth1" "eth0" + ;; askey,rt4230w-rev6|\ asrock,g10|\ buffalo,wxr-2533dhp|\ @@ -48,10 +53,6 @@ ipq806x_setup_interfaces() ucidef_set_network_device_conduit "lan1" "eth1" ucidef_set_network_device_conduit "wan" "eth0" ;; - edgecore,ecw5410|\ - extreme,ap3935) - ucidef_set_interfaces_lan_wan "eth1" "eth0" - ;; fortinet,fap-421e|\ ignitenet,ss-w2-ac2600|\ ubnt,unifi-ac-hd|\ diff --git a/target/linux/ipq806x/base-files/etc/init.d/bootcount b/target/linux/ipq806x/base-files/etc/init.d/bootcount index a25b869bf9..bbc3fbdf06 100755 --- a/target/linux/ipq806x/base-files/etc/init.d/bootcount +++ b/target/linux/ipq806x/base-files/etc/init.d/bootcount @@ -6,13 +6,14 @@ START=99 boot() { case $(board_name) in - asrock,g10) - asrock_bootconfig_mangle "bootcheck" && reboot - ;; + aruba,ap-32x|\ edgecore,ecw5410|\ ignitenet,ss-w2-ac2600) fw_setenv bootcount 0 ;; + asrock,g10) + asrock_bootconfig_mangle "bootcheck" && reboot + ;; extreme,ap3935) fw_setenv WATCHDOG_COUNT 0x00000000 ;; diff --git a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh index 1016e5d419..a097ba3850 100644 --- a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh +++ b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh @@ -26,6 +26,21 @@ platform_do_upgrade() { qcom,ipq8064-ap161) nand_do_upgrade "$1" ;; + aruba,ap-32x) + # The bootloader on this device unfortunately enforces a particular set of UBI volumes, + # and will mess with the partitioning if it doesn't find it. + # Therefore, we have to make do with the stock layout, which is a set of three + # MTD partitions, each containing a single UBI volume with the same name. + # Luckily, it doesn't check size, so we can have a "rootfs_data" volume next to a dummy + # "ubifs" volume on the "ubifs" partition. + CI_KERNPART="aos0" + CI_ROOTPART="aos1" + CI_KERN_UBIPART="aos0" + CI_ROOT_UBIPART="aos1" + CI_DATA_UBIPART="ubifs" + CI_SKIP_KERNEL_MTD=1 + nand_do_upgrade "$1" + ;; asrock,g10) asrock_upgrade_prepare nand_do_upgrade "$1" diff --git a/target/linux/ipq806x/config-6.12 b/target/linux/ipq806x/config-6.12 index 74c32dbdc6..d4fc4a2779 100644 --- a/target/linux/ipq806x/config-6.12 +++ b/target/linux/ipq806x/config-6.12 @@ -184,6 +184,8 @@ CONFIG_GENERIC_VDSO_32=y CONFIG_GLOB=y CONFIG_GPIOLIB_IRQCHIP=y CONFIG_GPIO_CDEV=y +CONFIG_GPIO_WATCHDOG=y +CONFIG_GPIO_WATCHDOG_ARCH_INITCALL=y CONFIG_GRO_CELLS=y CONFIG_HARDEN_BRANCH_PREDICTOR=y CONFIG_HARDIRQS_SW_RESEND=y diff --git a/target/linux/ipq806x/dts/qcom-ipq8068-ap-32x.dts b/target/linux/ipq806x/dts/qcom-ipq8068-ap-32x.dts new file mode 100644 index 0000000000..b6f1b7b110 --- /dev/null +++ b/target/linux/ipq806x/dts/qcom-ipq8068-ap-32x.dts @@ -0,0 +1,377 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq8064-v2.0.dtsi" + +#include +#include +#include + +/ { + model = "Aruba AP-32x"; + compatible = "aruba,ap-32x", "qcom,ipq8064"; + + memory@0 { + reg = <0x41500000 0x1eb00000>; + device_type = "memory"; + }; + + aliases { + serial0 = &gsbi4_serial; + serial1 = &gsbi2_serial; + + ethernet0 = &gmac2; + ethernet1 = &gmac3; + + led-boot = &led_power_amber; + led-failsafe = &led_power_red; + led-running = &led_power_green; + led-upgrade = &led_power_amber; + + label-mac-device = &gmac2; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs-append = " ubi.mtd=aos1 ubi.mtd=ubifs ubi.block=0,aos1 root=/dev/ubiblock0_0"; + }; + + keys { + compatible = "gpio-keys"; + pinctrl-0 = <&button_pins>; + pinctrl-names = "default"; + + reset { + label = "reset"; + gpios = <&qcom_pinmux 9 GPIO_ACTIVE_LOW>; + linux,code = ; + debounce-interval = <60>; + wakeup-source; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-0 = <&led_pins>; + pinctrl-names = "default"; + + led_power_green: power_green { + function = LED_FUNCTION_POWER; + color = ; + gpios = <&qcom_pinmux 28 GPIO_ACTIVE_HIGH>; + }; + + led_power_amber: power_amber { + function = LED_FUNCTION_POWER; + color = ; + gpios = <&qcom_pinmux 29 GPIO_ACTIVE_HIGH>; + }; + + led_power_red: power_red { + function = LED_FUNCTION_POWER; + color = ; + gpios = <&qcom_pinmux 30 GPIO_ACTIVE_HIGH>; + }; + + led_wlan_green { + function = LED_FUNCTION_WLAN; + color = ; + gpios = <&qcom_pinmux 31 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy0tpt"; + }; + + led_wlan_amber { + function = LED_FUNCTION_WLAN; + color = ; + gpios = <&qcom_pinmux 32 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy1tpt"; + }; + }; + + watchdog { + compatible = "linux,wdt-gpio"; + gpios = <&qcom_pinmux 61 GPIO_ACTIVE_LOW>; + hw_algo = "toggle"; + hw_margin_ms = <1000>; + always-running; + + pinctrl-names = "default"; + pinctrl-0 = <&watchdog_pins>; + }; + + i2c { + compatible = "i2c-gpio"; + + sda-gpios = <&qcom_pinmux 24 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + scl-gpios = <&qcom_pinmux 25 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + + #address-cells = <1>; + #size-cells = <0>; + + tpm@29 { + compatible = "atmel,at97sc3204t"; + reg = <0x29>; + }; + }; +}; + +&qcom_pinmux { + led_pins: led_pins { + mux { + pins = "gpio28", "gpio29", "gpio30", "gpio31", "gpio32"; + function = "gpio"; + drive-strength = <12>; + bias-pull-up; + }; + }; + + button_pins: button_pins { + mux { + pins = "gpio9"; + function = "gpio"; + bias-pull-up; + }; + }; + + uart0_pins: uart0_pins { + mux { + pins = "gpio10", "gpio11"; + function = "gsbi4"; + drive-strength = <10>; + bias-disable; + }; + }; + + uart1_pins: uart1_pins { + mux { + pins = "gpio22", "gpio23"; + function = "gsbi2"; + drive-strength = <10>; + bias-disable; + }; + }; + + watchdog_pins: watchdog_pins { + mux { + pins = "gpio61"; + function = "gpio"; + drive-strength = <10>; + bias-disable; + }; + }; + /* used for USB over-current detection instead */ + /delete-node/ pcie2_pins; +}; + +&gsbi4 { + status = "okay"; + qcom,mode = ; +}; + +&gsbi4_serial { + status = "okay"; + pinctrl-0 = <&uart0_pins>; + pinctrl-names = "default"; +}; + +&gsbi2 { + status = "okay"; + qcom,mode = ; +}; + +&gsbi2_serial { + status = "okay"; + pinctrl-0 = <&uart1_pins>; + pinctrl-names = "default"; +}; + +&gsbi5 { + qcom,mode = ; + status = "okay"; + + spi@1a280000 { + status = "okay"; + spi-max-frequency = <50000000>; + + pinctrl-0 = <&spi_pins>; + pinctrl-names = "default"; + + cs-gpios = <&qcom_pinmux 20 GPIO_ACTIVE_LOW>; + + mx25u3235f@0 { + compatible = "jedec,spi-nor"; + #address-cells = <1>; + #size-cells = <1>; + spi-max-frequency = <50000000>; + reg = <0>; + + partitions { + compatible = "qcom,smem-part"; + + partition-art { + compatible = "nvmem-cells"; + #address-cells = <1>; + #size-cells = <1>; + label = "0:art"; + + precal_art_1000: precal@1000 { + reg = <0x1000 0x2f20>; + }; + + precal_art_5000: precal@5000 { + reg = <0x5000 0x2f20>; + }; + }; + + partition-appsblenv { + label = "0:appsblenv"; + + nvmem-layout { + compatible = "u-boot,env"; + + macaddr_lan: ethaddr { + #nvmem-cell-cells = <1>; + }; + }; + }; + }; + }; + }; +}; + +&pcie0 { + status = "okay"; +}; + +&pcie_bridge0 { + wifi@0,0 { + compatible = "qcom,ath10k"; + status = "okay"; + reg = <0x10000 0 0 0 0>; + + nvmem-cells = <&precal_art_1000>; + nvmem-cell-names = "pre-calibration"; + }; +}; + +&pcie1 { + status = "okay"; +}; + +&pcie_bridge1 { + wifi@0,0 { + compatible = "qcom,ath10k"; + status = "okay"; + reg = <0x10000 0 0 0 0>; + + nvmem-cells = <&precal_art_5000>; + nvmem-cell-names = "pre-calibration"; + }; +}; + +&nand { + status = "okay"; + + nand@0 { + compatible = "qcom,nandcs"; + + reg = <0>; + + nand-ecc-strength = <4>; + nand-bus-width = <8>; + nand-ecc-step-size = <512>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + aos0@0 { + label = "aos0"; + reg = <0x0 0x2000000>; + }; + + aos1@2000000 { + label = "aos1"; + reg = <0x2000000 0x2000000>; + }; + + ubifs@4000000 { + label = "ubifs"; + reg = <0x4000000 0x4000000>; + }; + }; + }; +}; + +&mdio0 { + status = "okay"; + + pinctrl-0 = <&mdio0_pins>; + pinctrl-names = "default"; + + phy0: ethernet-phy@0 { + reg = <0>; + }; + + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + +&gmac2 { + status = "okay"; + + qcom,id = <2>; + mdiobus = <&mdio0>; + + phy-mode = "sgmii"; + phy-handle = <&phy0>; + + nvmem-cells = <&macaddr_lan 0>; + nvmem-cell-names = "mac-address"; +}; + +&gmac3 { + status = "okay"; + + qcom,id = <3>; + mdiobus = <&mdio0>; + + phy-mode = "sgmii"; + phy-handle = <&phy1>; + + nvmem-cells = <&macaddr_lan 1>; + nvmem-cell-names = "mac-address"; +}; + +&adm_dma { + status = "okay"; +}; + +/* USB Port 0 is connected to the onboard BLE SoC. + * The stock FW on that doesn't implement USB, so to prevent errors from + * being logged when the host fails to initialize it, it's disabled by + * default here. */ +&hs_phy_0 { + status = "disabled"; +}; + +&ss_phy_0 { + status = "disabled"; +}; + +&usb3_0 { + status = "disabled"; +}; + +&hs_phy_1 { + status = "okay"; +}; + +&ss_phy_1 { + status = "okay"; +}; + +&usb3_1 { + status = "okay"; +}; diff --git a/target/linux/ipq806x/image/generic.mk b/target/linux/ipq806x/image/generic.mk index 975d95a29c..57afa1543e 100644 --- a/target/linux/ipq806x/image/generic.mk +++ b/target/linux/ipq806x/image/generic.mk @@ -48,6 +48,18 @@ define Build/linksys-addfwhdr ;mv "$@.new" "$@" endef +define Build/apboot-addfwhdr + $(SCRIPT_DIR)/aruba-header.py \ + $@ $@.new \ + "$(call toupper,$(LINUX_KARCH)) $(VERSION_DIST) Linux-$(LINUX_VERSION), $(VERSION_NUMBER) $(VERSION_CODE)"\ + "$(VERSION_NUMBER)" \ + "$(VERSION_DIST)" \ + os \ + "$(word 1,$(1))" + + mv "$@.new" "$@" +endef + define Device/DniImage KERNEL_SUFFIX := -uImage KERNEL = kernel-bin | append-dtb | uImage none @@ -102,6 +114,29 @@ define Device/arris_tr4400-v2 endef TARGET_DEVICES += arris_tr4400-v2 +define Device/aruba_ap-32x + $(call Device/LegacyImage) + DEVICE_VENDOR := Aruba + DEVICE_MODEL := AP-325 + DEVICE_ALT0_VENDOR := Aruba + DEVICE_ALT0_MODEL := AP-324 + DEVICE_ALT1_VENDOR := Siemens + DEVICE_ALT1_MODEL := Scalance W1750D + SOC := qcom-ipq8068 + PAGESIZE := 2048 + BLOCKSIZE := 128k + KERNEL_SUFFIX := .ari + KERNEL = kernel-bin | append-dtb | uImage none | apboot-addfwhdr Octomore + KERNEL_LOADADDR = 0x41508000 + KERNEL_SIZE := 30720k + UBOOT_PATH := $$(STAGING_DIR_IMAGE)/aruba_ap-32x-apboot.mbn + ARTIFACTS := apboot.mbn + ARTIFACT/apboot.mbn := append-uboot + DEVICE_PACKAGES := ath10k-firmware-qca99x0-ct kmod-i2c-gpio kmod-tpm-i2c-atmel \ + apboot-aruba-ipq806x +endef +TARGET_DEVICES += aruba_ap-32x + define Device/askey_rt4230w-rev6 $(call Device/LegacyImage) $(Device/dsa-migration) diff --git a/target/linux/ipq806x/patches-6.12/900-arm-add-cmdline-override.patch b/target/linux/ipq806x/patches-6.12/900-arm-add-cmdline-override.patch index cd5c8c016d..1e4834527c 100644 --- a/target/linux/ipq806x/patches-6.12/900-arm-add-cmdline-override.patch +++ b/target/linux/ipq806x/patches-6.12/900-arm-add-cmdline-override.patch @@ -19,7 +19,7 @@ +++ b/drivers/of/fdt.c @@ -1053,6 +1053,17 @@ int __init early_init_dt_scan_chosen(cha if (p != NULL && l > 0) - strlcat(cmdline, p, min_t(int, strlen(cmdline) + (int)l, COMMAND_LINE_SIZE)); + strlcat(cmdline, p, COMMAND_LINE_SIZE); + /* CONFIG_CMDLINE_OVERRIDE is used to fallback to a different + * device tree option of chosen/bootargs-override. This is @@ -29,7 +29,7 @@ +#ifdef CONFIG_CMDLINE_OVERRIDE + p = of_get_flat_dt_prop(node, "bootargs-override", &l); + if (p != NULL && l > 0) -+ strscpy(cmdline, p, min((int)l, COMMAND_LINE_SIZE)); ++ strscpy(cmdline, p, min(l, COMMAND_LINE_SIZE)); +#endif + handle_cmdline: diff --git a/target/linux/layerscape/Makefile b/target/linux/layerscape/Makefile index 61690b8b58..7d675335e1 100644 --- a/target/linux/layerscape/Makefile +++ b/target/linux/layerscape/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk BOARD:=layerscape BOARDNAME:=NXP Layerscape -KERNEL_PATCHVER:=6.12 +KERNEL_PATCHVER:=6.18 FEATURES:=squashfs nand usb pcie gpio fpu ubifs ext4 rootfs-part boot-part SUBTARGETS:=armv8_64b armv7 diff --git a/target/linux/layerscape/armv7/config-6.12 b/target/linux/layerscape/armv7/config-6.18 similarity index 97% rename from target/linux/layerscape/armv7/config-6.12 rename to target/linux/layerscape/armv7/config-6.18 index c7c248458d..ef29c85e1b 100644 --- a/target/linux/layerscape/armv7/config-6.12 +++ b/target/linux/layerscape/armv7/config-6.18 @@ -19,6 +19,7 @@ CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_ARCH_STACKWALK=y CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_USES_CFI_GENERIC_LLVM_PASS=y CONFIG_ARM=y CONFIG_ARM_APPENDED_DTB=y CONFIG_ARM_ARCH_TIMER=y @@ -68,8 +69,6 @@ CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=262144 CONFIG_BLK_DEV_SD=y CONFIG_BLK_DEV_SR=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_MQ_VIRTIO=y CONFIG_BLK_PM=y CONFIG_BOUNCE=y CONFIG_BROADCOM_PHY=y @@ -149,6 +148,7 @@ CONFIG_CPU_THUMB_CAPABLE=y CONFIG_CPU_TLB_V7=y CONFIG_CPU_V7=y CONFIG_CRC16=y +CONFIG_CRC32_ARCH=y CONFIG_CRC_CCITT=y CONFIG_CRC_ITU_T=y CONFIG_CROSS_MEMORY_ATTACH=y @@ -157,8 +157,9 @@ CONFIG_CRYPTO_CRC32C=y CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_ECB=y CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +CONFIG_CRYPTO_LIB_BLAKE2S_ARCH=y CONFIG_CRYPTO_LIB_GF128MUL=y +CONFIG_CRYPTO_LIB_SHA256_ARCH=y CONFIG_CRYPTO_LIB_UTILS=y CONFIG_CRYPTO_LZO=y CONFIG_CRYPTO_ZSTD=y @@ -174,6 +175,7 @@ CONFIG_DECOMPRESS_LZMA=y CONFIG_DECOMPRESS_LZO=y CONFIG_DECOMPRESS_XZ=y CONFIG_DETECT_HUNG_TASK=y +CONFIG_DETECT_HUNG_TASK_BLOCKER=y # CONFIG_DEVFREQ_GOV_PASSIVE is not set # CONFIG_DEVFREQ_GOV_PERFORMANCE is not set # CONFIG_DEVFREQ_GOV_POWERSAVE is not set @@ -259,7 +261,6 @@ CONFIG_GENERIC_SMP_IDLE_THREAD=y CONFIG_GENERIC_STRNCPY_FROM_USER=y CONFIG_GENERIC_STRNLEN_USER=y CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_GENERIC_VDSO_32=y CONFIG_GIANFAR=y CONFIG_GLOB=y CONFIG_GPIOLIB_IRQCHIP=y @@ -308,11 +309,14 @@ CONFIG_ICS932S401=y CONFIG_IMX2_WDT=y # CONFIG_IMX7ULP_WDT is not set # CONFIG_IMX8MM_THERMAL is not set +# CONFIG_IMX_AIPSTZ is not set CONFIG_IMX_DMA=y # CONFIG_IMX_GPCV2_PM_DOMAINS is not set CONFIG_IMX_INTMUX=y # CONFIG_IMX_IRQSTEER is not set # CONFIG_IMX_MU_MSI is not set +# CONFIG_IMX_SCMI_CPU_DRV is not set +# CONFIG_IMX_SCMI_LMM_DRV is not set CONFIG_IMX_SDMA=y # CONFIG_IMX_WEIM is not set CONFIG_INITRAMFS_SOURCE="" @@ -329,6 +333,8 @@ CONFIG_IRQSTACKS=y CONFIG_IRQ_DOMAIN=y CONFIG_IRQ_DOMAIN_HIERARCHY=y CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_MSI_IOMMU=y +CONFIG_IRQ_MSI_LIB=y CONFIG_IRQ_WORK=y # CONFIG_ISDN is not set CONFIG_ISL29003=y @@ -355,8 +361,6 @@ CONFIG_MARVELL_PHY=y CONFIG_MCPM=y CONFIG_MDIO_BITBANG=y CONFIG_MDIO_BUS=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y # CONFIG_MDIO_GPIO is not set CONFIG_MEMORY=y CONFIG_MEMORY_ISOLATION=y @@ -434,6 +438,7 @@ CONFIG_NVMEM_LAYOUTS=y # CONFIG_NVMEM_SNVS_LPGPR is not set # CONFIG_NVMEM_SPMI_SDAM is not set CONFIG_NVMEM_SYSFS=y +# CONFIG_NXP_ENETC4 is not set CONFIG_OF=y CONFIG_OF_ADDRESS=y CONFIG_OF_DYNAMIC=y @@ -449,12 +454,12 @@ CONFIG_OUTER_CACHE=y CONFIG_OUTER_CACHE_SYNC=y CONFIG_PACKET_DIAG=y CONFIG_PADATA=y +CONFIG_PAGE_BLOCK_MAX_ORDER=11 CONFIG_PAGE_OFFSET=0xC0000000 CONFIG_PAGE_POOL=y CONFIG_PAGE_SIZE_LESS_THAN_256KB=y CONFIG_PAGE_SIZE_LESS_THAN_64KB=y # CONFIG_PANIC_ON_OOPS is not set -CONFIG_PANIC_ON_OOPS_VALUE=0 CONFIG_PANIC_TIMEOUT=0 CONFIG_PCI=y CONFIG_PCIEAER=y @@ -465,6 +470,7 @@ CONFIG_PCIEASPM_DEFAULT=y # CONFIG_PCIEASPM_POWER_SUPERSAVE is not set CONFIG_PCIEPORTBUS=y CONFIG_PCIE_DW=y +# CONFIG_PCIE_DW_DEBUGFS is not set CONFIG_PCIE_DW_HOST=y CONFIG_PCIE_PME=y CONFIG_PCI_DOMAINS=y @@ -481,13 +487,12 @@ CONFIG_PGTABLE_LEVELS=3 CONFIG_PHYLIB=y CONFIG_PHYLIB_LEDS=y CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_PHY_PACKAGE=y CONFIG_PID_NS=y CONFIG_PINCTRL=y # CONFIG_PINCTRL_IMX8ULP is not set # CONFIG_PINCTRL_IMX91 is not set # CONFIG_PINCTRL_IMX93 is not set -# CONFIG_PINCTRL_IMXRT1050 is not set -# CONFIG_PINCTRL_IMXRT1170 is not set CONFIG_PL310_ERRATA_588369=y CONFIG_PL310_ERRATA_727915=y CONFIG_PL310_ERRATA_753970=y @@ -505,6 +510,7 @@ CONFIG_POWER_RESET_GPIO=y CONFIG_POWER_RESET_GPIO_RESTART=y CONFIG_POWER_RESET_SYSCON=y CONFIG_POWER_RESET_SYSCON_POWEROFF=y +# CONFIG_POWER_RESET_TORADEX_EC is not set CONFIG_POWER_RESET_VEXPRESS=y CONFIG_POWER_SUPPLY=y CONFIG_PPS=y @@ -553,7 +559,6 @@ CONFIG_RTC_DRV_FSL_FTM_ALARM=y CONFIG_RTC_DRV_PCF2127=y CONFIG_RTC_I2C_AND_SPI=y CONFIG_RWSEM_SPIN_ON_OWNER=y -CONFIG_SCHED_DEBUG=y CONFIG_SCSI=y CONFIG_SCSI_COMMON=y CONFIG_SECCOMP=y @@ -580,7 +585,6 @@ CONFIG_SERIAL_ST_ASC=y CONFIG_SERIAL_ST_ASC_CONSOLE=y CONFIG_SERIAL_XILINX_PS_UART=y CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y -CONFIG_SGL_ALLOC=y CONFIG_SG_POOL=y CONFIG_SMP=y CONFIG_SMP_ON_UP=y @@ -617,7 +621,6 @@ CONFIG_SPI_SPIDEV=y CONFIG_SPI_XILINX=y CONFIG_SPLIT_PTE_PTLOCKS=y CONFIG_SPMI=y -# CONFIG_SPMI_HISI3670 is not set CONFIG_SQUASHFS_FILE_CACHE=y # CONFIG_SQUASHFS_FILE_DIRECT is not set CONFIG_SQUASHFS_LZO=y diff --git a/target/linux/layerscape/armv8_64b/config-6.12 b/target/linux/layerscape/armv8_64b/config-6.18 similarity index 96% rename from target/linux/layerscape/armv8_64b/config-6.12 rename to target/linux/layerscape/armv8_64b/config-6.18 index f9f1a777a7..53c7dde976 100644 --- a/target/linux/layerscape/armv8_64b/config-6.12 +++ b/target/linux/layerscape/armv8_64b/config-6.18 @@ -1,7 +1,6 @@ CONFIG_64BIT=y CONFIG_AQUANTIA_PHY=y CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y -CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y CONFIG_ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG=y CONFIG_ARCH_DMA_ADDR_T_64BIT=y CONFIG_ARCH_FORCE_MAX_ORDER=10 @@ -20,6 +19,7 @@ CONFIG_ARCH_PROC_KCORE_TEXT=y CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_ARCH_STACKWALK=y CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_USES_HIGH_VMA_FLAGS=y CONFIG_ARCH_WANTS_EXECMEM_LATE=y CONFIG_ARCH_WANTS_NO_INSTR=y CONFIG_ARCH_WANTS_THP_SWAP=y @@ -38,8 +38,9 @@ CONFIG_ARM64_ERRATUM_826319=y CONFIG_ARM64_ERRATUM_827319=y CONFIG_ARM64_ERRATUM_832075=y CONFIG_ARM64_ERRATUM_843419=y +CONFIG_ARM64_GCS=y +CONFIG_ARM64_HAFT=y CONFIG_ARM64_HW_AFDBM=y -CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y CONFIG_ARM64_PA_BITS=48 CONFIG_ARM64_PA_BITS_48=y CONFIG_ARM64_PLATFORM_DEVICES=y @@ -59,16 +60,19 @@ CONFIG_ARM_ARCH_TIMER=y CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND=y CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_ITS_PARENT=y CONFIG_ARM_GIC_V2M=y CONFIG_ARM_GIC_V3=y CONFIG_ARM_GIC_V3_ITS=y CONFIG_ARM_GIC_V3_ITS_FSL_MC=y +CONFIG_ARM_GIC_V5=y # CONFIG_ARM_PL172_MPMC is not set CONFIG_ARM_PSCI_CPUIDLE=y CONFIG_ARM_PSCI_FW=y CONFIG_ARM_SMMU=y # CONFIG_ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT is not set # CONFIG_ARM_SMMU_LEGACY_DT_BINDINGS is not set +# CONFIG_ARM_SMMU_MMU_500_CPRE_ERRATA is not set CONFIG_ARM_SMMU_V3=y # CONFIG_ARM_SMMU_V3_SVA is not set CONFIG_ARM_SP805_WATCHDOG=y @@ -83,6 +87,7 @@ CONFIG_AUDIT_GENERIC=y CONFIG_AUTOFS_FS=y CONFIG_BACKLIGHT_CLASS_DEVICE=y CONFIG_BALLOON_COMPACTION=y +CONFIG_BASIC_MODVERSIONS=y CONFIG_BATTERY_BQ27XXX=y # CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM is not set CONFIG_BATTERY_BQ27XXX_I2C=y @@ -95,8 +100,6 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=262144 CONFIG_BLK_DEV_SD=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_MQ_VIRTIO=y CONFIG_BLK_PM=y CONFIG_BSD_PROCESS_ACCT=y CONFIG_BSD_PROCESS_ACCT_V3=y @@ -109,6 +112,7 @@ CONFIG_CAVIUM_ERRATUM_27456=y CONFIG_CC_HAVE_SHADOW_CALL_STACK=y CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y CONFIG_CHECKPOINT_RESTORE=y +# CONFIG_CHROMEOS_OF_HW_PROBER is not set CONFIG_CHROME_PLATFORMS=y CONFIG_CLK_LS1028A_PLLDIG=y CONFIG_CLK_QORIQ=y @@ -162,12 +166,13 @@ CONFIG_CPU_PM=y CONFIG_CPU_RMAP=y CONFIG_CPU_THERMAL=y CONFIG_CRC16=y +CONFIG_CRC32_ARCH=y CONFIG_CRC64=y -CONFIG_CRC64_ROCKSOFT=y CONFIG_CRC7=y CONFIG_CRC_CCITT=y CONFIG_CRC_ITU_T=y CONFIG_CRC_T10DIF=y +CONFIG_CRC_T10DIF_ARCH=y CONFIG_CROSS_MEMORY_ATTACH=y # CONFIG_CROS_EC is not set CONFIG_CRYPTO_AES_ARM64=y @@ -178,11 +183,7 @@ CONFIG_CRYPTO_AUTHENC=y CONFIG_CRYPTO_BLAKE2B=y CONFIG_CRYPTO_CRC32=y CONFIG_CRYPTO_CRC32C=y -CONFIG_CRYPTO_CRC64_ROCKSOFT=y -CONFIG_CRYPTO_CRCT10DIF=y -CONFIG_CRYPTO_CRCT10DIF_ARM64_CE=y CONFIG_CRYPTO_CRYPTD=y -CONFIG_CRYPTO_CURVE25519=y CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_DES=y CONFIG_CRYPTO_DEV_FSL_CAAM=y @@ -203,19 +204,15 @@ CONFIG_CRYPTO_ENGINE=y CONFIG_CRYPTO_GHASH_ARM64_CE=y CONFIG_CRYPTO_HASH_INFO=y CONFIG_CRYPTO_HW=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_CURVE25519_GENERIC=y -CONFIG_CRYPTO_LIB_CURVE25519_INTERNAL=y CONFIG_CRYPTO_LIB_DES=y CONFIG_CRYPTO_LIB_GF128MUL=y -CONFIG_CRYPTO_LIB_SHA256=y +CONFIG_CRYPTO_LIB_SHA256_ARCH=y CONFIG_CRYPTO_LIB_UTILS=y CONFIG_CRYPTO_LZO=y CONFIG_CRYPTO_RNG=y CONFIG_CRYPTO_RSA=y CONFIG_CRYPTO_SHA256=y -CONFIG_CRYPTO_SHA256_ARM64=y -CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_SIG=y CONFIG_CRYPTO_XTS=y CONFIG_CRYPTO_XXHASH=y CONFIG_CRYPTO_ZSTD=y @@ -229,6 +226,7 @@ CONFIG_DECOMPRESS_LZMA=y CONFIG_DECOMPRESS_LZO=y CONFIG_DECOMPRESS_XZ=y CONFIG_DETECT_HUNG_TASK=y +CONFIG_DETECT_HUNG_TASK_BLOCKER=y CONFIG_DMADEVICES=y CONFIG_DMATEST=y CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC=y @@ -255,6 +253,7 @@ CONFIG_EXCLUSIVE_SYSTEM_RAM=y CONFIG_EXT4_FS=y CONFIG_EXTCON=y CONFIG_EXTCON_USB_GPIO=y +# CONFIG_EXTENDED_MODVERSIONS is not set CONFIG_F2FS_FS=y CONFIG_FAILOVER=y CONFIG_FANOTIFY=y @@ -270,6 +269,7 @@ CONFIG_FB_SYS_COPYAREA=y CONFIG_FB_SYS_FILLRECT=y CONFIG_FB_SYS_IMAGEBLIT=y CONFIG_FHANDLE=y +CONFIG_FIND_NORMAL_PAGE=y CONFIG_FIXED_PHY=y CONFIG_FIX_EARLYCON_MEM=y CONFIG_FONT_8x16=y @@ -311,6 +311,7 @@ CONFIG_FS_POSIX_ACL=y CONFIG_FUNCTION_ALIGNMENT=4 CONFIG_FUNCTION_ALIGNMENT_4B=y CONFIG_FUSE_FS=y +CONFIG_FUTEX_MPOL=y CONFIG_FWNODE_MDIO=y CONFIG_FW_CACHE=y CONFIG_FW_LOADER_PAGED_BUF=y @@ -318,6 +319,7 @@ CONFIG_FW_LOADER_SYSFS=y # CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set CONFIG_GARP=y CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS=y +# CONFIG_GENDWARFKSYMS is not set CONFIG_GENERIC_ALLOCATOR=y CONFIG_GENERIC_ARCH_NUMA=y CONFIG_GENERIC_ARCH_TOPOLOGY=y @@ -334,6 +336,8 @@ CONFIG_GENERIC_GETTIMEOFDAY=y CONFIG_GENERIC_IDLE_POLL_SETUP=y CONFIG_GENERIC_IOREMAP=y CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_ENTRY=y +CONFIG_GENERIC_IRQ_KEXEC_CLEAR_VM_FORWARD=y CONFIG_GENERIC_IRQ_MIGRATION=y CONFIG_GENERIC_IRQ_SHOW=y CONFIG_GENERIC_IRQ_SHOW_LEVEL=y @@ -346,6 +350,7 @@ CONFIG_GENERIC_SMP_IDLE_THREAD=y CONFIG_GENERIC_STRNCPY_FROM_USER=y CONFIG_GENERIC_STRNLEN_USER=y CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GENKSYMS=y # CONFIG_GIANFAR is not set CONFIG_GLOB=y CONFIG_GPIOLIB_IRQCHIP=y @@ -369,6 +374,7 @@ CONFIG_HIBERNATION_SNAPSHOT_DEV=y CONFIG_HOTPLUG_CORE_SYNC=y CONFIG_HOTPLUG_CORE_SYNC_DEAD=y CONFIG_HOTPLUG_CPU=y +CONFIG_HOTPLUG_SMT=y CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING=y @@ -442,7 +448,6 @@ CONFIG_KEYBOARD_ATKBD=y CONFIG_KEYBOARD_GPIO=y CONFIG_KSM=y CONFIG_LEGACY_DIRECT_IO=y -CONFIG_LIBCRC32C=y CONFIG_LIBFDT=y CONFIG_LOCALVERSION_AUTO=y CONFIG_LOCK_DEBUGGING_SUPPORT=y @@ -462,8 +467,6 @@ CONFIG_MDIO_BUS=y CONFIG_MDIO_BUS_MUX=y CONFIG_MDIO_BUS_MUX_MMIOREG=y CONFIG_MDIO_BUS_MUX_MULTIPLEXER=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y # CONFIG_MDIO_GPIO is not set CONFIG_MEMORY=y CONFIG_MEMORY_BALLOON=y @@ -484,6 +487,7 @@ CONFIG_MMC_SDHCI_OF_ESDHC=y CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMU_LAZY_TLB_REFCOUNT=y CONFIG_MMU_NOTIFIER=y +CONFIG_MM_ID=y CONFIG_MODULES_USE_ELF_RELA=y CONFIG_MODULE_FORCE_LOAD=y CONFIG_MODVERSIONS=y @@ -557,6 +561,7 @@ CONFIG_NLS_ISO8859_1=y CONFIG_NODES_SHIFT=2 CONFIG_NO_HZ_COMMON=y CONFIG_NO_HZ_IDLE=y +# CONFIG_NO_PAGE_MAPCOUNT is not set CONFIG_NR_CPUS=64 # CONFIG_NSM is not set CONFIG_NUMA=y @@ -569,6 +574,8 @@ CONFIG_NVMEM_LAYERSCAPE_SFP=y CONFIG_NVMEM_LAYOUTS=y # CONFIG_NVMEM_SPMI_SDAM is not set CONFIG_NVMEM_SYSFS=y +# CONFIG_NXP_ENETC4 is not set +CONFIG_NXP_ENETC_PF_COMMON=y CONFIG_OF=y CONFIG_OF_ADDRESS=y CONFIG_OF_EARLY_FLATTREE=y @@ -582,12 +589,12 @@ CONFIG_OF_NUMA=y CONFIG_PACKET_DIAG=y CONFIG_PACKING=y CONFIG_PADATA=y +CONFIG_PAGE_BLOCK_MAX_ORDER=10 CONFIG_PAGE_POOL=y CONFIG_PAGE_REPORTING=y CONFIG_PAGE_SIZE_LESS_THAN_256KB=y CONFIG_PAGE_SIZE_LESS_THAN_64KB=y # CONFIG_PANIC_ON_OOPS is not set -CONFIG_PANIC_ON_OOPS_VALUE=0 CONFIG_PANIC_TIMEOUT=0 CONFIG_PARAVIRT=y # CONFIG_PARTITION_ADVANCED is not set @@ -601,6 +608,7 @@ CONFIG_PCIEASPM_DEFAULT=y # CONFIG_PCIEASPM_POWER_SUPERSAVE is not set CONFIG_PCIEPORTBUS=y CONFIG_PCIE_DW=y +# CONFIG_PCIE_DW_DEBUGFS is not set CONFIG_PCIE_DW_HOST=y CONFIG_PCIE_LAYERSCAPE_GEN4=y CONFIG_PCIE_MOBIVEIL=y @@ -617,6 +625,7 @@ CONFIG_PCI_IOV=y CONFIG_PCI_LAYERSCAPE=y CONFIG_PCI_MSI=y CONFIG_PCS_LYNX=y +# CONFIG_PERSISTENT_HUGE_ZERO_FOLIO is not set CONFIG_PER_VMA_LOCK=y CONFIG_PGTABLE_HAS_HUGE_LEAVES=y CONFIG_PGTABLE_LEVELS=4 @@ -625,6 +634,7 @@ CONFIG_PHYLIB_LEDS=y CONFIG_PHYLINK=y CONFIG_PHYS_ADDR_T_64BIT=y # CONFIG_PHY_FSL_LYNX_28G is not set +CONFIG_PHY_PACKAGE=y CONFIG_PID_IN_CONTEXTIDR=y CONFIG_PID_NS=y CONFIG_PL330_DMA=y @@ -673,7 +683,6 @@ CONFIG_REGMAP_MMIO=y CONFIG_REGMAP_SPI=y CONFIG_RESET_CONTROLLER=y CONFIG_RFS_ACCEL=y -CONFIG_RODATA_FULL_DEFAULT_ENABLED=y CONFIG_RPS=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_DS1307=y @@ -720,7 +729,6 @@ CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y CONFIG_SERIO=y CONFIG_SERIO_AMBAKMI=y CONFIG_SERIO_LIBPS2=y -CONFIG_SGL_ALLOC=y CONFIG_SG_POOL=y CONFIG_SMP=y CONFIG_SOCK_DIAG=y @@ -773,7 +781,6 @@ CONFIG_THREAD_INFO_IN_TASK=y CONFIG_TICK_CPU_ACCOUNTING=y CONFIG_TIMER_OF=y CONFIG_TIMER_PROBE=y -CONFIG_TOOLS_SUPPORT_RELR=y CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y CONFIG_TRANSPARENT_HUGEPAGE=y CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y @@ -813,7 +820,6 @@ CONFIG_VFIO_IOMMU_TYPE1=y CONFIG_VFIO_PCI=y CONFIG_VFIO_PCI_CORE=y CONFIG_VFIO_PCI_INTX=y -CONFIG_VFIO_PCI_MMAP=y CONFIG_VFIO_VIRQFD=y CONFIG_VGA_ARB=y CONFIG_VGA_ARB_MAX_GPUS=16 diff --git a/target/linux/layerscape/patches-6.12/302-arm64-dts-ls1012a-update-with-ppfe-support.patch b/target/linux/layerscape/patches-6.18/302-arm64-dts-ls1012a-update-with-ppfe-support.patch similarity index 99% rename from target/linux/layerscape/patches-6.12/302-arm64-dts-ls1012a-update-with-ppfe-support.patch rename to target/linux/layerscape/patches-6.18/302-arm64-dts-ls1012a-update-with-ppfe-support.patch index bd69aa042d..5ea7262da3 100644 --- a/target/linux/layerscape/patches-6.12/302-arm64-dts-ls1012a-update-with-ppfe-support.patch +++ b/target/linux/layerscape/patches-6.18/302-arm64-dts-ls1012a-update-with-ppfe-support.patch @@ -190,7 +190,7 @@ Signed-off-by: Li Yang +}; --- a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi -@@ -568,6 +568,35 @@ +@@ -569,6 +569,35 @@ }; }; diff --git a/target/linux/layerscape/patches-6.12/303-arm64-dts-ls1012a-frdm-workaround-by-updating-qspi-f.patch b/target/linux/layerscape/patches-6.18/303-arm64-dts-ls1012a-frdm-workaround-by-updating-qspi-f.patch similarity index 100% rename from target/linux/layerscape/patches-6.12/303-arm64-dts-ls1012a-frdm-workaround-by-updating-qspi-f.patch rename to target/linux/layerscape/patches-6.18/303-arm64-dts-ls1012a-frdm-workaround-by-updating-qspi-f.patch diff --git a/target/linux/layerscape/patches-6.12/304-arm64-dts-ls1012a-rdb-workaround-by-updating-qspi-fl.patch b/target/linux/layerscape/patches-6.18/304-arm64-dts-ls1012a-rdb-workaround-by-updating-qspi-fl.patch similarity index 100% rename from target/linux/layerscape/patches-6.12/304-arm64-dts-ls1012a-rdb-workaround-by-updating-qspi-fl.patch rename to target/linux/layerscape/patches-6.18/304-arm64-dts-ls1012a-rdb-workaround-by-updating-qspi-fl.patch diff --git a/target/linux/layerscape/patches-6.12/305-arm64-dts-ls1046a-rdb-Update-qspi-spi-rx-bus-width-t.patch b/target/linux/layerscape/patches-6.18/305-arm64-dts-ls1046a-rdb-Update-qspi-spi-rx-bus-width-t.patch similarity index 100% rename from target/linux/layerscape/patches-6.12/305-arm64-dts-ls1046a-rdb-Update-qspi-spi-rx-bus-width-t.patch rename to target/linux/layerscape/patches-6.18/305-arm64-dts-ls1046a-rdb-Update-qspi-spi-rx-bus-width-t.patch diff --git a/target/linux/layerscape/patches-6.12/400-LF-20-3-mtd-spi-nor-Use-1-bit-mode-of-spansion-s25fs.patch b/target/linux/layerscape/patches-6.18/400-LF-20-3-mtd-spi-nor-Use-1-bit-mode-of-spansion-s25fs.patch similarity index 100% rename from target/linux/layerscape/patches-6.12/400-LF-20-3-mtd-spi-nor-Use-1-bit-mode-of-spansion-s25fs.patch rename to target/linux/layerscape/patches-6.18/400-LF-20-3-mtd-spi-nor-Use-1-bit-mode-of-spansion-s25fs.patch diff --git a/target/linux/layerscape/patches-6.12/701-staging-add-fsl_ppfe-driver.patch b/target/linux/layerscape/patches-6.18/701-staging-add-fsl_ppfe-driver.patch similarity index 99% rename from target/linux/layerscape/patches-6.12/701-staging-add-fsl_ppfe-driver.patch rename to target/linux/layerscape/patches-6.18/701-staging-add-fsl_ppfe-driver.patch index 279391531a..7dc16d9231 100644 --- a/target/linux/layerscape/patches-6.12/701-staging-add-fsl_ppfe-driver.patch +++ b/target/linux/layerscape/patches-6.18/701-staging-add-fsl_ppfe-driver.patch @@ -1,4 +1,4 @@ -From 81f5150aba929b222783a60a408b9a20a23bd171 Mon Sep 17 00:00:00 2001 +From 1d4b2a1c29da59ab500c1aca751103863e2254ed Mon Sep 17 00:00:00 2001 From: Calvin Johnson Date: Sat, 16 Sep 2017 07:05:49 +0530 Subject: [PATCH] staging: add fsl_ppfe driver @@ -6,8 +6,8 @@ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -This is squash of all commits with ppfe driver taken from NXP 6.12 tree: -https://github.com/nxp-qoriq/linux/tree/lf-6.12.y +This is squash of all commits with ppfe driver taken from NXP 6.18 tree: +https://github.com/nxp-qoriq/linux/tree/lf-6.18.y net: fsl_ppfe: dts binding for ppfe @@ -656,6 +656,33 @@ e.g. Signed-off-by: Dong Aisheng +LF 16506-1 net: ppfe: remove init_dummy_netdev + +See: +commit f835bdae7167 ("net: remove init_dummy_netdev()") + +drivers/staging/fsl_ppfe/pfe_hif.c:993:9: error: implicit declaration of function ‘init_dummy_netdev’ [-Werror=implicit-function-declaration] + 993 | init_dummy_netdev(&hif->dummy_dev); + | ^~~~~~~~~~~~~~~~~ + +Reviewed-by: Wei Fang +Signed-off-by: Dong Aisheng + +LF-16506-2 net: pfe: change to use hrtimer_setup + +Cope with upstream API change: +commit 48ad7bbfd53a ("treewide: Convert new and leftover hrtimer_init() users") + +e.g. +drivers/gpu/arm/midgard/mali_kbase_kinstr_prfcnt.c: In function ‘kbase_kinstr_prfcnt_init’: +drivers/gpu/arm/midgard/mali_kbase_kinstr_prfcnt.c:1272:9: error: implicit declaration of function ‘hrtimer_init’; did you mean ‘hrtimers_init’? [-Werror=implicit-function-declaration] + 1272 | hrtimer_init(&kinstr_ctx->dump_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + | ^~~~~~~~~~~~ + | hrtimers_init + +Reviewed-by: Wei Fang +Signed-off-by: Dong Aisheng + drivers: make all local platform_driver::remove() return void 0edb555a65d1 ("platform: Make platform_driver::remove() return void") @@ -685,12 +712,12 @@ Signed-off-by: Dong Aisheng drivers/staging/fsl_ppfe/pfe_ctrl.h | 100 + drivers/staging/fsl_ppfe/pfe_debugfs.c | 99 + drivers/staging/fsl_ppfe/pfe_debugfs.h | 13 + - drivers/staging/fsl_ppfe/pfe_eth.c | 2550 +++++++++++++++++ + drivers/staging/fsl_ppfe/pfe_eth.c | 2549 +++++++++++++++++ drivers/staging/fsl_ppfe/pfe_eth.h | 175 ++ drivers/staging/fsl_ppfe/pfe_firmware.c | 398 +++ drivers/staging/fsl_ppfe/pfe_firmware.h | 21 + drivers/staging/fsl_ppfe/pfe_hal.c | 1517 ++++++++++ - drivers/staging/fsl_ppfe/pfe_hif.c | 1063 +++++++ + drivers/staging/fsl_ppfe/pfe_hif.c | 1067 +++++++ drivers/staging/fsl_ppfe/pfe_hif.h | 199 ++ drivers/staging/fsl_ppfe/pfe_hif_lib.c | 628 ++++ drivers/staging/fsl_ppfe/pfe_hif_lib.h | 229 ++ @@ -702,7 +729,7 @@ Signed-off-by: Dong Aisheng drivers/staging/fsl_ppfe/pfe_perfmon.h | 26 + drivers/staging/fsl_ppfe/pfe_sysfs.c | 840 ++++++ drivers/staging/fsl_ppfe/pfe_sysfs.h | 17 + - 40 files changed, 10975 insertions(+) + 40 files changed, 10978 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/fsl_ppfe/pfe.txt create mode 100644 drivers/staging/fsl_ppfe/Kconfig create mode 100644 drivers/staging/fsl_ppfe/Makefile @@ -945,8 +972,8 @@ Signed-off-by: Dong Aisheng +}; --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -9114,6 +9114,14 @@ F: drivers/ptp/ptp_qoriq.c - F: drivers/ptp/ptp_qoriq_debugfs.c +@@ -10002,6 +10002,14 @@ F: drivers/net/ethernet/freescale/enetc/ + F: drivers/ptp/ptp_qoriq.c F: include/linux/fsl/ptp_qoriq.h +FREESCALE QORIQ PPFE ETHERNET DRIVER @@ -962,19 +989,19 @@ Signed-off-by: Dong Aisheng L: linux-spi@vger.kernel.org --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig -@@ -62,4 +62,6 @@ source "drivers/staging/fieldbus/Kconfig +@@ -50,4 +50,6 @@ source "drivers/staging/vme_user/Kconfig - source "drivers/staging/vme_user/Kconfig" + source "drivers/staging/gpib/Kconfig" +source "drivers/staging/fsl_ppfe/Kconfig" + endif # STAGING --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile -@@ -20,3 +20,4 @@ obj-$(CONFIG_GREYBUS) += greybus/ +@@ -14,3 +14,4 @@ obj-$(CONFIG_GREYBUS) += greybus/ obj-$(CONFIG_BCM2835_VCHIQ) += vc04_services/ obj-$(CONFIG_XIL_AXIS_FIFO) += axis-fifo/ - obj-$(CONFIG_FIELDBUS_DEV) += fieldbus/ + obj-$(CONFIG_GPIB) += gpib/ +obj-$(CONFIG_FSL_PPFE) += fsl_ppfe/ --- /dev/null +++ b/drivers/staging/fsl_ppfe/Kconfig @@ -3316,7 +3343,7 @@ Signed-off-by: Dong Aisheng +#endif /* _PFE_DEBUGFS_H_ */ --- /dev/null +++ b/drivers/staging/fsl_ppfe/pfe_eth.c -@@ -0,0 +1,2550 @@ +@@ -0,0 +1,2549 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. @@ -5406,10 +5433,9 @@ Signed-off-by: Dong Aisheng + + for (i = 0; i < emac_txq_cnt; i++) { + priv->fast_tx_timeout[i].queuenum = i; -+ hrtimer_init(&priv->fast_tx_timeout[i].timer, CLOCK_MONOTONIC, -+ HRTIMER_MODE_REL); -+ priv->fast_tx_timeout[i].timer.function = -+ pfe_eth_fast_tx_timeout; ++ hrtimer_setup(&priv->fast_tx_timeout[i].timer, ++ pfe_eth_fast_tx_timeout, CLOCK_MONOTONIC, ++ HRTIMER_MODE_REL); + priv->fast_tx_timeout[i].base = priv->fast_tx_timeout; + } +} @@ -7992,7 +8018,7 @@ Signed-off-by: Dong Aisheng +} --- /dev/null +++ b/drivers/staging/fsl_ppfe/pfe_hif.c -@@ -0,0 +1,1063 @@ +@@ -0,0 +1,1067 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. @@ -8985,8 +9011,12 @@ Signed-off-by: Dong Aisheng + } + + /* Initialize NAPI for Rx processing */ -+ init_dummy_netdev(&hif->dummy_dev); -+ netif_napi_add(&hif->dummy_dev, &hif->napi, pfe_hif_rx_poll); ++ hif->dummy_dev = alloc_netdev_dummy(0); ++ if (!hif->dummy_dev) { ++ pr_err("%s: Failed to allocate pfe dummy netdev\n", __func__); ++ goto err1; ++ } ++ netif_napi_add(hif->dummy_dev, &hif->napi, pfe_hif_rx_poll); + napi_enable(&hif->napi); + + spin_lock_init(&hif->tx_lock); @@ -9211,7 +9241,7 @@ Signed-off-by: Dong Aisheng + spinlock_t tx_lock; +/* lock synchronizes hif rx queue processing */ + spinlock_t lock; -+ struct net_device dummy_dev; ++ struct net_device *dummy_dev; + struct napi_struct napi; + struct device *dev; + diff --git a/target/linux/layerscape/patches-6.12/702-phy-Add-2.5G-SGMII-interface-mode.patch b/target/linux/layerscape/patches-6.18/702-phy-Add-2.5G-SGMII-interface-mode.patch similarity index 51% rename from target/linux/layerscape/patches-6.12/702-phy-Add-2.5G-SGMII-interface-mode.patch rename to target/linux/layerscape/patches-6.18/702-phy-Add-2.5G-SGMII-interface-mode.patch index e44f651c25..458f2609fb 100644 --- a/target/linux/layerscape/patches-6.12/702-phy-Add-2.5G-SGMII-interface-mode.patch +++ b/target/linux/layerscape/patches-6.18/702-phy-Add-2.5G-SGMII-interface-mode.patch @@ -1,23 +1,28 @@ -From 5677c6ef5f4096f3149a4e8cfd1438bc9eb2e8a4 Mon Sep 17 00:00:00 2001 +From ae52a1f314f65822a4c3a75f292816581be22ea1 Mon Sep 17 00:00:00 2001 From: Bhaskar Upadhaya -Date: Wed, 29 Nov 2017 15:27:57 +0530 +Date: Wed, 9 Jul 2025 13:23:51 +0300 Subject: [PATCH] phy: Add 2.5G SGMII interface mode Add 2.5G SGMII interface mode(PHY_INTERFACE_MODE_2500SGMII) -in existing phy_interface list +in existing phy_interface list. This is synonymous with +PHY_INTERFACE_MODE_2500BASEX without in-band autoneg used for the sole +purpose of connecting to on-board PHYs (not SFP modules), which we keep +for backwards compatibility with NXP device trees. Signed-off-by: Bhaskar Upadhaya +Signed-off-by: Vladimir Oltean --- Documentation/devicetree/bindings/net/ethernet-controller.yaml | 1 + drivers/net/phy/phy-core.c | 1 + - drivers/net/phy/phylink.c | 2 ++ + drivers/net/phy/phy_caps.c | 1 + + drivers/net/phy/phylink.c | 1 + include/linux/phy.h | 3 +++ - 4 files changed, 7 insertions(+) + 5 files changed, 7 insertions(+) --- a/Documentation/devicetree/bindings/net/ethernet-controller.yaml +++ b/Documentation/devicetree/bindings/net/ethernet-controller.yaml -@@ -65,6 +65,7 @@ properties: - - mii +@@ -42,6 +42,7 @@ properties: + - mii-lite - gmii - sgmii + - sgmii-2500 @@ -26,17 +31,27 @@ Signed-off-by: Bhaskar Upadhaya - qusgmii --- a/drivers/net/phy/phy-core.c +++ b/drivers/net/phy/phy-core.c -@@ -138,6 +138,7 @@ int phy_interface_num_ports(phy_interfac - case PHY_INTERFACE_MODE_RXAUI: - case PHY_INTERFACE_MODE_XAUI: - case PHY_INTERFACE_MODE_1000BASEKX: +@@ -178,6 +178,7 @@ int phy_interface_num_ports(phy_interfac + case PHY_INTERFACE_MODE_SMII: + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_2500BASEX: + case PHY_INTERFACE_MODE_2500SGMII: - return 1; - case PHY_INTERFACE_MODE_QSGMII: - case PHY_INTERFACE_MODE_QUSGMII: + case PHY_INTERFACE_MODE_5GBASER: + case PHY_INTERFACE_MODE_10GBASER: + case PHY_INTERFACE_MODE_25GBASER: +--- a/drivers/net/phy/phy_caps.c ++++ b/drivers/net/phy/phy_caps.c +@@ -331,6 +331,7 @@ unsigned long phy_caps_from_interface(ph + link_caps |= BIT(LINK_CAPA_1000FD); + break; + ++ case PHY_INTERFACE_MODE_2500SGMII: + case PHY_INTERFACE_MODE_2500BASEX: + link_caps |= BIT(LINK_CAPA_2500FD); + break; --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c -@@ -266,6 +266,7 @@ static int phylink_interface_max_speed(p +@@ -274,6 +274,7 @@ static int phylink_interface_max_speed(p case PHY_INTERFACE_MODE_GMII: return SPEED_1000; @@ -44,25 +59,17 @@ Signed-off-by: Bhaskar Upadhaya case PHY_INTERFACE_MODE_2500BASEX: case PHY_INTERFACE_MODE_10G_QXGMII: return SPEED_2500; -@@ -580,6 +581,7 @@ static unsigned long phylink_get_capabil - break; - - case PHY_INTERFACE_MODE_2500BASEX: -+ case PHY_INTERFACE_MODE_2500SGMII: - caps |= MAC_2500FD; - break; - --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -170,6 +170,7 @@ typedef enum { - PHY_INTERFACE_MODE_QUSGMII, - PHY_INTERFACE_MODE_1000BASEKX, - PHY_INTERFACE_MODE_10G_QXGMII, +@@ -136,6 +136,7 @@ typedef enum { + PHY_INTERFACE_MODE_100BASEX, + PHY_INTERFACE_MODE_1000BASEX, + PHY_INTERFACE_MODE_2500BASEX, + PHY_INTERFACE_MODE_2500SGMII, - PHY_INTERFACE_MODE_MAX, - } phy_interface_t; - -@@ -245,6 +246,8 @@ static inline const char *phy_modes(phy_ + PHY_INTERFACE_MODE_5GBASER, + PHY_INTERFACE_MODE_RXAUI, + PHY_INTERFACE_MODE_XAUI, +@@ -220,6 +221,8 @@ static inline const char *phy_modes(phy_ return "gmii"; case PHY_INTERFACE_MODE_SGMII: return "sgmii"; diff --git a/target/linux/layerscape/patches-6.12/703-layerscape-6.12-fix-compilation-warning-for-fsl-ppfe-.patch b/target/linux/layerscape/patches-6.18/703-layerscape-6.18-fix-compilation-warning-for-fsl-ppfe-.patch similarity index 100% rename from target/linux/layerscape/patches-6.12/703-layerscape-6.12-fix-compilation-warning-for-fsl-ppfe-.patch rename to target/linux/layerscape/patches-6.18/703-layerscape-6.18-fix-compilation-warning-for-fsl-ppfe-.patch diff --git a/target/linux/layerscape/patches-6.12/900-layerscape-dts-ls1012a-frdm-add-GPIO-hog-for-PHY-res.patch b/target/linux/layerscape/patches-6.18/900-layerscape-dts-ls1012a-frdm-add-GPIO-hog-for-PHY-res.patch similarity index 100% rename from target/linux/layerscape/patches-6.12/900-layerscape-dts-ls1012a-frdm-add-GPIO-hog-for-PHY-res.patch rename to target/linux/layerscape/patches-6.18/900-layerscape-dts-ls1012a-frdm-add-GPIO-hog-for-PHY-res.patch diff --git a/target/linux/mediatek/dts/mt7981b-creatlentem-clt-r30b1-112m.dts b/target/linux/mediatek/dts/mt7981b-creatlentem-clt-r30b1-112m.dts index 36351565eb..c987c76fad 100644 --- a/target/linux/mediatek/dts/mt7981b-creatlentem-clt-r30b1-112m.dts +++ b/target/linux/mediatek/dts/mt7981b-creatlentem-clt-r30b1-112m.dts @@ -7,9 +7,12 @@ compatible = "creatlentem,clt-r30b1-112m", "mediatek,mt7981"; }; -&partitions { - partition@580000 { - label = "ubi"; - reg = <0x0580000 0x7000000>; - }; +&spi_nand { + mediatek,nmbm; + mediatek,bmt-max-ratio = <1>; + mediatek,bmt-max-reserved-blocks = <64>; +}; + +&ubi { + reg = <0x0580000 0x7000000>; }; diff --git a/target/linux/mediatek/dts/mt7981b-creatlentem-clt-r30b1-common.dtsi b/target/linux/mediatek/dts/mt7981b-creatlentem-clt-r30b1-common.dtsi index 6958c174a0..ff55eb3f9f 100644 --- a/target/linux/mediatek/dts/mt7981b-creatlentem-clt-r30b1-common.dtsi +++ b/target/linux/mediatek/dts/mt7981b-creatlentem-clt-r30b1-common.dtsi @@ -17,7 +17,7 @@ serial0 = &uart0; }; - chosen { + chosen: chosen { stdout-path = "serial0:115200n8"; }; @@ -109,7 +109,7 @@ pinctrl-0 = <&spi0_flash_pins>; status = "okay"; - spi_nand@0 { + spi_nand: spi-nand@0 { compatible = "spi-nand"; reg = <0>; @@ -124,10 +124,6 @@ spi-cal-addrlen = <5>; spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>; - mediatek,nmbm; - mediatek,bmt-max-ratio = <1>; - mediatek,bmt-max-reserved-blocks = <64>; - partitions: partitions { compatible = "fixed-partitions"; #address-cells = <1>; @@ -183,6 +179,10 @@ reg = <0x380000 0x200000>; read-only; }; + + ubi: partition@580000 { + label = "ubi"; + }; }; }; }; diff --git a/target/linux/mediatek/dts/mt7981b-creatlentem-clt-r30b1-ubi.dts b/target/linux/mediatek/dts/mt7981b-creatlentem-clt-r30b1-ubi.dts new file mode 100644 index 0000000000..b4cd51e101 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-creatlentem-clt-r30b1-ubi.dts @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "mt7981b-creatlentem-clt-r30b1-common.dtsi" + +/ { + model = "CreatLentem CLT-R30B1 (UBI)"; + compatible = "creatlentem,clt-r30b1-ubi", "mediatek,mt7981"; +}; + +&chosen { + bootargs = "root=/dev/fit0 rootwait"; + rootdisk = <&ubi_rootdisk>; +}; + +/delete-node/ &partitions; + +&spi_nand { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "bl2"; + reg = <0x0 0x100000>; + read-only; + }; + + partition@100000 { + label = "ubi"; + reg = <0x100000 0x7f00000>; + compatible = "linux,ubi"; + + volumes { + ubi_factory: ubi-volume-factory { + volname = "factory"; + }; + + ubi_rootdisk: ubi-volume-fit { + volname = "fit"; + }; + + ubi-volume-ubootenv { + volname = "ubootenv"; + nvmem-layout { + compatible = "u-boot,env-redundant-bool"; + }; + }; + + ubi-volume-ubootenv2 { + volname = "ubootenv2"; + nvmem-layout { + compatible = "u-boot,env-redundant-bool"; + }; + }; + }; + }; + }; +}; + +&ubi_factory { + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x1000>; + }; + + macaddr_factory_4: macaddr@4 { + reg = <0x4 0x6>; + compatible = "mac-base"; + #nvmem-cell-cells = <1>; + }; + + macaddr_factory_24: macaddr@24 { + compatible = "mac-base"; + reg = <0x24 0x6>; + #nvmem-cell-cells = <1>; + }; + + macaddr_factory_2a: macaddr@2a { + compatible = "mac-base"; + reg = <0x2a 0x6>; + #nvmem-cell-cells = <1>; + }; + }; +}; diff --git a/target/linux/mediatek/dts/mt7981b-creatlentem-clt-r30b1.dts b/target/linux/mediatek/dts/mt7981b-creatlentem-clt-r30b1.dts index 941d0c3435..9b38fd8cc2 100644 --- a/target/linux/mediatek/dts/mt7981b-creatlentem-clt-r30b1.dts +++ b/target/linux/mediatek/dts/mt7981b-creatlentem-clt-r30b1.dts @@ -8,13 +8,18 @@ }; &partitions { - partition@580000 { - label = "ubi"; - reg = <0x0580000 0x4000000>; - }; partition@4580000 { label = "data"; reg = <0x4580000 0x2000000>; }; +}; +&spi_nand { + mediatek,nmbm; + mediatek,bmt-max-ratio = <1>; + mediatek,bmt-max-reserved-blocks = <64>; +}; + +&ubi { + reg = <0x0580000 0x4000000>; }; diff --git a/target/linux/mediatek/dts/mt7981b-openwrt-one.dts b/target/linux/mediatek/dts/mt7981b-openwrt-one.dts index d0b94af5cb..a3c532a141 100644 --- a/target/linux/mediatek/dts/mt7981b-openwrt-one.dts +++ b/target/linux/mediatek/dts/mt7981b-openwrt-one.dts @@ -50,7 +50,7 @@ user { label = "user"; - linux,code = ; + linux,code = ; gpios = <&pio 0 GPIO_ACTIVE_LOW>; }; diff --git a/target/linux/mediatek/dts/mt7986a-acer-predator-w6x-stock.dts b/target/linux/mediatek/dts/mt7986a-acer-predator-w6x-stock.dts index 68b3481dd8..7c5c89b0a5 100644 --- a/target/linux/mediatek/dts/mt7986a-acer-predator-w6x-stock.dts +++ b/target/linux/mediatek/dts/mt7986a-acer-predator-w6x-stock.dts @@ -23,6 +23,20 @@ partition@800000 { label = "ubi"; reg = <0x800000 0x6400000>; + + volumes { + ubi-volume-ubootenv { + volname = "ubootenv"; + + nvmem-layout { + compatible = "u-boot,env-redundant-bool"; + + macaddr_uboot_ethaddr: ethaddr { + #nvmem-cell-cells = <1>; + }; + }; + }; + }; }; partition@6C00000 { diff --git a/target/linux/mediatek/dts/mt7986a-acer-predator-w6x-ubootmod.dts b/target/linux/mediatek/dts/mt7986a-acer-predator-w6x-ubootmod.dts index e7920f515d..851dbb80ca 100644 --- a/target/linux/mediatek/dts/mt7986a-acer-predator-w6x-ubootmod.dts +++ b/target/linux/mediatek/dts/mt7986a-acer-predator-w6x-ubootmod.dts @@ -22,6 +22,18 @@ ubi_rootdisk: ubi-volume-fit { volname = "fit"; }; + + ubi-volume-ubootenv { + volname = "ubootenv"; + + nvmem-layout { + compatible = "u-boot,env-redundant-bool"; + + macaddr_uboot_ethaddr: ethaddr { + #nvmem-cell-cells = <1>; + }; + }; + }; }; }; }; diff --git a/target/linux/mediatek/dts/mt7986a-acer-predator-w6x.dtsi b/target/linux/mediatek/dts/mt7986a-acer-predator-w6x.dtsi index 1d299b70e1..fb5b5d63c2 100644 --- a/target/linux/mediatek/dts/mt7986a-acer-predator-w6x.dtsi +++ b/target/linux/mediatek/dts/mt7986a-acer-predator-w6x.dtsi @@ -77,6 +77,9 @@ reg = <0>; phy-mode = "2500base-x"; + nvmem-cells = <&macaddr_uboot_ethaddr 1>; + nvmem-cell-names = "mac-address"; + fixed-link { speed = <2500>; full-duplex; @@ -88,6 +91,9 @@ reg = <1>; phy-mode = "2500base-x"; phy-handle = <&phy6>; + + nvmem-cells = <&macaddr_uboot_ethaddr 0>; + nvmem-cell-names = "mac-address"; }; mdio-bus { 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 3cf6aff8da..90a746064a 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 @@ -59,6 +59,7 @@ mediatek_setup_interfaces() confiabits,mt7981|\ creatlentem,clt-r30b1|\ creatlentem,clt-r30b1-112m|\ + creatlentem,clt-r30b1-ubi|\ cudy,wr3000-v1|\ globitel,bt-r320|\ huasifei,wh3000r-nand|\ diff --git a/target/linux/mediatek/filogic/base-files/lib/preinit/10_fix_eth_mac.sh b/target/linux/mediatek/filogic/base-files/lib/preinit/10_fix_eth_mac.sh index 0d4c165e48..ead84eca26 100644 --- a/target/linux/mediatek/filogic/base-files/lib/preinit/10_fix_eth_mac.sh +++ b/target/linux/mediatek/filogic/base-files/lib/preinit/10_fix_eth_mac.sh @@ -12,16 +12,6 @@ preinit_set_mac_address() { ip link set dev game address "$lan_mac" ip link set dev eth1 address "$wan_mac" ;; - acer,predator-w6x-stock|\ - acer,predator-w6x-ubootmod) - wan_mac=$(mtd_get_mac_ascii u-boot-env ethaddr) - lan_mac=$(macaddr_add "$wan_mac" 1) - ip link set dev lan1 address "$lan_mac" - ip link set dev lan2 address "$lan_mac" - ip link set dev lan3 address "$lan_mac" - ip link set dev lan4 address "$lan_mac" - ip link set dev eth1 address "$wan_mac" - ;; acer,vero-w6m) wan_mac=$(mmc_get_mac_ascii u-boot-env WANMAC) lan_mac=$(mmc_get_mac_ascii u-boot-env LANMAC) 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 310a3d3149..25cfd887fb 100644 --- a/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh +++ b/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh @@ -149,6 +149,7 @@ platform_do_upgrade() { cmcc,rax3000m|\ cmcc,rax3000me|\ comfast,cf-wr632ax-ubootmod|\ + creatlentem,clt-r30b1-ubi|\ cudy,tr3000-v1-ubootmod|\ cudy,wbr3000uax-v1-ubootmod|\ cudy,wr3000e-v1-ubootmod|\ @@ -234,6 +235,7 @@ platform_do_upgrade() { xiaomi,redmi-router-ax6000-stock) CI_KERN_UBIPART="ubi_kernel" CI_ROOT_UBIPART="ubi" + CI_DATA_UBIPART="ubi" nand_do_upgrade "$1" ;; buffalo,wsr-6000ax8|\ @@ -367,6 +369,7 @@ platform_check_image() { cmcc,rax3000m|\ cmcc,rax3000me|\ comfast,cf-wr632ax-ubootmod|\ + creatlentem,clt-r30b1-ubi|\ cudy,tr3000-v1-ubootmod|\ cudy,wbr3000uax-v1-ubootmod|\ cudy,wr3000e-v1-ubootmod|\ diff --git a/target/linux/mediatek/image/filogic.mk b/target/linux/mediatek/image/filogic.mk index 2a5fcf8b3d..20f64cbb49 100644 --- a/target/linux/mediatek/image/filogic.mk +++ b/target/linux/mediatek/image/filogic.mk @@ -819,6 +819,8 @@ TARGET_DEVICES += bananapi_bpi-r4-lite define Device/bazis_ax3000wm DEVICE_VENDOR := Bazis DEVICE_MODEL := AX3000WM + DEVICE_ALT0_VENDOR := Shenzhen Jia Yan Technology + DEVICE_ALT0_MODEL := WD-R3000N-G2A DEVICE_DTS := mt7981b-bazis-ax3000wm DEVICE_DTS_DIR := ../dts UBINIZE_OPTS := -E 5 @@ -1130,7 +1132,7 @@ define Device/creatlentem_clt-r30b1-common DEVICE_VENDOR := CreatLentem DEVICE_MODEL := CLT-R30B1 DEVICE_ALT0_VENDOR := EDUP - DEVICE_ALT0_MODEL := RT2980 + DEVICE_ALT0_MODEL := EP-RT2980 DEVICE_ALT1_VENDOR := Dragonglass DEVICE_ALT1_MODEL := DGX21 DEVICE_ALT2_VENDOR := Livinet @@ -1141,7 +1143,6 @@ define Device/creatlentem_clt-r30b1-common BLOCKSIZE := 128k PAGESIZE := 2048 KERNEL_IN_UBI := 1 - IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata endef define Device/creatlentem_clt-r30b1-112m @@ -1152,6 +1153,7 @@ define Device/creatlentem_clt-r30b1-112m DEVICE_DTS := mt7981b-creatlentem-clt-r30b1-112m SUPPORTED_DEVICES += clt,r30b1 clt,r30b1-112m IMAGE_SIZE := 114688k + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata $(call Device/creatlentem_clt-r30b1-common) endef TARGET_DEVICES += creatlentem_clt-r30b1-112m @@ -1160,10 +1162,32 @@ define Device/creatlentem_clt-r30b1 DEVICE_DTS := mt7981b-creatlentem-clt-r30b1 SUPPORTED_DEVICES += mediatek,mt7981-spim-snand-rfb IMAGE_SIZE := 65536k + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata $(call Device/creatlentem_clt-r30b1-common) endef TARGET_DEVICES += creatlentem_clt-r30b1 +define Device/creatlentem_clt-r30b1-ubi + DEVICE_VARIANT := (UBI) + DEVICE_ALT0_VARIANT := (UBI) + DEVICE_ALT1_VARIANT := (UBI) + DEVICE_ALT2_VARIANT := (UBI) + DEVICE_DTS := mt7981b-creatlentem-clt-r30b1-ubi + 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-ubi-ddr3-1866 + ARTIFACT/bl31-uboot.fip := mt7981-bl31-uboot creatlentem_clt-r30b1-ubi + $(call Device/creatlentem_clt-r30b1-common) +endef +TARGET_DEVICES += creatlentem_clt-r30b1-ubi + define Device/cudy_ap3000outdoor-v1 DEVICE_VENDOR := Cudy DEVICE_MODEL := AP3000 Outdoor diff --git a/target/linux/mediatek/patches-6.18/432-drivers-spi-Add-support-for-dynamic-calibration.patch b/target/linux/mediatek/patches-6.18/432-drivers-spi-Add-support-for-dynamic-calibration.patch index 1b93477ed7..c39bb8f4c5 100644 --- a/target/linux/mediatek/patches-6.18/432-drivers-spi-Add-support-for-dynamic-calibration.patch +++ b/target/linux/mediatek/patches-6.18/432-drivers-spi-Add-support-for-dynamic-calibration.patch @@ -5,21 +5,21 @@ Subject: [PATCH 2/6] drivers: spi: Add support for dynamic calibration Signed-off-by: SkyLake.Huang --- - drivers/spi/spi.c | 137 ++++++++++++++++++++++++++++++++++++++++ + drivers/spi/spi.c | 140 ++++++++++++++++++++++++++++++++++++++++ include/linux/spi/spi.h | 42 ++++++++++++ - 2 files changed, 179 insertions(+) + 2 files changed, 182 insertions(+) --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c -@@ -1478,6 +1478,70 @@ static int spi_transfer_wait(struct spi_ +@@ -1478,6 +1478,73 @@ static int spi_transfer_wait(struct spi_ return 0; } +int spi_do_calibration(struct spi_controller *ctlr, struct spi_device *spi, + int (*cal_read)(void *priv, u32 *addr, int addrlen, u8 *buf, int readlen), void *drv_priv) +{ -+ int datalen = ctlr->cal_rule->datalen; -+ int addrlen = ctlr->cal_rule->addrlen; ++ int datalen; ++ int addrlen; + u8 *buf; + int ret; + int i; @@ -34,6 +34,9 @@ Signed-off-by: SkyLake.Huang + if(!ctlr->cal_target || !ctlr->cal_rule || !ctlr->append_caldata) + return 0; + ++ datalen = ctlr->cal_rule->datalen; ++ addrlen = ctlr->cal_rule->addrlen; ++ + buf = kzalloc(datalen * sizeof(u8), GFP_KERNEL); + if(!buf) + return -ENOMEM; @@ -82,7 +85,7 @@ Signed-off-by: SkyLake.Huang static void _spi_transfer_delay_ns(u32 ns) { if (!ns) -@@ -2332,6 +2396,75 @@ void spi_flush_queue(struct spi_controll +@@ -2332,6 +2399,75 @@ void spi_flush_queue(struct spi_controll /*-------------------------------------------------------------------------*/ #if defined(CONFIG_OF) @@ -158,7 +161,7 @@ Signed-off-by: SkyLake.Huang static void of_spi_parse_dt_cs_delay(struct device_node *nc, struct spi_delay *delay, const char *prop) { -@@ -2487,6 +2620,10 @@ of_register_spi_device(struct spi_contro +@@ -2487,6 +2623,10 @@ of_register_spi_device(struct spi_contro if (rc) goto err_out; diff --git a/target/linux/mediatek/patches-6.18/901-arm-add-cmdline-override.patch b/target/linux/mediatek/patches-6.18/901-arm-add-cmdline-override.patch index 505ba385df..66cbf9b6a1 100644 --- a/target/linux/mediatek/patches-6.18/901-arm-add-cmdline-override.patch +++ b/target/linux/mediatek/patches-6.18/901-arm-add-cmdline-override.patch @@ -33,7 +33,7 @@ Signed-off-by: Yoonji Park +++ b/drivers/of/fdt.c @@ -1120,6 +1120,17 @@ int __init early_init_dt_scan_chosen(cha if (p != NULL && l > 0) - strlcat(cmdline, p, min_t(int, strlen(cmdline) + (int)l, COMMAND_LINE_SIZE)); + strlcat(cmdline, p, COMMAND_LINE_SIZE); + /* CONFIG_CMDLINE_OVERRIDE is used to fallback to a different + * device tree option of chosen/bootargs-override. This is @@ -43,7 +43,7 @@ Signed-off-by: Yoonji Park +#ifdef CONFIG_CMDLINE_OVERRIDE + p = of_get_flat_dt_prop(node, "bootargs-override", &l); + if (p != NULL && l > 0) -+ strscpy(cmdline, p, min((int)l, COMMAND_LINE_SIZE)); ++ strscpy(cmdline, p, min(l, COMMAND_LINE_SIZE)); +#endif + handle_cmdline: @@ -51,7 +51,7 @@ Signed-off-by: Yoonji Park * CONFIG_CMDLINE is meant to be a default in case nothing else --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig -@@ -2398,6 +2398,14 @@ config CMDLINE_FORCE +@@ -2436,6 +2436,14 @@ config CMDLINE_FORCE endchoice diff --git a/target/linux/mpc85xx/config-6.18 b/target/linux/mpc85xx/config-6.18 index 142d6249db..80b19b2d89 100644 --- a/target/linux/mpc85xx/config-6.18 +++ b/target/linux/mpc85xx/config-6.18 @@ -187,11 +187,11 @@ CONFIG_OF_KOBJ=y CONFIG_OF_MDIO=y CONFIG_OLD_SIGACTION=y CONFIG_OLD_SIGSUSPEND=y -CONFIG_PAGE_BLOCK_MAX_ORDER=10 # CONFIG_P1010_RDB is not set # CONFIG_P1022_DS is not set # CONFIG_P1022_RDK is not set # CONFIG_P1023_RDB is not set +CONFIG_PAGE_BLOCK_MAX_ORDER=10 CONFIG_PAGE_OFFSET=0xc0000000 CONFIG_PAGE_POOL=y CONFIG_PAGE_SIZE_LESS_THAN_256KB=y diff --git a/target/linux/mpc85xx/patches-6.12/102-powerpc-add-cmdline-override.patch b/target/linux/mpc85xx/patches-6.12/102-powerpc-add-cmdline-override.patch index e7fb4bcd1b..bdd45edfac 100644 --- a/target/linux/mpc85xx/patches-6.12/102-powerpc-add-cmdline-override.patch +++ b/target/linux/mpc85xx/patches-6.12/102-powerpc-add-cmdline-override.patch @@ -19,7 +19,7 @@ +++ b/drivers/of/fdt.c @@ -1053,6 +1053,17 @@ int __init early_init_dt_scan_chosen(cha if (p != NULL && l > 0) - strlcat(cmdline, p, min_t(int, strlen(cmdline) + (int)l, COMMAND_LINE_SIZE)); + strlcat(cmdline, p, COMMAND_LINE_SIZE); + /* CONFIG_CMDLINE_OVERRIDE is used to fallback to a different + * device tree option of chosen/bootargs-override. This is @@ -29,7 +29,7 @@ +#ifdef CONFIG_CMDLINE_OVERRIDE + p = of_get_flat_dt_prop(node, "bootargs-override", &l); + if (p != NULL && l > 0) -+ strscpy(cmdline, p, COMMAND_LINE_SIZE); ++ strscpy(cmdline, p, min(l, COMMAND_LINE_SIZE)); +#endif + handle_cmdline: diff --git a/target/linux/mpc85xx/patches-6.18/102-powerpc-add-cmdline-override.patch b/target/linux/mpc85xx/patches-6.18/102-powerpc-add-cmdline-override.patch index 2fe98ff9ad..f2ea1febb7 100644 --- a/target/linux/mpc85xx/patches-6.18/102-powerpc-add-cmdline-override.patch +++ b/target/linux/mpc85xx/patches-6.18/102-powerpc-add-cmdline-override.patch @@ -19,7 +19,7 @@ +++ b/drivers/of/fdt.c @@ -1120,6 +1120,17 @@ int __init early_init_dt_scan_chosen(cha if (p != NULL && l > 0) - strlcat(cmdline, p, min_t(int, strlen(cmdline) + (int)l, COMMAND_LINE_SIZE)); + strlcat(cmdline, p, COMMAND_LINE_SIZE); + /* CONFIG_CMDLINE_OVERRIDE is used to fallback to a different + * device tree option of chosen/bootargs-override. This is @@ -29,7 +29,7 @@ +#ifdef CONFIG_CMDLINE_OVERRIDE + p = of_get_flat_dt_prop(node, "bootargs-override", &l); + if (p != NULL && l > 0) -+ strscpy(cmdline, p, COMMAND_LINE_SIZE); ++ strscpy(cmdline, p, min(l, COMMAND_LINE_SIZE)); +#endif + handle_cmdline: diff --git a/target/linux/mvebu/cortexa53/base-files/lib/upgrade/platform.sh b/target/linux/mvebu/cortexa53/base-files/lib/upgrade/platform.sh index 8b8149c96b..e62e72ba55 100755 --- a/target/linux/mvebu/cortexa53/base-files/lib/upgrade/platform.sh +++ b/target/linux/mvebu/cortexa53/base-files/lib/upgrade/platform.sh @@ -43,6 +43,7 @@ methode_update_active_bootscript() { platform_check_image() { case "$(board_name)" in + cznic,turris-mox|\ glinet,gl-mv1000|\ globalscale,espressobin|\ globalscale,espressobin-emmc|\ @@ -59,6 +60,7 @@ platform_check_image() { platform_do_upgrade() { case "$(board_name)" in + cznic,turris-mox|\ glinet,gl-mv1000|\ globalscale,espressobin|\ globalscale,espressobin-emmc|\ @@ -117,6 +119,7 @@ platform_do_upgrade() { } platform_copy_config() { case "$(board_name)" in + cznic,turris-mox|\ glinet,gl-mv1000|\ globalscale,espressobin|\ globalscale,espressobin-emmc|\ diff --git a/target/linux/mvebu/cortexa9/base-files/etc/board.d/02_network b/target/linux/mvebu/cortexa9/base-files/etc/board.d/02_network index cd0f4c99c4..9833143d75 100644 --- a/target/linux/mvebu/cortexa9/base-files/etc/board.d/02_network +++ b/target/linux/mvebu/cortexa9/base-files/etc/board.d/02_network @@ -15,7 +15,8 @@ mvebu_setup_interfaces() ctera,c200-v2|\ synology,ds213j|\ wd,cloud-ex2-ultra|\ - wd,cloud-mirror-gen2) + wd,cloud-mirror-gen2|\ + zyxel,nas326) ucidef_set_interface_lan "eth0" "dhcp" ;; cznic,turris-omnia) @@ -104,6 +105,10 @@ mvebu_setup_macs() label_mac=$(macaddr_canonicalize $(strings /dev/mtd7|grep -E '([0-9A-F]{2}[:])')) lan_mac=$label_mac ;; + zyxel,nas326) + label_mac=$(mtd_get_mac_ascii u-boot-env ethaddr) + lan_mac=$label_mac + ;; esac [ -n "$lan_mac" ] && ucidef_set_interface_macaddr "lan" $lan_mac diff --git a/target/linux/mvebu/cortexa9/base-files/lib/upgrade/platform.sh b/target/linux/mvebu/cortexa9/base-files/lib/upgrade/platform.sh index a30f4bc1e2..8198bea7b7 100755 --- a/target/linux/mvebu/cortexa9/base-files/lib/upgrade/platform.sh +++ b/target/linux/mvebu/cortexa9/base-files/lib/upgrade/platform.sh @@ -8,6 +8,14 @@ RAMFS_COPY_DATA='/etc/fw_env.config /var/lock/fw_printenv.lock' REQUIRE_IMAGE_METADATA=1 +nas326_initial_setup() +{ + # initialize UBI if it's running on initramfs + [ "$(rootfs_type)" = "tmpfs" ] || return 0 + + ubirmvol /dev/ubi0 -N ubi_rootfs1 +} + platform_check_image() { case "$(board_name)" in cznic,turris-omnia|\ @@ -29,6 +37,7 @@ platform_do_upgrade() { CI_KERNPART=boot CI_KERN_UBIPART=ubi_kernel CI_ROOT_UBIPART=ubi + CI_DATA_UBIPART=ubi nand_do_upgrade "$1" ;; buffalo,ls421de|\ @@ -36,6 +45,10 @@ platform_do_upgrade() { wd,cloud-mirror-gen2) nand_do_upgrade "$1" ;; + zyxel,nas326) + nas326_initial_setup + nand_do_upgrade "$1" + ;; ctera,c200-v2) part=$(find_mtd_part "active_bank") diff --git a/target/linux/mvebu/files/arch/arm/boot/dts/marvell/armada-380-zyxel-nas326.dts b/target/linux/mvebu/files/arch/arm/boot/dts/marvell/armada-380-zyxel-nas326.dts new file mode 100644 index 0000000000..ca88040a13 --- /dev/null +++ b/target/linux/mvebu/files/arch/arm/boot/dts/marvell/armada-380-zyxel-nas326.dts @@ -0,0 +1,383 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; + +#include +#include +#include +#include "armada-380.dtsi" + +/ { + model = "Zyxel NAS326"; + compatible = "zyxel,nas326", "marvell,armada380"; + + aliases { + led-boot = &status_white; + led-failsafe = &status_red; + led-running = &status_white; + led-upgrade = &status_white; + label-mac-device = ð0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + append-rootblock = "nullparameter="; /* override the bootloader args */ + }; + + memory@0 { + device_type = "memory"; + reg = <0x00000000 0x20000000>; /* 512MB */ + }; + + soc { + ranges = ; + + internal-regs { + timer@c200 { + status = "okay"; + }; + + pcie { + status = "okay"; + + pcie@1,0 { + status = "okay"; + }; + + pcie@2,0 { + status = "okay"; + }; + }; + }; + }; + + usb2_phy: usb2_phy { + compatible = "usb-nop-xceiv"; + vcc-supply = <&usb2_power>; + }; + + gpio-keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&button_pins>; + + power { + label = "Power Button"; + linux,code = ; + gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>; + }; + + copy { + label = "Copy Button"; + linux,code = ; + gpios = <&gpio1 7 GPIO_ACTIVE_LOW>; + }; + + reset { + label = "Reset Button"; + linux,code = ; + gpios = <&gpio1 17 GPIO_ACTIVE_HIGH>; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins>; + + sata1white { + color = ; + function = LED_FUNCTION_DISK_ACTIVITY; + function-enumerator = <1>; + gpios = <&gpio1 18 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "ata1"; + }; + + sata1red { + color = ; + function = LED_FUNCTION_DISK_ERR; + function-enumerator = <1>; + gpios = <&gpio1 16 GPIO_ACTIVE_HIGH>; + }; + + sata2white { + color = ; + function = LED_FUNCTION_DISK_ACTIVITY; + function-enumerator = <2>; + gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "ata2"; + }; + + sata2red { + color = ; + function = LED_FUNCTION_DISK_ERR; + function-enumerator = <2>; + gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>; + }; + + usb { + color = ; + function = LED_FUNCTION_USB; + gpios = <&gpio0 21 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "usb-host"; + }; + + status_white: status_white { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&gpio1 20 GPIO_ACTIVE_HIGH>; + }; + + status_red: status_red { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>; + }; + + copy_white { + color = ; + function = "copy"; + gpios = <&gpio0 26 GPIO_ACTIVE_HIGH>; + }; + + copy_red { + color = ; + function = "copy"; + gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>; + }; + }; + + regulators { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + + usb2_power: regulator@1 { + compatible = "regulator-fixed"; + reg = <1>; + regulator-name = "USB2 Power"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + regulator-always-on; + regulator-boot-on; + gpio = <&gpio1 11 GPIO_ACTIVE_HIGH>; + }; + + reg_sata0: regulator@2 { + compatible = "regulator-fixed"; + regulator-name = "pwr_en_sata0"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + regulator-boot-on; + gpio = <&gpio1 13 GPIO_ACTIVE_HIGH>; + }; + + reg_5v_sata0: v5-sata0 { + compatible = "regulator-fixed"; + regulator-name = "v5.0-sata0"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <®_sata0>; + }; + + reg_12v_sata0: v12-sata0 { + compatible = "regulator-fixed"; + regulator-name = "v12.0-sata0"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + vin-supply = <®_sata0>; + }; + + reg_sata1: regulator@3 { + regulator-name = "pwr_en_sata1"; + compatible = "regulator-fixed"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + regulator-boot-on; + gpio = <&gpio0 29 GPIO_ACTIVE_HIGH>; + }; + + reg_5v_sata1: v5-sata1 { + compatible = "regulator-fixed"; + regulator-name = "v5.0-sata1"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <®_sata1>; + }; + + reg_12v_sata1: v12-sata1 { + compatible = "regulator-fixed"; + regulator-name = "v12.0-sata1"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + vin-supply = <®_sata1>; + }; + }; + + gpio-poweroff { + compatible = "gpio-poweroff"; + pinctrl-0 = <&pwr_off>; + pinctrl-names = "default"; + gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>; + }; +}; + +&ahci0 { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + sata-port@0 { + reg = <0>; + target-supply = <®_sata0>; + #thermal-sensor-cells = <0>; + }; + + sata-port@1 { + reg = <1>; + target-supply = <®_sata1>; + #thermal-sensor-cells = <1>; + }; +}; + +&bm { + status = "okay"; +}; + +&bm_bppi { + status = "okay"; +}; + +ð0 { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&ge0_rgmii_pins>; + phy = <&phy0>; + phy-mode = "rgmii-id"; +}; + +&i2c0 { + status = "okay"; + clock-frequency = <100000>; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <100000>; +}; + +&mdio { + phy0: ethernet-phy@1 { + marvell,reg-init = <0x01 0x16 0x00 0x03 0x01 0x10 0x00 0x1817 0x01 0x11 0x00 0x442a 0x01 0x16 0x00 0x00 0x01 0x00 0x00 0x1140 0x01 0x04 0x00 0x1e1 0x01 0x10 0x00 0x3860 0x01 0x00 0x00 0x9140>; + reg = <1>; + }; +}; + +&nand_controller { + status = "okay"; + + nand: nand@0 { + reg = <0>; + label = "pxa3xx_nand-0"; + nand-rb = <0>; + marvell,nand-keep-config; + nand-on-flash-bbt; + nand-ecc-strength = <4>; + nand-ecc-step-size = <512>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "U-Boot"; + reg = <0x0 0x200000>; + read-only; + }; + + partition@200000 { + label = "u-boot-env"; + reg = <0x200000 0x200000>; + }; + + partition@400000 { + label = "Config"; + reg = <0x400000 0xa00000>; + read-only; + }; + + partition@e00000 { + label = "kernel"; + reg = <0xe00000 0xf00000>;/* 15 MB */ + }; + + partition@1d00000 { + label = "ubi"; + reg = <0x1d00000 0x6a00000>;/* 106 MB */ + }; + + partition@8700000 { + label = "Kernel-2"; + reg = <0x8700000 0xf00000>; + read-only; + }; + + partition@9600000 { + label = "RootFS-2"; + reg = <0x9600000 0x6a00000>; + read-only; + }; + }; + }; +}; + +&pinctrl { + button_pins: button_pins { + marvell,pins = "mpp39", "mpp46", "mpp49"; + marvell,function = "gpio"; + }; + + led_pins: led_pins { + marvell,pins = "mpp21", "mpp26", "mpp37", + "mpp48", "mpp50", "mpp52", + "mpp53", "mpp54", "mpp55"; + marvell,function = "gpio"; + }; + + pwr_off: pwr_off { + marvell,pins = "mpp20"; + marvell,function = "gpio"; + }; +}; + +&sdhci { + broken-cd; + wp-inverted; + bus-width = <8>; + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&usb0 { + status = "okay"; +}; + +&usb3_0 { + status = "okay"; +}; + +&usb3_1 { + status = "okay"; +}; diff --git a/target/linux/mvebu/image/cortexa53.mk b/target/linux/mvebu/image/cortexa53.mk index 8bc153ce69..3f6cbec71d 100644 --- a/target/linux/mvebu/image/cortexa53.mk +++ b/target/linux/mvebu/image/cortexa53.mk @@ -6,7 +6,7 @@ define Device/cznic_turris-mox kmod-rtc-ds1307 kmod-i2c-pxa kmod-dsa kmod-dsa-mv88e6xxx kmod-sfp \ kmod-phy-marvell kmod-phy-marvell-10g kmod-ath10k ath10k-board-qca988x \ ath10k-firmware-qca988x kmod-mt7915e kmod-mt7915-firmware mwlwifi-firmware-88w8997 \ - wpad-openssl kmod-mwifiex-sdio + wpad-openssl kmod-mwifiex-sdio kmod-btmrvl SOC := armada-3720 BOOT_SCRIPT := turris-mox endef diff --git a/target/linux/mvebu/image/cortexa9.mk b/target/linux/mvebu/image/cortexa9.mk index 0890df630e..b8d71675a4 100644 --- a/target/linux/mvebu/image/cortexa9.mk +++ b/target/linux/mvebu/image/cortexa9.mk @@ -497,3 +497,17 @@ define Device/wd_cloud-mirror-gen2 IMAGE/uImage-factory.bin := append-kernel endef TARGET_DEVICES += wd_cloud-mirror-gen2 + +define Device/zyxel_nas326 + $(Device/NAND-128K) + DEVICE_VENDOR := Zyxel + DEVICE_MODEL := NAS326 + DEVICE_PACKAGES += mkf2fs e2fsprogs \ + partx-utils kmod-hwmon-drivetemp -ppp -kmod-nft-offload -dnsmasq \ + -odhcpd-ipv6only + DEVICE_DTS := armada-380-zyxel-nas326 + FILESYSTEMS := squashfs ubifs + KERNEL := kernel-bin | append-dtb + KERNEL_INITRAMFS := kernel-bin | append-dtb | uImage none +endef +TARGET_DEVICES += zyxel_nas326 diff --git a/target/linux/mvebu/image/turris-mox.bootscript b/target/linux/mvebu/image/turris-mox.bootscript index 29d16964af..6a4d4cd60f 100644 --- a/target/linux/mvebu/image/turris-mox.bootscript +++ b/target/linux/mvebu/image/turris-mox.bootscript @@ -40,7 +40,7 @@ if part uuid ${devtype} ${devnum}:${distro_bootpart} bootuuid; then fi fi if test "$filesize" != "0"; then - setenv bootargs "earlyprintk console=ttyMV0,115200 earlycon=ar3700_uart,0xd0012000 rootfstype=${rootfstype} root=${rootdev} rootflags=${rootflags} rootwait ${contract} rw cfg80211.freg=${regdomain} ${quirks}" + setenv bootargs "earlyprintk console=ttyMV0,115200 earlycon=ar3700_uart,0xd0012000 rootfstype=${rootfstype} root=${rootdev} rootflags=${rootflags} rootwait ${contract} rw cfg80211.freg=${regdomain} sysctl.kernel.firmware_config.force_sysfs_fallback=0 ${quirks}" booti ${kernel_addr_r} - ${fdt_addr_r} echo "Booting Image failed" else diff --git a/target/linux/qualcommax/dts/ipq8074-deco-x80-5g.dts b/target/linux/qualcommax/dts/ipq8074-deco-x80-5g.dts index 09f8be6e15..2f14b554cc 100644 --- a/target/linux/qualcommax/dts/ipq8074-deco-x80-5g.dts +++ b/target/linux/qualcommax/dts/ipq8074-deco-x80-5g.dts @@ -33,8 +33,8 @@ to suit the TP-Link Deco X80-5G target */ w_disable { gpio-export,name = "w_disable"; - gpio-export,output = <1>; - gpios = <&tlmm 35 GPIO_ACTIVE_HIGH>; /* wwan disable output */ + gpio-export,output = <0>; + gpios = <&tlmm 55 GPIO_ACTIVE_LOW>; /* wwan disable output */ }; modem-reset { @@ -48,6 +48,12 @@ to suit the TP-Link Deco X80-5G target */ gpio-export,output = <0>; gpios = <&tlmm 56 GPIO_ACTIVE_HIGH>; /* select external sma antennas for wwan output */ }; + + modem-power { /* sdx_pon_gpio for pcie */ + gpio-export,name = "modem_power"; + gpio-export,output = <1>; + gpios = <&tlmm 30 GPIO_ACTIVE_HIGH>; + }; }; gpio_keys { @@ -315,11 +321,27 @@ to suit the TP-Link Deco X80-5G target */ bias-disable; }; - modem_pins: modem-state { - pins = "gpio29", "gpio55"; - function = "gpio"; - drive-strength = <2>; - bias-disable; + modem_pins: modem-pins { + modem_power_on { + bias-pull-up; + drive-strength = <8>; + output-high; + pins = "gpio30"; + function = "gpio"; + }; + + modem_reset { + drive-strength = <8>; + output-high; + pins = "gpio29"; + }; + + w_disable { + pins = "gpio55"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; }; led_pins: led-state { @@ -344,6 +366,13 @@ to suit the TP-Link Deco X80-5G target */ bias-pull-up; }; }; + + pcie0_default_state: pcie0_wake_gpio { + bias-pull-up; + drive-strength = <8>; + function = "pcie0_wake"; + pins = "gpio59"; + }; }; &blsp1_uart5 { @@ -456,3 +485,20 @@ to suit the TP-Link Deco X80-5G target */ status = "okay"; qcom,ath11k-calibration-variant = "tplink_deco-x80-5g"; }; + +&pcie_qmp0 { + status = "okay"; +}; + +&pcie0 { + status = "okay"; + pinctrl-0 = <&pcie0_default_state>; + pinctrl-names = "default"; + perst-gpio = <&tlmm 58 GPIO_ACTIVE_LOW>; + + pcie@0 { + modem@0,0 { + reg = <0x00 0x00 0x00 0x00 0x00>; + }; + }; +}; diff --git a/target/linux/qualcommax/image/ipq807x.mk b/target/linux/qualcommax/image/ipq807x.mk index 6c517df578..3e2f107995 100644 --- a/target/linux/qualcommax/image/ipq807x.mk +++ b/target/linux/qualcommax/image/ipq807x.mk @@ -483,7 +483,8 @@ define Device/tplink_deco-x80-5g DEVICE_DTS_CONFIG := config@hk01.c5 SOC := ipq8074 DEVICE_PACKAGES := kmod-hwmon-gpiofan ipq-wifi-tplink_deco-x80-5g \ - kmod-usb-serial-option kmod-usb-net-qmi-wwan + kmod-usb-serial-option kmod-usb-net-qmi-wwan kmod-mhi-pci-generic \ + kmod-mhi-wwan-ctrl kmod-mhi-wwan-mbim endef TARGET_DEVICES += tplink_deco-x80-5g diff --git a/target/linux/qualcommax/ipq50xx/base-files/lib/upgrade/platform.sh b/target/linux/qualcommax/ipq50xx/base-files/lib/upgrade/platform.sh index a5a4dc5bbb..13ccc3986e 100644 --- a/target/linux/qualcommax/ipq50xx/base-files/lib/upgrade/platform.sh +++ b/target/linux/qualcommax/ipq50xx/base-files/lib/upgrade/platform.sh @@ -229,6 +229,7 @@ platform_do_upgrade() { # Kernel and rootfs are placed in 2 different UBI CI_KERN_UBIPART="ubi_kernel" CI_ROOT_UBIPART="rootfs" + CI_DATA_UBIPART="rootfs" nand_do_upgrade "$1" ;; yuncore,ax830|\ 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 dbb5f50a5e..0f14005d63 100644 --- a/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh +++ b/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh @@ -200,6 +200,7 @@ platform_do_upgrade() { buffalo,wxr-5950ax12) CI_KERN_UBIPART="rootfs" CI_ROOT_UBIPART="user_property" + CI_DATA_UBIPART="user_property" buffalo_upgrade_prepare nand_do_flash_file "$1" || nand_do_upgrade_failed nand_do_restore_config || nand_do_upgrade_failed @@ -258,6 +259,7 @@ platform_do_upgrade() { # Kernel and rootfs are placed in 2 different UBI CI_KERN_UBIPART="ubi_kernel" CI_ROOT_UBIPART="rootfs" + CI_DATA_UBIPART="rootfs" nand_do_upgrade "$1" ;; redmi,ax6-stock|\ @@ -330,6 +332,7 @@ platform_do_upgrade() { zte,mf269) CI_KERN_UBIPART="ubi_kernel" CI_ROOT_UBIPART="rootfs" + CI_DATA_UBIPART="rootfs" nand_do_upgrade "$1" ;; zte,mf269-stock) diff --git a/target/linux/qualcommax/patches-6.12/0911-arm64-cmdline-replacement.patch b/target/linux/qualcommax/patches-6.12/0911-arm64-cmdline-replacement.patch index 8e72f181a6..127677d220 100644 --- a/target/linux/qualcommax/patches-6.12/0911-arm64-cmdline-replacement.patch +++ b/target/linux/qualcommax/patches-6.12/0911-arm64-cmdline-replacement.patch @@ -91,7 +91,7 @@ Signed-off-by: Qiyuan Zhang + *(cur_ptr + offset) = *cur_ptr; + } + -+ strncpy(s_ptr, p, r_len - 1); ++ memcpy(s_ptr, p, r_len - 1); + + pr_info("Kernel command line after replacement: %s\n", cmdline); + } else { @@ -102,4 +102,4 @@ Signed-off-by: Qiyuan Zhang + p = of_get_flat_dt_prop(node, "bootargs-append", &l); if (p != NULL && l > 0) - strlcat(cmdline, p, min_t(int, strlen(cmdline) + (int)l, COMMAND_LINE_SIZE)); + strlcat(cmdline, p, COMMAND_LINE_SIZE); diff --git a/target/linux/qualcommbe/Makefile b/target/linux/qualcommbe/Makefile index 46b274620a..940f99442e 100644 --- a/target/linux/qualcommbe/Makefile +++ b/target/linux/qualcommbe/Makefile @@ -8,8 +8,7 @@ KERNELNAME:=Image CPU_TYPE:=cortex-a53 SUBTARGETS:=ipq95xx -KERNEL_PATCHVER:=6.12 -KERNEL_TESTING_PATCHVER:=6.18 +KERNEL_PATCHVER:=6.18 include $(INCLUDE_DIR)/target.mk DEFAULT_PACKAGES += \ diff --git a/target/linux/qualcommbe/config-6.12 b/target/linux/qualcommbe/config-6.12 deleted file mode 100644 index 5178c3bf24..0000000000 --- a/target/linux/qualcommbe/config-6.12 +++ /dev/null @@ -1,618 +0,0 @@ -CONFIG_64BIT=y -CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y -CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y -CONFIG_ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG=y -CONFIG_ARCH_DMA_ADDR_T_64BIT=y -CONFIG_ARCH_FORCE_MAX_ORDER=10 -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_PKEY_BITS=3 -CONFIG_ARCH_PROC_KCORE_TEXT=y -CONFIG_ARCH_QCOM=y -CONFIG_ARCH_SPARSEMEM_ENABLE=y -CONFIG_ARCH_STACKWALK=y -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ARCH_WANTS_EXECMEM_LATE=y -CONFIG_ARCH_WANTS_NO_INSTR=y -CONFIG_ARCH_WANTS_THP_SWAP=y -CONFIG_ARM64=y -CONFIG_ARM64_4K_PAGES=y -CONFIG_ARM64_ERRATUM_1165522=y -CONFIG_ARM64_ERRATUM_1286807=y -CONFIG_ARM64_ERRATUM_2051678=y -CONFIG_ARM64_ERRATUM_2054223=y -CONFIG_ARM64_ERRATUM_2067961=y -CONFIG_ARM64_ERRATUM_2077057=y -CONFIG_ARM64_ERRATUM_2658417=y -CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y -CONFIG_ARM64_PA_BITS=48 -CONFIG_ARM64_PA_BITS_48=y -CONFIG_ARM64_PLATFORM_DEVICES=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_ARM64_WORKAROUND_TSB_FLUSH_FAILURE=y -CONFIG_ARM_AMBA=y -CONFIG_ARM_ARCH_TIMER=y -CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y -CONFIG_ARM_GIC=y -CONFIG_ARM_GIC_V2M=y -CONFIG_ARM_GIC_V3=y -CONFIG_ARM_GIC_V3_ITS=y -# CONFIG_ARM_MHU_V2 is not set -# CONFIG_ARM_MHU_V3 is not set -CONFIG_ARM_PSCI_CPUIDLE=y -CONFIG_ARM_PSCI_FW=y -# CONFIG_ARM_QCOM_CPUFREQ_HW is not set -CONFIG_ARM_QCOM_CPUFREQ_NVMEM=y -CONFIG_AT803X_PHY=y -CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y -CONFIG_AUXILIARY_BUS=y -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_SD=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_MQ_VIRTIO=y -CONFIG_BLK_PM=y -CONFIG_BUILTIN_RETURN_ADDRESS_STRIPS_PAC=y -CONFIG_CC_HAVE_SHADOW_CALL_STACK=y -CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y -# CONFIG_CLK_QCM2290_GPUCC is not set -# CONFIG_CLK_X1E80100_CAMCC is not set -# CONFIG_CLK_X1E80100_DISPCC is not set -# CONFIG_CLK_X1E80100_GCC is not set -# CONFIG_CLK_X1E80100_GPUCC is not set -# CONFIG_CLK_X1E80100_TCSRCC is not set -CONFIG_CLONE_BACKWARDS=y -CONFIG_COMMON_CLK=y -CONFIG_COMMON_CLK_QCOM=y -CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 -# CONFIG_COMPAT_32BIT_TIME is not set -CONFIG_CONTEXT_TRACKING=y -CONFIG_CONTEXT_TRACKING_IDLE=y -CONFIG_COREDUMP=y -CONFIG_CPUFREQ_DT=y -CONFIG_CPUFREQ_DT_PLATDEV=y -CONFIG_CPU_FREQ=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=y -CONFIG_CPU_FREQ_GOV_ATTR_SET=y -# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set -# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set -CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y -# CONFIG_CPU_FREQ_GOV_USERSPACE is not set -CONFIG_CPU_FREQ_STAT=y -CONFIG_CPU_FREQ_THERMAL=y -CONFIG_CPU_IDLE=y -CONFIG_CPU_IDLE_GOV_MENU=y -CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_CPU_MITIGATIONS=y -CONFIG_CPU_PM=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_THERMAL=y -CONFIG_CRC16=y -CONFIG_CRC8=y -CONFIG_CRYPTO_AUTHENC=y -CONFIG_CRYPTO_CBC=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_DEV_QCE=y -CONFIG_CRYPTO_DEV_QCE_AEAD=y -# CONFIG_CRYPTO_DEV_QCE_ENABLE_AEAD is not set -CONFIG_CRYPTO_DEV_QCE_ENABLE_ALL=y -# CONFIG_CRYPTO_DEV_QCE_ENABLE_SHA is not set -# CONFIG_CRYPTO_DEV_QCE_ENABLE_SKCIPHER is not set -CONFIG_CRYPTO_DEV_QCE_SHA=y -CONFIG_CRYPTO_DEV_QCE_SKCIPHER=y -CONFIG_CRYPTO_DEV_QCE_SW_MAX_LEN=512 -CONFIG_CRYPTO_DEV_QCOM_RNG=y -CONFIG_CRYPTO_ECB=y -CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_HW=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_DES=y -CONFIG_CRYPTO_LIB_GF128MUL=y -CONFIG_CRYPTO_LIB_SHA256=y -CONFIG_CRYPTO_LIB_UTILS=y -CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_RNG=y -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_SHA256=y -CONFIG_CRYPTO_XTS=y -CONFIG_CRYPTO_ZSTD=y -CONFIG_DCACHE_WORD_ACCESS=y -CONFIG_DEBUG_BUGVERBOSE=y -CONFIG_DEBUG_INFO=y -CONFIG_DEV_COREDUMP=y -CONFIG_DMADEVICES=y -CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC=y -CONFIG_DMA_DIRECT_REMAP=y -CONFIG_DMA_ENGINE=y -CONFIG_DMA_NEED_SYNC=y -CONFIG_DMA_OF=y -CONFIG_DMA_VIRTUAL_CHANNELS=y -CONFIG_DTC=y -CONFIG_DT_IDLE_STATES=y -CONFIG_EDAC_SUPPORT=y -CONFIG_EXCLUSIVE_SYSTEM_RAM=y -CONFIG_FIXED_PHY=y -CONFIG_FIX_EARLYCON_MEM=y -CONFIG_FRAME_POINTER=y -CONFIG_FS_IOMAP=y -CONFIG_FUNCTION_ALIGNMENT=4 -CONFIG_FUNCTION_ALIGNMENT_4B=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_FW_LOADER_SYSFS=y -CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS=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_DEVICES=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_EFFECTIVE_AFF_MASK=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_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_CDEV=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HWMON=y -CONFIG_HWSPINLOCK=y -CONFIG_HWSPINLOCK_QCOM=y -CONFIG_HW_RANDOM=y -CONFIG_I2C=y -CONFIG_I2C_BOARDINFO=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_HELPER_AUTO=y -# CONFIG_I2C_QCOM_CCI is not set -CONFIG_I2C_QUP=y -CONFIG_IIO=y -CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 -CONFIG_INITRAMFS_SOURCE="" -CONFIG_INTERCONNECT=y -CONFIG_INTERCONNECT_CLK=y -# CONFIG_INTERCONNECT_QCOM is not set -CONFIG_IPQ_APSS_6018=y -CONFIG_IPQ_APSS_PLL=y -# CONFIG_IPQ_CMN_PLL is not set -# CONFIG_IPQ_GCC_4019 is not set -# CONFIG_IPQ_GCC_5018 is not set -# CONFIG_IPQ_GCC_5332 is not set -# CONFIG_IPQ_GCC_6018 is not set -# CONFIG_IPQ_GCC_8074 is not set -# CONFIG_IPQ_GCC_9574 is not set -# CONFIG_IPQ_NSSCC_QCA8K is not set -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_DOMAIN_HIERARCHY=y -CONFIG_IRQ_FASTEOI_HIERARCHY_HANDLERS=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_MSI_LIB=y -CONFIG_IRQ_WORK=y -# CONFIG_KPSS_XCC is not set -CONFIG_LEDS_TLC591XX=y -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LOCK_SPIN_ON_OWNER=y -CONFIG_LRU_GEN_WALKS_MMU=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -CONFIG_MAILBOX=y -# CONFIG_MAILBOX_TEST is not set -CONFIG_MDIO_BUS=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -CONFIG_MDIO_IPQ4019=y -# CONFIG_MFD_QCOM_RPM is not set -CONFIG_MFD_SYSCON=y -CONFIG_MIGRATION=y -# CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY is not set -CONFIG_MMC=y -CONFIG_MMC_BLOCK=y -CONFIG_MMC_BLOCK_MINORS=32 -CONFIG_MMC_CQHCI=y -CONFIG_MMC_SDHCI=y -CONFIG_MMC_SDHCI_IO_ACCESSORS=y -CONFIG_MMC_SDHCI_MSM=y -CONFIG_MMC_SDHCI_PLTFM=y -CONFIG_MMU_LAZY_TLB_REFCOUNT=y -CONFIG_MODULES_USE_ELF_RELA=y -# CONFIG_MSM_GCC_8916 is not set -# CONFIG_MSM_GCC_8917 is not set -# CONFIG_MSM_GCC_8939 is not set -# CONFIG_MSM_GCC_8976 is not set -# CONFIG_MSM_GCC_8994 is not set -# CONFIG_MSM_GCC_8996 is not set -# CONFIG_MSM_GCC_8998 is not set -# CONFIG_MSM_GPUCC_8998 is not set -# CONFIG_MSM_MMCC_8996 is not set -# CONFIG_MSM_MMCC_8998 is not set -CONFIG_MTD_NAND_CORE=y -CONFIG_MTD_NAND_ECC=y -CONFIG_MTD_NAND_ECC_SW_HAMMING=y -CONFIG_MTD_NAND_QCOM=y -CONFIG_MTD_QCOMSMEM_PARTS=y -CONFIG_MTD_RAW_NAND=y -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_UBI=y -CONFIG_MTD_UBI_BEB_LIMIT=20 -CONFIG_MTD_UBI_BLOCK=y -CONFIG_MTD_UBI_WL_THRESHOLD=4096 -CONFIG_MUTEX_SPIN_ON_OWNER=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NEED_SG_DMA_LENGTH=y -CONFIG_NET_EGRESS=y -CONFIG_NET_FLOW_LIMIT=y -CONFIG_NET_INGRESS=y -CONFIG_NET_SELFTESTS=y -CONFIG_NET_XGRESS=y -CONFIG_NLS=y -CONFIG_NO_HZ_COMMON=y -CONFIG_NO_HZ_IDLE=y -CONFIG_NR_CPUS=4 -# CONFIG_NSM is not set -CONFIG_NVMEM=y -CONFIG_NVMEM_LAYOUTS=y -CONFIG_NVMEM_LAYOUT_U_BOOT_ENV=y -CONFIG_NVMEM_QCOM_QFPROM=y -# CONFIG_NVMEM_QCOM_SEC_QFPROM is not set -CONFIG_NVMEM_SYSFS=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_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_PCIEASPM=y -CONFIG_PCIEASPM_DEFAULT=y -# CONFIG_PCIEASPM_PERFORMANCE is not set -# CONFIG_PCIEASPM_POWERSAVE is not set -# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set -CONFIG_PCIEPORTBUS=y -CONFIG_PCIE_DW=y -CONFIG_PCIE_DW_HOST=y -CONFIG_PCIE_PME=y -CONFIG_PCIE_QCOM=y -CONFIG_PCIE_QCOM_COMMON=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DOMAINS_GENERIC=y -CONFIG_PCI_MSI=y -# CONFIG_PCS_QCOM_IPQ9574 is not set -CONFIG_PER_VMA_LOCK=y -CONFIG_PGTABLE_LEVELS=3 -CONFIG_PHYLIB=y -CONFIG_PHYLIB_LEDS=y -CONFIG_PHYS_ADDR_T_64BIT=y -# CONFIG_PHY_QCOM_APQ8064_SATA is not set -# CONFIG_PHY_QCOM_EDP is not set -# CONFIG_PHY_QCOM_EUSB2_REPEATER is not set -# CONFIG_PHY_QCOM_IPQ4019_USB is not set -# CONFIG_PHY_QCOM_IPQ806X_SATA is not set -# CONFIG_PHY_QCOM_IPQ806X_USB is not set -# CONFIG_PHY_QCOM_M31_USB is not set -# CONFIG_PHY_QCOM_PCIE2 is not set -CONFIG_PHY_QCOM_QMP=y -CONFIG_PHY_QCOM_QMP_COMBO=y -CONFIG_PHY_QCOM_QMP_PCIE=y -CONFIG_PHY_QCOM_QMP_PCIE_8996=y -CONFIG_PHY_QCOM_QMP_UFS=y -CONFIG_PHY_QCOM_QMP_USB=y -# CONFIG_PHY_QCOM_QMP_USB_LEGACY is not set -CONFIG_PHY_QCOM_QUSB2=y -# CONFIG_PHY_QCOM_SGMII_ETH is not set -# CONFIG_PHY_QCOM_SNPS_EUSB2 is not set -# CONFIG_PHY_QCOM_USB_HS_28NM is not set -# CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2 is not set -# CONFIG_PHY_QCOM_USB_SS is not set -CONFIG_PINCTRL=y -# CONFIG_PINCTRL_IPQ5018 is not set -# CONFIG_PINCTRL_IPQ5332 is not set -# CONFIG_PINCTRL_IPQ6018 is not set -# CONFIG_PINCTRL_IPQ8074 is not set -# CONFIG_PINCTRL_IPQ9574 is not set -CONFIG_PINCTRL_MSM=y -# CONFIG_PINCTRL_MSM8916 is not set -# CONFIG_PINCTRL_MSM8976 is not set -# CONFIG_PINCTRL_MSM8994 is not set -# CONFIG_PINCTRL_MSM8996 is not set -# CONFIG_PINCTRL_MSM8998 is not set -# CONFIG_PINCTRL_QCM2290 is not set -# CONFIG_PINCTRL_QCOM_SSBI_PMIC is not set -# CONFIG_PINCTRL_QCS404 is not set -# CONFIG_PINCTRL_QDU1000 is not set -# CONFIG_PINCTRL_SA8775P is not set -# CONFIG_PINCTRL_SC7180 is not set -# CONFIG_PINCTRL_SC8280XP is not set -# CONFIG_PINCTRL_SDM660 is not set -# CONFIG_PINCTRL_SDM670 is not set -# CONFIG_PINCTRL_SDM845 is not set -# CONFIG_PINCTRL_SDX75 is not set -# CONFIG_PINCTRL_SM4450 is not set -# CONFIG_PINCTRL_SM6350 is not set -# CONFIG_PINCTRL_SM6375 is not set -# CONFIG_PINCTRL_SM7150 is not set -# CONFIG_PINCTRL_SM8150 is not set -# CONFIG_PINCTRL_SM8250 is not set -# CONFIG_PINCTRL_SM8450 is not set -# CONFIG_PINCTRL_SM8550 is not set -# CONFIG_PINCTRL_SM8650 is not set -# CONFIG_PINCTRL_X1E80100 is not set -CONFIG_PM=y -CONFIG_PM_CLK=y -CONFIG_PM_OPP=y -CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y -CONFIG_POWER_RESET=y -# CONFIG_POWER_RESET_MSM is not set -CONFIG_POWER_SUPPLY=y -CONFIG_PRINTK_TIME=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_PWM=y -CONFIG_PWM_IPQ=y -CONFIG_QCA807X_PHY=y -CONFIG_QCA808X_PHY=y -# CONFIG_QCM_DISPCC_2290 is not set -# CONFIG_QCM_GCC_2290 is not set -# CONFIG_QCOM_A53PLL is not set -# CONFIG_QCOM_AOSS_QMP is not set -CONFIG_QCOM_APCS_IPC=y -# CONFIG_QCOM_APR is not set -CONFIG_QCOM_BAM_DMA=y -# CONFIG_QCOM_CLK_APCC_MSM8996 is not set -# CONFIG_QCOM_CLK_APCS_MSM8916 is not set -# CONFIG_QCOM_COMMAND_DB is not set -# CONFIG_QCOM_CPR is not set -# CONFIG_QCOM_CPUCP_MBOX is not set -# CONFIG_QCOM_EBI2 is not set -# CONFIG_QCOM_FASTRPC is not set -# CONFIG_QCOM_GENI_SE is not set -# CONFIG_QCOM_GSBI is not set -# CONFIG_QCOM_HFPLL is not set -# CONFIG_QCOM_ICC_BWMON is not set -# CONFIG_QCOM_IPA is not set -# CONFIG_QCOM_IPCC is not set -# CONFIG_QCOM_LLCC is not set -CONFIG_QCOM_MDT_LOADER=y -# CONFIG_QCOM_MPM is not set -CONFIG_QCOM_NET_PHYLIB=y -# CONFIG_QCOM_OCMEM is not set -# CONFIG_QCOM_PDC is not set -CONFIG_QCOM_PIL_INFO=y -# CONFIG_QCOM_PPE is not set -# CONFIG_QCOM_Q6V5_ADSP is not set -CONFIG_QCOM_Q6V5_COMMON=y -# CONFIG_QCOM_Q6V5_MSS is not set -# CONFIG_QCOM_Q6V5_PAS is not set -CONFIG_QCOM_Q6V5_WCSS=y -# CONFIG_QCOM_QSEECOM is not set -# CONFIG_QCOM_RAMP_CTRL is not set -# CONFIG_QCOM_RMTFS_MEM is not set -# CONFIG_QCOM_RPMH is not set -# CONFIG_QCOM_RPM_MASTER_STATS is not set -CONFIG_QCOM_RPROC_COMMON=y -CONFIG_QCOM_SCM=y -# CONFIG_QCOM_SMD_RPM is not set -CONFIG_QCOM_SMEM=y -CONFIG_QCOM_SMEM_STATE=y -CONFIG_QCOM_SMP2P=y -# CONFIG_QCOM_SMSM is not set -CONFIG_QCOM_SOCINFO=y -# CONFIG_QCOM_SPM is not set -# CONFIG_QCOM_STATS is not set -# CONFIG_QCOM_SYSMON is not set -CONFIG_QCOM_TSENS=y -CONFIG_QCOM_TZMEM=y -CONFIG_QCOM_TZMEM_MODE_GENERIC=y -# CONFIG_QCOM_TZMEM_MODE_SHMBRIDGE is not set -# CONFIG_QCOM_WCNSS_CTRL is not set -# CONFIG_QCOM_WCNSS_PIL is not set -CONFIG_QCOM_WDT=y -# CONFIG_QCS_GCC_404 is not set -# CONFIG_QCS_Q6SSTOP_404 is not set -# CONFIG_QCS_TURING_404 is not set -# CONFIG_QDU_ECPRICC_1000 is not set -# CONFIG_QDU_GCC_1000 is not set -CONFIG_QUEUED_RWLOCKS=y -CONFIG_QUEUED_SPINLOCKS=y -CONFIG_RANDSTRUCT_NONE=y -CONFIG_RAS=y -CONFIG_RATIONAL=y -CONFIG_REGMAP=y -CONFIG_REGMAP_I2C=y -CONFIG_REGMAP_MMIO=y -CONFIG_REGULATOR=y -CONFIG_REGULATOR_FIXED_VOLTAGE=y -# CONFIG_REGULATOR_VQMMC_IPQ4019 is not set -CONFIG_RELOCATABLE=y -CONFIG_REMOTEPROC=y -CONFIG_REMOTEPROC_CDEV=y -CONFIG_RESET_CONTROLLER=y -# CONFIG_RESET_QCOM_AOSS is not set -# CONFIG_RESET_QCOM_PDC is not set -CONFIG_RFS_ACCEL=y -CONFIG_RODATA_FULL_DEFAULT_ENABLED=y -CONFIG_RPMSG=y -CONFIG_RPMSG_CHAR=y -# CONFIG_RPMSG_CTRL is not set -# CONFIG_RPMSG_NS is not set -CONFIG_RPMSG_QCOM_GLINK=y -CONFIG_RPMSG_QCOM_GLINK_RPM=y -CONFIG_RPMSG_QCOM_GLINK_SMEM=y -CONFIG_RPMSG_QCOM_SMD=y -# CONFIG_RPMSG_TTY is not set -CONFIG_RPS=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_I2C_AND_SPI=y -CONFIG_RWSEM_SPIN_ON_OWNER=y -# CONFIG_SA_GCC_8775P is not set -# CONFIG_SA_GPUCC_8775P is not set -# CONFIG_SCHED_CORE is not set -CONFIG_SCHED_HW_PRESSURE=y -CONFIG_SCHED_MC=y -CONFIG_SCHED_SMT=y -CONFIG_SCSI=y -CONFIG_SCSI_COMMON=y -# CONFIG_SCSI_LOWLEVEL is not set -# CONFIG_SCSI_PROC_FS is not set -# CONFIG_SC_CAMCC_7280 is not set -# CONFIG_SC_CAMCC_8280XP is not set -# CONFIG_SC_DISPCC_7180 is not set -# CONFIG_SC_DISPCC_8280XP is not set -# CONFIG_SC_GCC_7180 is not set -# CONFIG_SC_GCC_8280XP is not set -# CONFIG_SC_GPUCC_7180 is not set -# CONFIG_SC_LPASSCC_7280 is not set -# CONFIG_SC_LPASSCC_8280XP is not set -# CONFIG_SC_LPASS_CORECC_7180 is not set -# CONFIG_SC_LPASS_CORECC_7280 is not set -# CONFIG_SC_VIDEOCC_7180 is not set -# CONFIG_SDM_CAMCC_845 is not set -# CONFIG_SDM_DISPCC_845 is not set -# CONFIG_SDM_GCC_660 is not set -# CONFIG_SDM_GCC_845 is not set -# CONFIG_SDM_GPUCC_845 is not set -# CONFIG_SDM_LPASSCC_845 is not set -# CONFIG_SDM_VIDEOCC_845 is not set -# CONFIG_SDX_GCC_75 is not set -CONFIG_SERIAL_8250_FSL=y -CONFIG_SERIAL_MCTRL_GPIO=y -CONFIG_SERIAL_MSM=y -CONFIG_SERIAL_MSM_CONSOLE=y -CONFIG_SGL_ALLOC=y -CONFIG_SG_POOL=y -CONFIG_SMP=y -# CONFIG_SM_CAMCC_4450 is not set -# CONFIG_SM_CAMCC_6350 is not set -# CONFIG_SM_CAMCC_7150 is not set -# CONFIG_SM_CAMCC_8150 is not set -# CONFIG_SM_CAMCC_8450 is not set -# CONFIG_SM_CAMCC_8550 is not set -# CONFIG_SM_CAMCC_8650 is not set -# CONFIG_SM_GCC_4450 is not set -# CONFIG_SM_GCC_7150 is not set -# CONFIG_SM_GCC_8150 is not set -# CONFIG_SM_GCC_8250 is not set -# CONFIG_SM_GCC_8450 is not set -# CONFIG_SM_GCC_8550 is not set -# CONFIG_SM_GCC_8650 is not set -# CONFIG_SM_GPUCC_4450 is not set -# CONFIG_SM_GPUCC_6115 is not set -# CONFIG_SM_GPUCC_6125 is not set -# CONFIG_SM_GPUCC_6350 is not set -# CONFIG_SM_GPUCC_6375 is not set -# CONFIG_SM_GPUCC_8150 is not set -# CONFIG_SM_GPUCC_8250 is not set -# CONFIG_SM_GPUCC_8350 is not set -# CONFIG_SM_GPUCC_8450 is not set -# CONFIG_SM_GPUCC_8550 is not set -# CONFIG_SM_GPUCC_8650 is not set -# CONFIG_SM_TCSRCC_8550 is not set -# CONFIG_SM_TCSRCC_8650 is not set -# CONFIG_SM_VIDEOCC_7150 is not set -# CONFIG_SM_VIDEOCC_8150 is not set -# CONFIG_SM_VIDEOCC_8250 is not set -# CONFIG_SM_VIDEOCC_8350 is not set -# CONFIG_SM_VIDEOCC_8450 is not set -CONFIG_SOCK_RX_QUEUE_MAPPING=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_SPI=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -# CONFIG_SPI_QPIC_SNAND is not set -CONFIG_SPI_QUP=y -CONFIG_SPLIT_PMD_PTLOCKS=y -CONFIG_SPLIT_PTE_PTLOCKS=y -CONFIG_SWIOTLB=y -CONFIG_SWPHY=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -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_HWMON=y -CONFIG_THERMAL_OF=y -CONFIG_THREAD_INFO_IN_TASK=y -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TIMER_OF=y -CONFIG_TIMER_PROBE=y -CONFIG_TOOLS_SUPPORT_RELR=y -CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y -CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y -CONFIG_UBIFS_FS=y -CONFIG_UBIFS_FS_ADVANCED_COMPR=y -# CONFIG_UCLAMP_TASK is not set -CONFIG_UNMAP_KERNEL_AT_EL0=y -CONFIG_USB=y -CONFIG_USB_COMMON=y -CONFIG_USB_SUPPORT=y -CONFIG_USER_STACKTRACE_SUPPORT=y -CONFIG_VDSO_GETRANDOM=y -CONFIG_VIRTIO=y -CONFIG_VIRTIO_ANCHOR=y -# CONFIG_VIRTIO_BLK is not set -# CONFIG_VIRTIO_DEBUG is not set -# CONFIG_VIRTIO_NET is not set -CONFIG_VMAP_STACK=y -CONFIG_WANT_DEV_COREDUMP=y -CONFIG_WATCHDOG_CORE=y -CONFIG_WATCHDOG_SYSFS=y -CONFIG_XPS=y -CONFIG_XXHASH=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZONE_DMA32=y -CONFIG_ZSTD_COMMON=y -CONFIG_ZSTD_COMPRESS=y -CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/qualcommbe/patches-6.12/0002-v6.13-dt-bindings-PCI-qcom-Document-the-IPQ9574-PCIe.patch b/target/linux/qualcommbe/patches-6.12/0002-v6.13-dt-bindings-PCI-qcom-Document-the-IPQ9574-PCIe.patch deleted file mode 100644 index 2c883030e3..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0002-v6.13-dt-bindings-PCI-qcom-Document-the-IPQ9574-PCIe.patch +++ /dev/null @@ -1,101 +0,0 @@ -From e3ccffe9335ce3bdba93640588fab4560d18485e Mon Sep 17 00:00:00 2001 -From: devi priya -Date: Thu, 1 Aug 2024 11:18:00 +0530 -Subject: [PATCH 02/22] v6.13: dt-bindings: PCI: qcom: Document the IPQ9574 - PCIe controller -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Document the PCIe controller on IPQ9574 platform. - -Link: https://lore.kernel.org/r/20240801054803.3015572-2-quic_srichara@quicinc.com -Signed-off-by: devi priya -Signed-off-by: Sricharan Ramabadhran -Signed-off-by: Krzysztof Wilczyński -Reviewed-by: Krzysztof Kozlowski -Reviewed-by: Manivannan Sadhasivam ---- - .../devicetree/bindings/pci/qcom,pcie.yaml | 50 +++++++++++++++++++ - 1 file changed, 50 insertions(+) - ---- a/Documentation/devicetree/bindings/pci/qcom,pcie.yaml -+++ b/Documentation/devicetree/bindings/pci/qcom,pcie.yaml -@@ -26,6 +26,7 @@ properties: - - qcom,pcie-ipq8064-v2 - - qcom,pcie-ipq8074 - - qcom,pcie-ipq8074-gen3 -+ - qcom,pcie-ipq9574 - - qcom,pcie-msm8996 - - qcom,pcie-qcs404 - - qcom,pcie-sdm845 -@@ -164,6 +165,7 @@ allOf: - enum: - - qcom,pcie-ipq6018 - - qcom,pcie-ipq8074-gen3 -+ - qcom,pcie-ipq9574 - then: - properties: - reg: -@@ -405,6 +407,53 @@ allOf: - compatible: - contains: - enum: -+ - qcom,pcie-ipq9574 -+ then: -+ properties: -+ clocks: -+ minItems: 6 -+ maxItems: 6 -+ clock-names: -+ items: -+ - const: axi_m # AXI Master clock -+ - const: axi_s # AXI Slave clock -+ - const: axi_bridge -+ - const: rchng -+ - const: ahb -+ - const: aux -+ -+ resets: -+ minItems: 8 -+ maxItems: 8 -+ reset-names: -+ items: -+ - const: pipe # PIPE reset -+ - const: sticky # Core Sticky reset -+ - const: axi_s_sticky # AXI Slave Sticky reset -+ - const: axi_s # AXI Slave reset -+ - const: axi_m_sticky # AXI Master Sticky reset -+ - const: axi_m # AXI Master reset -+ - const: aux # AUX Reset -+ - const: ahb # AHB Reset -+ -+ interrupts: -+ minItems: 8 -+ interrupt-names: -+ items: -+ - const: msi0 -+ - const: msi1 -+ - const: msi2 -+ - const: msi3 -+ - const: msi4 -+ - const: msi5 -+ - const: msi6 -+ - const: msi7 -+ -+ - if: -+ properties: -+ compatible: -+ contains: -+ enum: - - qcom,pcie-qcs404 - then: - properties: -@@ -510,6 +559,7 @@ allOf: - - qcom,pcie-ipq8064v2 - - qcom,pcie-ipq8074 - - qcom,pcie-ipq8074-gen3 -+ - qcom,pcie-ipq9574 - - qcom,pcie-qcs404 - then: - required: diff --git a/target/linux/qualcommbe/patches-6.12/0004-v6.14-arm64-dts-qcom-ipq9574-Add-PCIe-PHYs-and-contr.patch b/target/linux/qualcommbe/patches-6.12/0004-v6.14-arm64-dts-qcom-ipq9574-Add-PCIe-PHYs-and-contr.patch deleted file mode 100644 index 9b0deb29db..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0004-v6.14-arm64-dts-qcom-ipq9574-Add-PCIe-PHYs-and-contr.patch +++ /dev/null @@ -1,468 +0,0 @@ -From acb06ebe2d1f043fd597f5c33aff048ae1804293 Mon Sep 17 00:00:00 2001 -From: devi priya -Date: Thu, 1 Aug 2024 11:18:01 +0530 -Subject: [PATCH 04/22] v6.14: arm64: dts: qcom: ipq9574: Add PCIe PHYs and - controller nodes - -Add PCIe0, PCIe1, PCIe2, PCIe3 (and corresponding PHY) devices -found on IPQ9574 platform. The PCIe0 & PCIe1 are 1-lane Gen3 -host whereas PCIe2 & PCIe3 are 2-lane Gen3 host. - -Signed-off-by: devi priya -Signed-off-by: Sricharan Ramabadhran -Link: https://lore.kernel.org/r/20240801054803.3015572-3-quic_srichara@quicinc.com -Signed-off-by: Bjorn Andersson ---- - arch/arm64/boot/dts/qcom/ipq9574.dtsi | 420 +++++++++++++++++++++++++- - 1 file changed, 416 insertions(+), 4 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi -@@ -226,6 +226,52 @@ - reg = <0x00060000 0x6000>; - }; - -+ pcie0_phy: phy@84000 { -+ compatible = "qcom,ipq9574-qmp-gen3x1-pcie-phy"; -+ reg = <0x00084000 0x1000>; -+ -+ clocks = <&gcc GCC_PCIE0_AUX_CLK>, -+ <&gcc GCC_PCIE0_AHB_CLK>, -+ <&gcc GCC_PCIE0_PIPE_CLK>; -+ clock-names = "aux", "cfg_ahb", "pipe"; -+ -+ assigned-clocks = <&gcc GCC_PCIE0_AUX_CLK>; -+ assigned-clock-rates = <20000000>; -+ -+ resets = <&gcc GCC_PCIE0_PHY_BCR>, -+ <&gcc GCC_PCIE0PHY_PHY_BCR>; -+ reset-names = "phy", "common"; -+ -+ #clock-cells = <0>; -+ clock-output-names = "gcc_pcie0_pipe_clk_src"; -+ -+ #phy-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ pcie2_phy: phy@8c000 { -+ compatible = "qcom,ipq9574-qmp-gen3x2-pcie-phy"; -+ reg = <0x0008c000 0x2000>; -+ -+ clocks = <&gcc GCC_PCIE2_AUX_CLK>, -+ <&gcc GCC_PCIE2_AHB_CLK>, -+ <&gcc GCC_PCIE2_PIPE_CLK>; -+ clock-names = "aux", "cfg_ahb", "pipe"; -+ -+ assigned-clocks = <&gcc GCC_PCIE2_AUX_CLK>; -+ assigned-clock-rates = <20000000>; -+ -+ resets = <&gcc GCC_PCIE2_PHY_BCR>, -+ <&gcc GCC_PCIE2PHY_PHY_BCR>; -+ reset-names = "phy", "common"; -+ -+ #clock-cells = <0>; -+ clock-output-names = "gcc_pcie2_pipe_clk_src"; -+ -+ #phy-cells = <0>; -+ status = "disabled"; -+ }; -+ - rng: rng@e3000 { - compatible = "qcom,prng-ee"; - reg = <0x000e3000 0x1000>; -@@ -243,6 +289,52 @@ - status = "disabled"; - }; - -+ pcie3_phy: phy@f4000 { -+ compatible = "qcom,ipq9574-qmp-gen3x2-pcie-phy"; -+ reg = <0x000f4000 0x2000>; -+ -+ clocks = <&gcc GCC_PCIE3_AUX_CLK>, -+ <&gcc GCC_PCIE3_AHB_CLK>, -+ <&gcc GCC_PCIE3_PIPE_CLK>; -+ clock-names = "aux", "cfg_ahb", "pipe"; -+ -+ assigned-clocks = <&gcc GCC_PCIE3_AUX_CLK>; -+ assigned-clock-rates = <20000000>; -+ -+ resets = <&gcc GCC_PCIE3_PHY_BCR>, -+ <&gcc GCC_PCIE3PHY_PHY_BCR>; -+ reset-names = "phy", "common"; -+ -+ #clock-cells = <0>; -+ clock-output-names = "gcc_pcie3_pipe_clk_src"; -+ -+ #phy-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ pcie1_phy: phy@fc000 { -+ compatible = "qcom,ipq9574-qmp-gen3x1-pcie-phy"; -+ reg = <0x000fc000 0x1000>; -+ -+ clocks = <&gcc GCC_PCIE1_AUX_CLK>, -+ <&gcc GCC_PCIE1_AHB_CLK>, -+ <&gcc GCC_PCIE1_PIPE_CLK>; -+ clock-names = "aux", "cfg_ahb", "pipe"; -+ -+ assigned-clocks = <&gcc GCC_PCIE1_AUX_CLK>; -+ assigned-clock-rates = <20000000>; -+ -+ resets = <&gcc GCC_PCIE1_PHY_BCR>, -+ <&gcc GCC_PCIE1PHY_PHY_BCR>; -+ reset-names = "phy", "common"; -+ -+ #clock-cells = <0>; -+ clock-output-names = "gcc_pcie1_pipe_clk_src"; -+ -+ #phy-cells = <0>; -+ status = "disabled"; -+ }; -+ - qfprom: efuse@a4000 { - compatible = "qcom,ipq9574-qfprom", "qcom,qfprom"; - reg = <0x000a4000 0x5a1>; -@@ -311,10 +403,10 @@ - clocks = <&xo_board_clk>, - <&sleep_clk>, - <0>, -- <0>, -- <0>, -- <0>, -- <0>, -+ <&pcie0_phy>, -+ <&pcie1_phy>, -+ <&pcie2_phy>, -+ <&pcie3_phy>, - <0>; - #clock-cells = <1>; - #reset-cells = <1>; -@@ -758,6 +850,326 @@ - status = "disabled"; - }; - }; -+ -+ pcie1: pcie@10000000 { -+ compatible = "qcom,pcie-ipq9574"; -+ reg = <0x10000000 0xf1d>, -+ <0x10000f20 0xa8>, -+ <0x10001000 0x1000>, -+ <0x000f8000 0x4000>, -+ <0x10100000 0x1000>; -+ reg-names = "dbi", "elbi", "atu", "parf", "config"; -+ device_type = "pci"; -+ linux,pci-domain = <1>; -+ bus-range = <0x00 0xff>; -+ num-lanes = <1>; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ -+ ranges = <0x01000000 0x0 0x00000000 0x10200000 0x0 0x100000>, -+ <0x02000000 0x0 0x10300000 0x10300000 0x0 0x7d00000>; -+ -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ , -+ ; -+ interrupt-names = "msi0", -+ "msi1", -+ "msi2", -+ "msi3", -+ "msi4", -+ "msi5", -+ "msi6", -+ "msi7"; -+ -+ #interrupt-cells = <1>; -+ interrupt-map-mask = <0 0 0 0x7>; -+ interrupt-map = <0 0 0 1 &intc 0 0 35 IRQ_TYPE_LEVEL_HIGH>, -+ <0 0 0 2 &intc 0 0 49 IRQ_TYPE_LEVEL_HIGH>, -+ <0 0 0 3 &intc 0 0 84 IRQ_TYPE_LEVEL_HIGH>, -+ <0 0 0 4 &intc 0 0 85 IRQ_TYPE_LEVEL_HIGH>; -+ -+ clocks = <&gcc GCC_PCIE1_AXI_M_CLK>, -+ <&gcc GCC_PCIE1_AXI_S_CLK>, -+ <&gcc GCC_PCIE1_AXI_S_BRIDGE_CLK>, -+ <&gcc GCC_PCIE1_RCHNG_CLK>, -+ <&gcc GCC_PCIE1_AHB_CLK>, -+ <&gcc GCC_PCIE1_AUX_CLK>; -+ clock-names = "axi_m", -+ "axi_s", -+ "axi_bridge", -+ "rchng", -+ "ahb", -+ "aux"; -+ -+ resets = <&gcc GCC_PCIE1_PIPE_ARES>, -+ <&gcc GCC_PCIE1_CORE_STICKY_ARES>, -+ <&gcc GCC_PCIE1_AXI_S_STICKY_ARES>, -+ <&gcc GCC_PCIE1_AXI_S_ARES>, -+ <&gcc GCC_PCIE1_AXI_M_STICKY_ARES>, -+ <&gcc GCC_PCIE1_AXI_M_ARES>, -+ <&gcc GCC_PCIE1_AUX_ARES>, -+ <&gcc GCC_PCIE1_AHB_ARES>; -+ reset-names = "pipe", -+ "sticky", -+ "axi_s_sticky", -+ "axi_s", -+ "axi_m_sticky", -+ "axi_m", -+ "aux", -+ "ahb"; -+ -+ phys = <&pcie1_phy>; -+ phy-names = "pciephy"; -+ interconnects = <&gcc MASTER_ANOC_PCIE1 &gcc SLAVE_ANOC_PCIE1>, -+ <&gcc MASTER_SNOC_PCIE1 &gcc SLAVE_SNOC_PCIE1>; -+ interconnect-names = "pcie-mem", "cpu-pcie"; -+ status = "disabled"; -+ }; -+ -+ pcie3: pcie@18000000 { -+ compatible = "qcom,pcie-ipq9574"; -+ reg = <0x18000000 0xf1d>, -+ <0x18000f20 0xa8>, -+ <0x18001000 0x1000>, -+ <0x000f0000 0x4000>, -+ <0x18100000 0x1000>; -+ reg-names = "dbi", "elbi", "atu", "parf", "config"; -+ device_type = "pci"; -+ linux,pci-domain = <3>; -+ bus-range = <0x00 0xff>; -+ num-lanes = <2>; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ -+ ranges = <0x01000000 0x0 0x00000000 0x18200000 0x0 0x100000>, -+ <0x02000000 0x0 0x18300000 0x18300000 0x0 0x7d00000>; -+ -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ , -+ ; -+ interrupt-names = "msi0", -+ "msi1", -+ "msi2", -+ "msi3", -+ "msi4", -+ "msi5", -+ "msi6", -+ "msi7"; -+ -+ #interrupt-cells = <1>; -+ interrupt-map-mask = <0 0 0 0x7>; -+ interrupt-map = <0 0 0 1 &intc 0 0 189 IRQ_TYPE_LEVEL_HIGH>, -+ <0 0 0 2 &intc 0 0 190 IRQ_TYPE_LEVEL_HIGH>, -+ <0 0 0 3 &intc 0 0 191 IRQ_TYPE_LEVEL_HIGH>, -+ <0 0 0 4 &intc 0 0 192 IRQ_TYPE_LEVEL_HIGH>; -+ -+ clocks = <&gcc GCC_PCIE3_AXI_M_CLK>, -+ <&gcc GCC_PCIE3_AXI_S_CLK>, -+ <&gcc GCC_PCIE3_AXI_S_BRIDGE_CLK>, -+ <&gcc GCC_PCIE3_RCHNG_CLK>, -+ <&gcc GCC_PCIE3_AHB_CLK>, -+ <&gcc GCC_PCIE3_AUX_CLK>; -+ clock-names = "axi_m", -+ "axi_s", -+ "axi_bridge", -+ "rchng", -+ "ahb", -+ "aux"; -+ -+ resets = <&gcc GCC_PCIE3_PIPE_ARES>, -+ <&gcc GCC_PCIE3_CORE_STICKY_ARES>, -+ <&gcc GCC_PCIE3_AXI_S_STICKY_ARES>, -+ <&gcc GCC_PCIE3_AXI_S_ARES>, -+ <&gcc GCC_PCIE3_AXI_M_STICKY_ARES>, -+ <&gcc GCC_PCIE3_AXI_M_ARES>, -+ <&gcc GCC_PCIE3_AUX_ARES>, -+ <&gcc GCC_PCIE3_AHB_ARES>; -+ reset-names = "pipe", -+ "sticky", -+ "axi_s_sticky", -+ "axi_s", -+ "axi_m_sticky", -+ "axi_m", -+ "aux", -+ "ahb"; -+ -+ phys = <&pcie3_phy>; -+ phy-names = "pciephy"; -+ interconnects = <&gcc MASTER_ANOC_PCIE3 &gcc SLAVE_ANOC_PCIE3>, -+ <&gcc MASTER_SNOC_PCIE3 &gcc SLAVE_SNOC_PCIE3>; -+ interconnect-names = "pcie-mem", "cpu-pcie"; -+ status = "disabled"; -+ }; -+ -+ pcie2: pcie@20000000 { -+ compatible = "qcom,pcie-ipq9574"; -+ reg = <0x20000000 0xf1d>, -+ <0x20000f20 0xa8>, -+ <0x20001000 0x1000>, -+ <0x00088000 0x4000>, -+ <0x20100000 0x1000>; -+ reg-names = "dbi", "elbi", "atu", "parf", "config"; -+ device_type = "pci"; -+ linux,pci-domain = <2>; -+ bus-range = <0x00 0xff>; -+ num-lanes = <2>; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ -+ ranges = <0x01000000 0x0 0x00000000 0x20200000 0x0 0x100000>, -+ <0x02000000 0x0 0x20300000 0x20300000 0x0 0x7d00000>; -+ -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ , -+ ; -+ interrupt-names = "msi0", -+ "msi1", -+ "msi2", -+ "msi3", -+ "msi4", -+ "msi5", -+ "msi6", -+ "msi7"; -+ -+ #interrupt-cells = <1>; -+ interrupt-map-mask = <0 0 0 0x7>; -+ interrupt-map = <0 0 0 1 &intc 0 0 164 IRQ_TYPE_LEVEL_HIGH>, -+ <0 0 0 2 &intc 0 0 165 IRQ_TYPE_LEVEL_HIGH>, -+ <0 0 0 3 &intc 0 0 186 IRQ_TYPE_LEVEL_HIGH>, -+ <0 0 0 4 &intc 0 0 187 IRQ_TYPE_LEVEL_HIGH>; -+ -+ clocks = <&gcc GCC_PCIE2_AXI_M_CLK>, -+ <&gcc GCC_PCIE2_AXI_S_CLK>, -+ <&gcc GCC_PCIE2_AXI_S_BRIDGE_CLK>, -+ <&gcc GCC_PCIE2_RCHNG_CLK>, -+ <&gcc GCC_PCIE2_AHB_CLK>, -+ <&gcc GCC_PCIE2_AUX_CLK>; -+ clock-names = "axi_m", -+ "axi_s", -+ "axi_bridge", -+ "rchng", -+ "ahb", -+ "aux"; -+ -+ resets = <&gcc GCC_PCIE2_PIPE_ARES>, -+ <&gcc GCC_PCIE2_CORE_STICKY_ARES>, -+ <&gcc GCC_PCIE2_AXI_S_STICKY_ARES>, -+ <&gcc GCC_PCIE2_AXI_S_ARES>, -+ <&gcc GCC_PCIE2_AXI_M_STICKY_ARES>, -+ <&gcc GCC_PCIE2_AXI_M_ARES>, -+ <&gcc GCC_PCIE2_AUX_ARES>, -+ <&gcc GCC_PCIE2_AHB_ARES>; -+ reset-names = "pipe", -+ "sticky", -+ "axi_s_sticky", -+ "axi_s", -+ "axi_m_sticky", -+ "axi_m", -+ "aux", -+ "ahb"; -+ -+ phys = <&pcie2_phy>; -+ phy-names = "pciephy"; -+ interconnects = <&gcc MASTER_ANOC_PCIE2 &gcc SLAVE_ANOC_PCIE2>, -+ <&gcc MASTER_SNOC_PCIE2 &gcc SLAVE_SNOC_PCIE2>; -+ interconnect-names = "pcie-mem", "cpu-pcie"; -+ status = "disabled"; -+ }; -+ -+ pcie0: pci@28000000 { -+ compatible = "qcom,pcie-ipq9574"; -+ reg = <0x28000000 0xf1d>, -+ <0x28000f20 0xa8>, -+ <0x28001000 0x1000>, -+ <0x00080000 0x4000>, -+ <0x28100000 0x1000>; -+ reg-names = "dbi", "elbi", "atu", "parf", "config"; -+ device_type = "pci"; -+ linux,pci-domain = <0>; -+ bus-range = <0x00 0xff>; -+ num-lanes = <1>; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ -+ ranges = <0x01000000 0x0 0x00000000 0x28200000 0x0 0x100000>, -+ <0x02000000 0x0 0x28300000 0x28300000 0x0 0x7d00000>; -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ , -+ ; -+ interrupt-names = "msi0", -+ "msi1", -+ "msi2", -+ "msi3", -+ "msi4", -+ "msi5", -+ "msi6", -+ "msi7"; -+ -+ #interrupt-cells = <1>; -+ interrupt-map-mask = <0 0 0 0x7>; -+ interrupt-map = <0 0 0 1 &intc 0 0 75 IRQ_TYPE_LEVEL_HIGH>, -+ <0 0 0 2 &intc 0 0 78 IRQ_TYPE_LEVEL_HIGH>, -+ <0 0 0 3 &intc 0 0 79 IRQ_TYPE_LEVEL_HIGH>, -+ <0 0 0 4 &intc 0 0 83 IRQ_TYPE_LEVEL_HIGH>; -+ -+ clocks = <&gcc GCC_PCIE0_AXI_M_CLK>, -+ <&gcc GCC_PCIE0_AXI_S_CLK>, -+ <&gcc GCC_PCIE0_AXI_S_BRIDGE_CLK>, -+ <&gcc GCC_PCIE0_RCHNG_CLK>, -+ <&gcc GCC_PCIE0_AHB_CLK>, -+ <&gcc GCC_PCIE0_AUX_CLK>; -+ clock-names = "axi_m", -+ "axi_s", -+ "axi_bridge", -+ "rchng", -+ "ahb", -+ "aux"; -+ -+ resets = <&gcc GCC_PCIE0_PIPE_ARES>, -+ <&gcc GCC_PCIE0_CORE_STICKY_ARES>, -+ <&gcc GCC_PCIE0_AXI_S_STICKY_ARES>, -+ <&gcc GCC_PCIE0_AXI_S_ARES>, -+ <&gcc GCC_PCIE0_AXI_M_STICKY_ARES>, -+ <&gcc GCC_PCIE0_AXI_M_ARES>, -+ <&gcc GCC_PCIE0_AUX_ARES>, -+ <&gcc GCC_PCIE0_AHB_ARES>; -+ reset-names = "pipe", -+ "sticky", -+ "axi_s_sticky", -+ "axi_s", -+ "axi_m_sticky", -+ "axi_m", -+ "aux", -+ "ahb"; -+ -+ phys = <&pcie0_phy>; -+ phy-names = "pciephy"; -+ interconnects = <&gcc MASTER_ANOC_PCIE0 &gcc SLAVE_ANOC_PCIE0>, -+ <&gcc MASTER_SNOC_PCIE0 &gcc SLAVE_SNOC_PCIE0>; -+ interconnect-names = "pcie-mem", "cpu-pcie"; -+ status = "disabled"; -+ }; -+ - }; - - thermal-zones { diff --git a/target/linux/qualcommbe/patches-6.12/0005-v6.14-arm64-dts-qcom-ipq9574-Enable-PCIe-PHYs-and-co.patch b/target/linux/qualcommbe/patches-6.12/0005-v6.14-arm64-dts-qcom-ipq9574-Enable-PCIe-PHYs-and-co.patch deleted file mode 100644 index f07e422966..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0005-v6.14-arm64-dts-qcom-ipq9574-Enable-PCIe-PHYs-and-co.patch +++ /dev/null @@ -1,152 +0,0 @@ -From 695cb0b8f9c525fe6d3ffbc349bc6087acd71201 Mon Sep 17 00:00:00 2001 -From: devi priya -Date: Thu, 1 Aug 2024 11:18:02 +0530 -Subject: [PATCH 05/22] v6.14: arm64: dts: qcom: ipq9574: Enable PCIe PHYs and - controllers - -Enable the PCIe controller and PHY nodes corresponding to RDP 433. - -Signed-off-by: devi priya -Signed-off-by: Sricharan Ramabadhran -Link: https://lore.kernel.org/r/20240801054803.3015572-4-quic_srichara@quicinc.com -Signed-off-by: Bjorn Andersson ---- - arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts | 113 ++++++++++++++++++++ - 1 file changed, 113 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts -+++ b/arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts -@@ -8,6 +8,7 @@ - - /dts-v1/; - -+#include - #include "ipq9574-rdp-common.dtsi" - - / { -@@ -15,6 +16,45 @@ - compatible = "qcom,ipq9574-ap-al02-c7", "qcom,ipq9574"; - }; - -+&pcie1_phy { -+ status = "okay"; -+}; -+ -+&pcie1 { -+ pinctrl-0 = <&pcie1_default>; -+ pinctrl-names = "default"; -+ -+ perst-gpios = <&tlmm 26 GPIO_ACTIVE_LOW>; -+ wake-gpios = <&tlmm 27 GPIO_ACTIVE_LOW>; -+ status = "okay"; -+}; -+ -+&pcie2_phy { -+ status = "okay"; -+}; -+ -+&pcie2 { -+ pinctrl-0 = <&pcie2_default>; -+ pinctrl-names = "default"; -+ -+ perst-gpios = <&tlmm 29 GPIO_ACTIVE_LOW>; -+ wake-gpios = <&tlmm 30 GPIO_ACTIVE_LOW>; -+ status = "okay"; -+}; -+ -+&pcie3_phy { -+ status = "okay"; -+}; -+ -+&pcie3 { -+ pinctrl-0 = <&pcie3_default>; -+ pinctrl-names = "default"; -+ -+ perst-gpios = <&tlmm 32 GPIO_ACTIVE_LOW>; -+ wake-gpios = <&tlmm 33 GPIO_ACTIVE_LOW>; -+ status = "okay"; -+}; -+ - &sdhc_1 { - pinctrl-0 = <&sdc_default_state>; - pinctrl-names = "default"; -@@ -28,6 +68,79 @@ - }; - - &tlmm { -+ -+ pcie1_default: pcie1-default-state { -+ clkreq-n-pins { -+ pins = "gpio25"; -+ function = "pcie1_clk"; -+ drive-strength = <6>; -+ bias-pull-up; -+ }; -+ -+ perst-n-pins { -+ pins = "gpio26"; -+ function = "gpio"; -+ drive-strength = <8>; -+ bias-pull-down; -+ output-low; -+ }; -+ -+ wake-n-pins { -+ pins = "gpio27"; -+ function = "pcie1_wake"; -+ drive-strength = <6>; -+ bias-pull-up; -+ }; -+ }; -+ -+ pcie2_default: pcie2-default-state { -+ clkreq-n-pins { -+ pins = "gpio28"; -+ function = "pcie2_clk"; -+ drive-strength = <6>; -+ bias-pull-up; -+ }; -+ -+ perst-n-pins { -+ pins = "gpio29"; -+ function = "gpio"; -+ drive-strength = <8>; -+ bias-pull-down; -+ output-low; -+ }; -+ -+ wake-n-pins { -+ pins = "gpio30"; -+ function = "pcie2_wake"; -+ drive-strength = <6>; -+ bias-pull-up; -+ }; -+ }; -+ -+ pcie3_default: pcie3-default-state { -+ clkreq-n-pins { -+ pins = "gpio31"; -+ function = "pcie3_clk"; -+ drive-strength = <6>; -+ bias-pull-up; -+ }; -+ -+ perst-n-pins { -+ pins = "gpio32"; -+ function = "gpio"; -+ drive-strength = <8>; -+ bias-pull-up; -+ output-low; -+ }; -+ -+ wake-n-pins { -+ pins = "gpio33"; -+ function = "pcie3_wake"; -+ drive-strength = <6>; -+ bias-pull-up; -+ }; -+ }; -+ - sdc_default_state: sdc-default-state { - clk-pins { - pins = "gpio5"; diff --git a/target/linux/qualcommbe/patches-6.12/0006-v6.14-dt-bindings-clock-qcom-Add-CMN-PLL-clock-contr.patch b/target/linux/qualcommbe/patches-6.12/0006-v6.14-dt-bindings-clock-qcom-Add-CMN-PLL-clock-contr.patch deleted file mode 100644 index f0087764a1..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0006-v6.14-dt-bindings-clock-qcom-Add-CMN-PLL-clock-contr.patch +++ /dev/null @@ -1,132 +0,0 @@ -From f4b785b3360c594bb10bd6f1dc5096b3e93f86d9 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Fri, 3 Jan 2025 15:31:34 +0800 -Subject: [PATCH 06/22] v6.14: dt-bindings: clock: qcom: Add CMN PLL clock - controller for IPQ SoC - -The CMN PLL controller provides clocks to networking hardware blocks -and to GCC on Qualcomm IPQ9574 SoC. It receives input clock from the -on-chip Wi-Fi, and produces output clocks at fixed rates. These output -rates are predetermined, and are unrelated to the input clock rate. -The primary purpose of CMN PLL is to supply clocks to the networking -hardware such as PPE (packet process engine), PCS and the externally -connected switch or PHY device. The CMN PLL block also outputs fixed -rate clocks to GCC, such as 24 MHZ as XO clock and 32 KHZ as sleep -clock supplied to GCC. - -Signed-off-by: Luo Jie -Reviewed-by: Krzysztof Kozlowski -Link: https://lore.kernel.org/r/20250103-qcom_ipq_cmnpll-v8-1-c89fb4d4849d@quicinc.com -Signed-off-by: Bjorn Andersson ---- - .../bindings/clock/qcom,ipq9574-cmn-pll.yaml | 77 +++++++++++++++++++ - include/dt-bindings/clock/qcom,ipq-cmn-pll.h | 22 ++++++ - 2 files changed, 99 insertions(+) - create mode 100644 Documentation/devicetree/bindings/clock/qcom,ipq9574-cmn-pll.yaml - create mode 100644 include/dt-bindings/clock/qcom,ipq-cmn-pll.h - ---- /dev/null -+++ b/Documentation/devicetree/bindings/clock/qcom,ipq9574-cmn-pll.yaml -@@ -0,0 +1,77 @@ -+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/clock/qcom,ipq9574-cmn-pll.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Qualcomm CMN PLL Clock Controller on IPQ SoC -+ -+maintainers: -+ - Bjorn Andersson -+ - Luo Jie -+ -+description: -+ The CMN (or common) PLL clock controller expects a reference -+ input clock. This reference clock is from the on-board Wi-Fi. -+ The CMN PLL supplies a number of fixed rate output clocks to -+ the devices providing networking functions and to GCC. These -+ networking hardware include PPE (packet process engine), PCS -+ and the externally connected switch or PHY devices. The CMN -+ PLL block also outputs fixed rate clocks to GCC. The PLL's -+ primary function is to enable fixed rate output clocks for -+ networking hardware functions used with the IPQ SoC. -+ -+properties: -+ compatible: -+ enum: -+ - qcom,ipq9574-cmn-pll -+ -+ reg: -+ maxItems: 1 -+ -+ clocks: -+ items: -+ - description: The reference clock. The supported clock rates include -+ 25000000, 31250000, 40000000, 48000000, 50000000 and 96000000 HZ. -+ - description: The AHB clock -+ - description: The SYS clock -+ description: -+ The reference clock is the source clock of CMN PLL, which is from the -+ Wi-Fi. The AHB and SYS clocks must be enabled to access CMN PLL -+ clock registers. -+ -+ clock-names: -+ items: -+ - const: ref -+ - const: ahb -+ - const: sys -+ -+ "#clock-cells": -+ const: 1 -+ -+required: -+ - compatible -+ - reg -+ - clocks -+ - clock-names -+ - "#clock-cells" -+ -+additionalProperties: false -+ -+examples: -+ - | -+ #include -+ #include -+ -+ cmn_pll: clock-controller@9b000 { -+ compatible = "qcom,ipq9574-cmn-pll"; -+ reg = <0x0009b000 0x800>; -+ clocks = <&cmn_pll_ref_clk>, -+ <&gcc GCC_CMN_12GPLL_AHB_CLK>, -+ <&gcc GCC_CMN_12GPLL_SYS_CLK>; -+ clock-names = "ref", "ahb", "sys"; -+ #clock-cells = <1>; -+ assigned-clocks = <&cmn_pll CMN_PLL_CLK>; -+ assigned-clock-rates-u64 = /bits/ 64 <12000000000>; -+ }; -+... ---- /dev/null -+++ b/include/dt-bindings/clock/qcom,ipq-cmn-pll.h -@@ -0,0 +1,22 @@ -+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ -+/* -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#ifndef _DT_BINDINGS_CLK_QCOM_IPQ_CMN_PLL_H -+#define _DT_BINDINGS_CLK_QCOM_IPQ_CMN_PLL_H -+ -+/* CMN PLL core clock. */ -+#define CMN_PLL_CLK 0 -+ -+/* The output clocks from CMN PLL of IPQ9574. */ -+#define XO_24MHZ_CLK 1 -+#define SLEEP_32KHZ_CLK 2 -+#define PCS_31P25MHZ_CLK 3 -+#define NSS_1200MHZ_CLK 4 -+#define PPE_353MHZ_CLK 5 -+#define ETH0_50MHZ_CLK 6 -+#define ETH1_50MHZ_CLK 7 -+#define ETH2_50MHZ_CLK 8 -+#define ETH_25MHZ_CLK 9 -+#endif diff --git a/target/linux/qualcommbe/patches-6.12/0007-v6.14-clk-qcom-Add-CMN-PLL-clock-controller-driver-f.patch b/target/linux/qualcommbe/patches-6.12/0007-v6.14-clk-qcom-Add-CMN-PLL-clock-controller-driver-f.patch deleted file mode 100644 index edbbf8e13d..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0007-v6.14-clk-qcom-Add-CMN-PLL-clock-controller-driver-f.patch +++ /dev/null @@ -1,501 +0,0 @@ -From 51c937f5d7a3b239b637555bbd4dc0017b5cccba Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Fri, 3 Jan 2025 15:31:35 +0800 -Subject: [PATCH 07/22] v6.14: clk: qcom: Add CMN PLL clock controller driver - for IPQ SoC - -The CMN PLL clock controller supplies clocks to the hardware -blocks that together make up the Ethernet function on Qualcomm -IPQ SoCs and to GCC. The driver is initially supported for -IPQ9574 SoC. - -The CMN PLL clock controller expects a reference input clock -from the on-board Wi-Fi block acting as clock source. The input -reference clock needs to be configured to one of the supported -clock rates. - -The controller supplies a number of fixed-rate output clocks. -For the IPQ9574, there is one output clock of 353 MHZ to PPE -(Packet Process Engine) hardware block, three 50 MHZ output -clocks and an additional 25 MHZ output clock supplied to the -connected Ethernet devices. The PLL also supplies a 24 MHZ -clock as XO and a 32 KHZ sleep clock to GCC, and one 31.25 -MHZ clock to PCS. - -Signed-off-by: Luo Jie -Acked-by: Konrad Dybcio -Link: https://lore.kernel.org/r/20250103-qcom_ipq_cmnpll-v8-2-c89fb4d4849d@quicinc.com -Signed-off-by: Bjorn Andersson ---- - drivers/clk/qcom/Kconfig | 9 + - drivers/clk/qcom/Makefile | 1 + - drivers/clk/qcom/ipq-cmn-pll.c | 435 +++++++++++++++++++++++++++++++++ - 3 files changed, 445 insertions(+) - create mode 100644 drivers/clk/qcom/ipq-cmn-pll.c - ---- a/drivers/clk/qcom/Kconfig -+++ b/drivers/clk/qcom/Kconfig -@@ -190,6 +190,15 @@ config IPQ_APSS_6018 - Say Y if you want to support CPU frequency scaling on - ipq based devices. - -+config IPQ_CMN_PLL -+ tristate "IPQ CMN PLL Clock Controller" -+ help -+ Support for CMN PLL clock controller on IPQ platform. The -+ CMN PLL consumes the AHB/SYS clocks from GCC and supplies -+ the output clocks to the networking hardware and GCC blocks. -+ Say Y or M if you want to support CMN PLL clock on the IPQ -+ based devices. -+ - config IPQ_GCC_4019 - tristate "IPQ4019 Global Clock Controller" - help ---- a/drivers/clk/qcom/Makefile -+++ b/drivers/clk/qcom/Makefile -@@ -29,6 +29,7 @@ obj-$(CONFIG_CLK_X1E80100_TCSRCC) += tcs - obj-$(CONFIG_CLK_QCM2290_GPUCC) += gpucc-qcm2290.o - obj-$(CONFIG_IPQ_APSS_PLL) += apss-ipq-pll.o - obj-$(CONFIG_IPQ_APSS_6018) += apss-ipq6018.o -+obj-$(CONFIG_IPQ_CMN_PLL) += ipq-cmn-pll.o - obj-$(CONFIG_IPQ_GCC_4019) += gcc-ipq4019.o - obj-$(CONFIG_IPQ_GCC_5018) += gcc-ipq5018.o - obj-$(CONFIG_IPQ_GCC_5332) += gcc-ipq5332.o ---- /dev/null -+++ b/drivers/clk/qcom/ipq-cmn-pll.c -@@ -0,0 +1,435 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+/* -+ * CMN PLL block expects the reference clock from on-board Wi-Fi block, -+ * and supplies fixed rate clocks as output to the networking hardware -+ * blocks and to GCC. The networking related blocks include PPE (packet -+ * process engine), the externally connected PHY or switch devices, and -+ * the PCS. -+ * -+ * On the IPQ9574 SoC, there are three clocks with 50 MHZ and one clock -+ * with 25 MHZ which are output from the CMN PLL to Ethernet PHY (or switch), -+ * and one clock with 353 MHZ to PPE. The other fixed rate output clocks -+ * are supplied to GCC (24 MHZ as XO and 32 KHZ as sleep clock), and to PCS -+ * with 31.25 MHZ. -+ * -+ * +---------+ -+ * | GCC | -+ * +--+---+--+ -+ * AHB CLK| |SYS CLK -+ * V V -+ * +-------+---+------+ -+ * | +-------------> eth0-50mhz -+ * REF CLK | IPQ9574 | -+ * -------->+ +-------------> eth1-50mhz -+ * | CMN PLL block | -+ * | +-------------> eth2-50mhz -+ * | | -+ * +----+----+----+---+-------------> eth-25mhz -+ * | | | -+ * V V V -+ * GCC PCS NSS/PPE -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#define CMN_PLL_REFCLK_SRC_SELECTION 0x28 -+#define CMN_PLL_REFCLK_SRC_DIV GENMASK(9, 8) -+ -+#define CMN_PLL_LOCKED 0x64 -+#define CMN_PLL_CLKS_LOCKED BIT(8) -+ -+#define CMN_PLL_POWER_ON_AND_RESET 0x780 -+#define CMN_ANA_EN_SW_RSTN BIT(6) -+ -+#define CMN_PLL_REFCLK_CONFIG 0x784 -+#define CMN_PLL_REFCLK_EXTERNAL BIT(9) -+#define CMN_PLL_REFCLK_DIV GENMASK(8, 4) -+#define CMN_PLL_REFCLK_INDEX GENMASK(3, 0) -+ -+#define CMN_PLL_CTRL 0x78c -+#define CMN_PLL_CTRL_LOCK_DETECT_EN BIT(15) -+ -+#define CMN_PLL_DIVIDER_CTRL 0x794 -+#define CMN_PLL_DIVIDER_CTRL_FACTOR GENMASK(9, 0) -+ -+/** -+ * struct cmn_pll_fixed_output_clk - CMN PLL output clocks information -+ * @id: Clock specifier to be supplied -+ * @name: Clock name to be registered -+ * @rate: Clock rate -+ */ -+struct cmn_pll_fixed_output_clk { -+ unsigned int id; -+ const char *name; -+ unsigned long rate; -+}; -+ -+/** -+ * struct clk_cmn_pll - CMN PLL hardware specific data -+ * @regmap: hardware regmap. -+ * @hw: handle between common and hardware-specific interfaces -+ */ -+struct clk_cmn_pll { -+ struct regmap *regmap; -+ struct clk_hw hw; -+}; -+ -+#define CLK_PLL_OUTPUT(_id, _name, _rate) { \ -+ .id = _id, \ -+ .name = _name, \ -+ .rate = _rate, \ -+} -+ -+#define to_clk_cmn_pll(_hw) container_of(_hw, struct clk_cmn_pll, hw) -+ -+static const struct regmap_config ipq_cmn_pll_regmap_config = { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .max_register = 0x7fc, -+ .fast_io = true, -+}; -+ -+static const struct cmn_pll_fixed_output_clk ipq9574_output_clks[] = { -+ CLK_PLL_OUTPUT(XO_24MHZ_CLK, "xo-24mhz", 24000000UL), -+ CLK_PLL_OUTPUT(SLEEP_32KHZ_CLK, "sleep-32khz", 32000UL), -+ CLK_PLL_OUTPUT(PCS_31P25MHZ_CLK, "pcs-31p25mhz", 31250000UL), -+ CLK_PLL_OUTPUT(NSS_1200MHZ_CLK, "nss-1200mhz", 1200000000UL), -+ CLK_PLL_OUTPUT(PPE_353MHZ_CLK, "ppe-353mhz", 353000000UL), -+ CLK_PLL_OUTPUT(ETH0_50MHZ_CLK, "eth0-50mhz", 50000000UL), -+ CLK_PLL_OUTPUT(ETH1_50MHZ_CLK, "eth1-50mhz", 50000000UL), -+ CLK_PLL_OUTPUT(ETH2_50MHZ_CLK, "eth2-50mhz", 50000000UL), -+ CLK_PLL_OUTPUT(ETH_25MHZ_CLK, "eth-25mhz", 25000000UL), -+}; -+ -+/* -+ * CMN PLL has the single parent clock, which supports the several -+ * possible parent clock rates, each parent clock rate is reflected -+ * by the specific reference index value in the hardware. -+ */ -+static int ipq_cmn_pll_find_freq_index(unsigned long parent_rate) -+{ -+ int index = -EINVAL; -+ -+ switch (parent_rate) { -+ case 25000000: -+ index = 3; -+ break; -+ case 31250000: -+ index = 4; -+ break; -+ case 40000000: -+ index = 6; -+ break; -+ case 48000000: -+ case 96000000: -+ /* -+ * Parent clock rate 48 MHZ and 96 MHZ take the same value -+ * of reference clock index. 96 MHZ needs the source clock -+ * divider to be programmed as 2. -+ */ -+ index = 7; -+ break; -+ case 50000000: -+ index = 8; -+ break; -+ default: -+ break; -+ } -+ -+ return index; -+} -+ -+static unsigned long clk_cmn_pll_recalc_rate(struct clk_hw *hw, -+ unsigned long parent_rate) -+{ -+ struct clk_cmn_pll *cmn_pll = to_clk_cmn_pll(hw); -+ u32 val, factor; -+ -+ /* -+ * The value of CMN_PLL_DIVIDER_CTRL_FACTOR is automatically adjusted -+ * by HW according to the parent clock rate. -+ */ -+ regmap_read(cmn_pll->regmap, CMN_PLL_DIVIDER_CTRL, &val); -+ factor = FIELD_GET(CMN_PLL_DIVIDER_CTRL_FACTOR, val); -+ -+ return parent_rate * 2 * factor; -+} -+ -+static int clk_cmn_pll_determine_rate(struct clk_hw *hw, -+ struct clk_rate_request *req) -+{ -+ int ret; -+ -+ /* Validate the rate of the single parent clock. */ -+ ret = ipq_cmn_pll_find_freq_index(req->best_parent_rate); -+ -+ return ret < 0 ? ret : 0; -+} -+ -+/* -+ * This function is used to initialize the CMN PLL to enable the fixed -+ * rate output clocks. It is expected to be configured once. -+ */ -+static int clk_cmn_pll_set_rate(struct clk_hw *hw, unsigned long rate, -+ unsigned long parent_rate) -+{ -+ struct clk_cmn_pll *cmn_pll = to_clk_cmn_pll(hw); -+ int ret, index; -+ u32 val; -+ -+ /* -+ * Configure the reference input clock selection as per the given -+ * parent clock. The output clock rates are always of fixed value. -+ */ -+ index = ipq_cmn_pll_find_freq_index(parent_rate); -+ if (index < 0) -+ return index; -+ -+ ret = regmap_update_bits(cmn_pll->regmap, CMN_PLL_REFCLK_CONFIG, -+ CMN_PLL_REFCLK_INDEX, -+ FIELD_PREP(CMN_PLL_REFCLK_INDEX, index)); -+ if (ret) -+ return ret; -+ -+ /* -+ * Update the source clock rate selection and source clock -+ * divider as 2 when the parent clock rate is 96 MHZ. -+ */ -+ if (parent_rate == 96000000) { -+ ret = regmap_update_bits(cmn_pll->regmap, CMN_PLL_REFCLK_CONFIG, -+ CMN_PLL_REFCLK_DIV, -+ FIELD_PREP(CMN_PLL_REFCLK_DIV, 2)); -+ if (ret) -+ return ret; -+ -+ ret = regmap_update_bits(cmn_pll->regmap, CMN_PLL_REFCLK_SRC_SELECTION, -+ CMN_PLL_REFCLK_SRC_DIV, -+ FIELD_PREP(CMN_PLL_REFCLK_SRC_DIV, 0)); -+ if (ret) -+ return ret; -+ } -+ -+ /* Enable PLL locked detect. */ -+ ret = regmap_set_bits(cmn_pll->regmap, CMN_PLL_CTRL, -+ CMN_PLL_CTRL_LOCK_DETECT_EN); -+ if (ret) -+ return ret; -+ -+ /* -+ * Reset the CMN PLL block to ensure the updated configurations -+ * take effect. -+ */ -+ ret = regmap_clear_bits(cmn_pll->regmap, CMN_PLL_POWER_ON_AND_RESET, -+ CMN_ANA_EN_SW_RSTN); -+ if (ret) -+ return ret; -+ -+ usleep_range(1000, 1200); -+ ret = regmap_set_bits(cmn_pll->regmap, CMN_PLL_POWER_ON_AND_RESET, -+ CMN_ANA_EN_SW_RSTN); -+ if (ret) -+ return ret; -+ -+ /* Stability check of CMN PLL output clocks. */ -+ return regmap_read_poll_timeout(cmn_pll->regmap, CMN_PLL_LOCKED, val, -+ (val & CMN_PLL_CLKS_LOCKED), -+ 100, 100 * USEC_PER_MSEC); -+} -+ -+static const struct clk_ops clk_cmn_pll_ops = { -+ .recalc_rate = clk_cmn_pll_recalc_rate, -+ .determine_rate = clk_cmn_pll_determine_rate, -+ .set_rate = clk_cmn_pll_set_rate, -+}; -+ -+static struct clk_hw *ipq_cmn_pll_clk_hw_register(struct platform_device *pdev) -+{ -+ struct clk_parent_data pdata = { .index = 0 }; -+ struct device *dev = &pdev->dev; -+ struct clk_init_data init = {}; -+ struct clk_cmn_pll *cmn_pll; -+ struct regmap *regmap; -+ void __iomem *base; -+ int ret; -+ -+ base = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(base)) -+ return ERR_CAST(base); -+ -+ regmap = devm_regmap_init_mmio(dev, base, &ipq_cmn_pll_regmap_config); -+ if (IS_ERR(regmap)) -+ return ERR_CAST(regmap); -+ -+ cmn_pll = devm_kzalloc(dev, sizeof(*cmn_pll), GFP_KERNEL); -+ if (!cmn_pll) -+ return ERR_PTR(-ENOMEM); -+ -+ init.name = "cmn_pll"; -+ init.parent_data = &pdata; -+ init.num_parents = 1; -+ init.ops = &clk_cmn_pll_ops; -+ -+ cmn_pll->hw.init = &init; -+ cmn_pll->regmap = regmap; -+ -+ ret = devm_clk_hw_register(dev, &cmn_pll->hw); -+ if (ret) -+ return ERR_PTR(ret); -+ -+ return &cmn_pll->hw; -+} -+ -+static int ipq_cmn_pll_register_clks(struct platform_device *pdev) -+{ -+ const struct cmn_pll_fixed_output_clk *fixed_clk; -+ struct clk_hw_onecell_data *hw_data; -+ struct device *dev = &pdev->dev; -+ struct clk_hw *cmn_pll_hw; -+ unsigned int num_clks; -+ struct clk_hw *hw; -+ int ret, i; -+ -+ fixed_clk = ipq9574_output_clks; -+ num_clks = ARRAY_SIZE(ipq9574_output_clks); -+ -+ hw_data = devm_kzalloc(dev, struct_size(hw_data, hws, num_clks + 1), -+ GFP_KERNEL); -+ if (!hw_data) -+ return -ENOMEM; -+ -+ /* -+ * Register the CMN PLL clock, which is the parent clock of -+ * the fixed rate output clocks. -+ */ -+ cmn_pll_hw = ipq_cmn_pll_clk_hw_register(pdev); -+ if (IS_ERR(cmn_pll_hw)) -+ return PTR_ERR(cmn_pll_hw); -+ -+ /* Register the fixed rate output clocks. */ -+ for (i = 0; i < num_clks; i++) { -+ hw = clk_hw_register_fixed_rate_parent_hw(dev, fixed_clk[i].name, -+ cmn_pll_hw, 0, -+ fixed_clk[i].rate); -+ if (IS_ERR(hw)) { -+ ret = PTR_ERR(hw); -+ goto unregister_fixed_clk; -+ } -+ -+ hw_data->hws[fixed_clk[i].id] = hw; -+ } -+ -+ /* -+ * Provide the CMN PLL clock. The clock rate of CMN PLL -+ * is configured to 12 GHZ by DT property assigned-clock-rates-u64. -+ */ -+ hw_data->hws[CMN_PLL_CLK] = cmn_pll_hw; -+ hw_data->num = num_clks + 1; -+ -+ ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, hw_data); -+ if (ret) -+ goto unregister_fixed_clk; -+ -+ platform_set_drvdata(pdev, hw_data); -+ -+ return 0; -+ -+unregister_fixed_clk: -+ while (i > 0) -+ clk_hw_unregister(hw_data->hws[fixed_clk[--i].id]); -+ -+ return ret; -+} -+ -+static int ipq_cmn_pll_clk_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ int ret; -+ -+ ret = devm_pm_runtime_enable(dev); -+ if (ret) -+ return ret; -+ -+ ret = devm_pm_clk_create(dev); -+ if (ret) -+ return ret; -+ -+ /* -+ * To access the CMN PLL registers, the GCC AHB & SYS clocks -+ * of CMN PLL block need to be enabled. -+ */ -+ ret = pm_clk_add(dev, "ahb"); -+ if (ret) -+ return dev_err_probe(dev, ret, "Fail to add AHB clock\n"); -+ -+ ret = pm_clk_add(dev, "sys"); -+ if (ret) -+ return dev_err_probe(dev, ret, "Fail to add SYS clock\n"); -+ -+ ret = pm_runtime_resume_and_get(dev); -+ if (ret) -+ return ret; -+ -+ /* Register CMN PLL clock and fixed rate output clocks. */ -+ ret = ipq_cmn_pll_register_clks(pdev); -+ pm_runtime_put(dev); -+ if (ret) -+ return dev_err_probe(dev, ret, -+ "Fail to register CMN PLL clocks\n"); -+ -+ return 0; -+} -+ -+static void ipq_cmn_pll_clk_remove(struct platform_device *pdev) -+{ -+ struct clk_hw_onecell_data *hw_data = platform_get_drvdata(pdev); -+ int i; -+ -+ /* -+ * The clock with index CMN_PLL_CLK is unregistered by -+ * device management. -+ */ -+ for (i = 0; i < hw_data->num; i++) { -+ if (i != CMN_PLL_CLK) -+ clk_hw_unregister(hw_data->hws[i]); -+ } -+} -+ -+static const struct dev_pm_ops ipq_cmn_pll_pm_ops = { -+ SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL) -+}; -+ -+static const struct of_device_id ipq_cmn_pll_clk_ids[] = { -+ { .compatible = "qcom,ipq9574-cmn-pll", }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, ipq_cmn_pll_clk_ids); -+ -+static struct platform_driver ipq_cmn_pll_clk_driver = { -+ .probe = ipq_cmn_pll_clk_probe, -+ .remove = ipq_cmn_pll_clk_remove, -+ .driver = { -+ .name = "ipq_cmn_pll", -+ .of_match_table = ipq_cmn_pll_clk_ids, -+ .pm = &ipq_cmn_pll_pm_ops, -+ }, -+}; -+module_platform_driver(ipq_cmn_pll_clk_driver); -+ -+MODULE_DESCRIPTION("Qualcomm Technologies, Inc. IPQ CMN PLL Driver"); -+MODULE_LICENSE("GPL"); diff --git a/target/linux/qualcommbe/patches-6.12/0008-v6.14-arm64-dts-qcom-ipq9574-Add-CMN-PLL-node.patch b/target/linux/qualcommbe/patches-6.12/0008-v6.14-arm64-dts-qcom-ipq9574-Add-CMN-PLL-node.patch deleted file mode 100644 index b29bbda235..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0008-v6.14-arm64-dts-qcom-ipq9574-Add-CMN-PLL-node.patch +++ /dev/null @@ -1,122 +0,0 @@ -From 20a3597d994c8ac372bbb66d9f11bccb7f405154 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Fri, 3 Jan 2025 15:31:37 +0800 -Subject: [PATCH 08/22] v6.14: arm64: dts: qcom: ipq9574: Add CMN PLL node - -The CMN PLL clock controller allows selection of an input clock rate -from a defined set of input clock rates. It in-turn supplies fixed -rate output clocks to the hardware blocks that provide the ethernet -functions such as PPE (Packet Process Engine) and connected switch or -PHY, and to GCC. - -The reference clock of CMN PLL is routed from XO to the CMN PLL through -the internal WiFi block. -.XO (48 MHZ or 96 MHZ)-->WiFi (multiplier/divider)-->48 MHZ to CMN PLL. - -The reference input clock from WiFi to CMN PLL is fully controlled by -the bootstrap pins which select the XO frequency (48 MHZ or 96 MHZ). -Based on this frequency, the divider in the internal Wi-Fi block is -automatically configured by hardware (1 for 48 MHZ, 2 for 96 MHZ), to -ensure output clock to CMN PLL is 48 MHZ. - -Signed-off-by: Luo Jie -Reviewed-by: Konrad Dybcio -Link: https://lore.kernel.org/r/20250103-qcom_ipq_cmnpll-v8-4-c89fb4d4849d@quicinc.com -Signed-off-by: Bjorn Andersson ---- - .../boot/dts/qcom/ipq9574-rdp-common.dtsi | 17 +++++++++++- - arch/arm64/boot/dts/qcom/ipq9574.dtsi | 26 ++++++++++++++++++- - 2 files changed, 41 insertions(+), 2 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq9574-rdp-common.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574-rdp-common.dtsi -@@ -3,7 +3,7 @@ - * IPQ9574 RDP board common device tree source - * - * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. -- * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. -+ * Copyright (c) 2023-2024, Qualcomm Innovation Center, Inc. All rights reserved. - */ - - /dts-v1/; -@@ -171,6 +171,21 @@ - status = "okay"; - }; - -+/* -+ * The bootstrap pins for the board select the XO clock frequency -+ * (48 MHZ or 96 MHZ used for different RDP type board). This setting -+ * automatically enables the right dividers, to ensure the reference -+ * clock output from WiFi to the CMN PLL is 48 MHZ. -+ */ -+&ref_48mhz_clk { -+ clock-div = <1>; -+ clock-mult = <1>; -+}; -+ - &xo_board_clk { - clock-frequency = <24000000>; - }; -+ -+&xo_clk { -+ clock-frequency = <48000000>; -+}; ---- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi -@@ -3,10 +3,11 @@ - * IPQ9574 SoC device tree source - * - * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. -- * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. -+ * Copyright (c) 2023-2024, Qualcomm Innovation Center, Inc. All rights reserved. - */ - - #include -+#include - #include - #include - #include -@@ -19,6 +20,12 @@ - #size-cells = <2>; - - clocks { -+ ref_48mhz_clk: ref-48mhz-clk { -+ compatible = "fixed-factor-clock"; -+ clocks = <&xo_clk>; -+ #clock-cells = <0>; -+ }; -+ - sleep_clk: sleep-clk { - compatible = "fixed-clock"; - #clock-cells = <0>; -@@ -28,6 +35,11 @@ - compatible = "fixed-clock"; - #clock-cells = <0>; - }; -+ -+ xo_clk: xo-clk { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ }; - }; - - cpus { -@@ -335,6 +347,18 @@ - status = "disabled"; - }; - -+ cmn_pll: clock-controller@9b000 { -+ compatible = "qcom,ipq9574-cmn-pll"; -+ reg = <0x0009b000 0x800>; -+ clocks = <&ref_48mhz_clk>, -+ <&gcc GCC_CMN_12GPLL_AHB_CLK>, -+ <&gcc GCC_CMN_12GPLL_SYS_CLK>; -+ clock-names = "ref", "ahb", "sys"; -+ #clock-cells = <1>; -+ assigned-clocks = <&cmn_pll CMN_PLL_CLK>; -+ assigned-clock-rates-u64 = /bits/ 64 <12000000000>; -+ }; -+ - qfprom: efuse@a4000 { - compatible = "qcom,ipq9574-qfprom", "qcom,qfprom"; - reg = <0x000a4000 0x5a1>; diff --git a/target/linux/qualcommbe/patches-6.12/0009-v6.14-arm64-dts-qcom-ipq9574-Update-xo_board_clk-to-.patch b/target/linux/qualcommbe/patches-6.12/0009-v6.14-arm64-dts-qcom-ipq9574-Update-xo_board_clk-to-.patch deleted file mode 100644 index 0268c5c28e..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0009-v6.14-arm64-dts-qcom-ipq9574-Update-xo_board_clk-to-.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 62307c5e153de617cb0827509fb964df051caaac Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Fri, 3 Jan 2025 15:31:38 +0800 -Subject: [PATCH 09/22] v6.14: arm64: dts: qcom: ipq9574: Update xo_board_clk - to use fixed factor clock - -xo_board_clk is fixed to 24 MHZ, which is routed from WiFi output clock -48 MHZ (also being the reference clock of CMN PLL) divided 2 by analog -block routing channel. - -Reviewed-by: Konrad Dybcio -Signed-off-by: Luo Jie -Link: https://lore.kernel.org/r/20250103-qcom_ipq_cmnpll-v8-5-c89fb4d4849d@quicinc.com -Signed-off-by: Bjorn Andersson ---- - arch/arm64/boot/dts/qcom/ipq9574-rdp-common.dtsi | 7 ++++++- - arch/arm64/boot/dts/qcom/ipq9574.dtsi | 3 ++- - 2 files changed, 8 insertions(+), 2 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq9574-rdp-common.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574-rdp-common.dtsi -@@ -182,8 +182,13 @@ - clock-mult = <1>; - }; - -+/* -+ * The frequency of xo_board_clk is fixed to 24 MHZ, which is routed -+ * from WiFi output clock 48 MHZ divided by 2. -+ */ - &xo_board_clk { -- clock-frequency = <24000000>; -+ clock-div = <2>; -+ clock-mult = <1>; - }; - - &xo_clk { ---- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi -@@ -32,7 +32,8 @@ - }; - - xo_board_clk: xo-board-clk { -- compatible = "fixed-clock"; -+ compatible = "fixed-factor-clock"; -+ clocks = <&ref_48mhz_clk>; - #clock-cells = <0>; - }; - diff --git a/target/linux/qualcommbe/patches-6.12/0016-v6.15-spi-dt-bindings-Introduce-qcom-spi-qpic-snand.patch b/target/linux/qualcommbe/patches-6.12/0016-v6.15-spi-dt-bindings-Introduce-qcom-spi-qpic-snand.patch deleted file mode 100644 index 6a1627a67e..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0016-v6.15-spi-dt-bindings-Introduce-qcom-spi-qpic-snand.patch +++ /dev/null @@ -1,105 +0,0 @@ -From 66fde1c5d29006127cc4fc5a12a0c42415c098bd Mon Sep 17 00:00:00 2001 -From: Md Sadre Alam -Date: Mon, 24 Feb 2025 16:44:13 +0530 -Subject: [PATCH 16/22] v6.15: spi: dt-bindings: Introduce qcom,spi-qpic-snand - -Document the QPIC-SPI-NAND flash controller present in the IPQ SoCs. -It can work both in serial and parallel mode and supports typical -SPI-NAND page cache operations. - -Reviewed-by: Krzysztof Kozlowski -Reviewed-by: Rob Herring (Arm) -Signed-off-by: Md Sadre Alam -Link: https://patch.msgid.link/20250224111414.2809669-2-quic_mdalam@quicinc.com -Signed-off-by: Mark Brown ---- - .../bindings/spi/qcom,spi-qpic-snand.yaml | 83 +++++++++++++++++++ - 1 file changed, 83 insertions(+) - create mode 100644 Documentation/devicetree/bindings/spi/qcom,spi-qpic-snand.yaml - ---- /dev/null -+++ b/Documentation/devicetree/bindings/spi/qcom,spi-qpic-snand.yaml -@@ -0,0 +1,83 @@ -+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/spi/qcom,spi-qpic-snand.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Qualcomm QPIC NAND controller -+ -+maintainers: -+ - Md sadre Alam -+ -+description: -+ The QCOM QPIC-SPI-NAND flash controller is an extended version of -+ the QCOM QPIC NAND flash controller. It can work both in serial -+ and parallel mode. It supports typical SPI-NAND page cache -+ operations in single, dual or quad IO mode with pipelined ECC -+ encoding/decoding using the QPIC ECC HW engine. -+ -+allOf: -+ - $ref: /schemas/spi/spi-controller.yaml# -+ -+properties: -+ compatible: -+ enum: -+ - qcom,ipq9574-snand -+ -+ reg: -+ maxItems: 1 -+ -+ clocks: -+ maxItems: 3 -+ -+ clock-names: -+ items: -+ - const: core -+ - const: aon -+ - const: iom -+ -+ dmas: -+ items: -+ - description: tx DMA channel -+ - description: rx DMA channel -+ - description: cmd DMA channel -+ -+ dma-names: -+ items: -+ - const: tx -+ - const: rx -+ - const: cmd -+ -+required: -+ - compatible -+ - reg -+ - clocks -+ - clock-names -+ -+unevaluatedProperties: false -+ -+examples: -+ - | -+ #include -+ spi@79b0000 { -+ compatible = "qcom,ipq9574-snand"; -+ reg = <0x1ac00000 0x800>; -+ -+ clocks = <&gcc GCC_QPIC_CLK>, -+ <&gcc GCC_QPIC_AHB_CLK>, -+ <&gcc GCC_QPIC_IO_MACRO_CLK>; -+ clock-names = "core", "aon", "iom"; -+ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ flash@0 { -+ compatible = "spi-nand"; -+ reg = <0>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ nand-ecc-engine = <&qpic_nand>; -+ nand-ecc-strength = <4>; -+ nand-ecc-step-size = <512>; -+ }; -+ }; diff --git a/target/linux/qualcommbe/patches-6.12/0018-v6.15-dt-bindings-clock-gcc-ipq9574-Add-definition-f.patch b/target/linux/qualcommbe/patches-6.12/0018-v6.15-dt-bindings-clock-gcc-ipq9574-Add-definition-f.patch deleted file mode 100644 index dfe655df94..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0018-v6.15-dt-bindings-clock-gcc-ipq9574-Add-definition-f.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 25ce13ad8852f14835e650132ccf4fc0bf127699 Mon Sep 17 00:00:00 2001 -From: Devi Priya -Date: Thu, 13 Mar 2025 16:33:54 +0530 -Subject: [PATCH 18/22] v6.15: dt-bindings: clock: gcc-ipq9574: Add definition - for GPLL0_OUT_AUX - -Add the definition for GPLL0_OUT_AUX clock. - -Acked-by: Krzysztof Kozlowski -Signed-off-by: Devi Priya -Signed-off-by: Manikanta Mylavarapu -Link: https://lore.kernel.org/r/20250313110359.242491-2-quic_mmanikan@quicinc.com -Signed-off-by: Bjorn Andersson ---- - include/dt-bindings/clock/qcom,ipq9574-gcc.h | 1 + - 1 file changed, 1 insertion(+) - ---- a/include/dt-bindings/clock/qcom,ipq9574-gcc.h -+++ b/include/dt-bindings/clock/qcom,ipq9574-gcc.h -@@ -220,4 +220,5 @@ - #define GCC_PCIE1_PIPE_CLK 211 - #define GCC_PCIE2_PIPE_CLK 212 - #define GCC_PCIE3_PIPE_CLK 213 -+#define GPLL0_OUT_AUX 214 - #endif diff --git a/target/linux/qualcommbe/patches-6.12/0019-v6.15-dt-bindings-clock-Add-ipq9574-NSSCC-clock-and-.patch b/target/linux/qualcommbe/patches-6.12/0019-v6.15-dt-bindings-clock-Add-ipq9574-NSSCC-clock-and-.patch deleted file mode 100644 index 0552b07b1e..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0019-v6.15-dt-bindings-clock-Add-ipq9574-NSSCC-clock-and-.patch +++ /dev/null @@ -1,415 +0,0 @@ -From 5ed04d121a8d24cc3151aa57a21a6c944ad6d7f3 Mon Sep 17 00:00:00 2001 -From: Devi Priya -Date: Thu, 13 Mar 2025 16:33:56 +0530 -Subject: [PATCH 19/22] v6.15: dt-bindings: clock: Add ipq9574 NSSCC clock and - reset definitions - -Add NSSCC clock and reset definitions for ipq9574. - -Reviewed-by: Krzysztof Kozlowski -Signed-off-by: Devi Priya -Signed-off-by: Manikanta Mylavarapu -Link: https://lore.kernel.org/r/20250313110359.242491-4-quic_mmanikan@quicinc.com -Signed-off-by: Bjorn Andersson ---- - .../bindings/clock/qcom,ipq9574-nsscc.yaml | 98 +++++++++++ - .../dt-bindings/clock/qcom,ipq9574-nsscc.h | 152 ++++++++++++++++++ - .../dt-bindings/reset/qcom,ipq9574-nsscc.h | 134 +++++++++++++++ - 3 files changed, 384 insertions(+) - create mode 100644 Documentation/devicetree/bindings/clock/qcom,ipq9574-nsscc.yaml - create mode 100644 include/dt-bindings/clock/qcom,ipq9574-nsscc.h - create mode 100644 include/dt-bindings/reset/qcom,ipq9574-nsscc.h - ---- /dev/null -+++ b/Documentation/devicetree/bindings/clock/qcom,ipq9574-nsscc.yaml -@@ -0,0 +1,98 @@ -+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/clock/qcom,ipq9574-nsscc.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Qualcomm Networking Sub System Clock & Reset Controller on IPQ9574 -+ -+maintainers: -+ - Bjorn Andersson -+ - Anusha Rao -+ -+description: | -+ Qualcomm networking sub system clock control module provides the clocks, -+ resets on IPQ9574 -+ -+ See also:: -+ include/dt-bindings/clock/qcom,ipq9574-nsscc.h -+ include/dt-bindings/reset/qcom,ipq9574-nsscc.h -+ -+properties: -+ compatible: -+ const: qcom,ipq9574-nsscc -+ -+ clocks: -+ items: -+ - description: Board XO source -+ - description: CMN_PLL NSS 1200MHz (Bias PLL cc) clock source -+ - description: CMN_PLL PPE 353MHz (Bias PLL ubi nc) clock source -+ - description: GCC GPLL0 OUT AUX clock source -+ - description: Uniphy0 NSS Rx clock source -+ - description: Uniphy0 NSS Tx clock source -+ - description: Uniphy1 NSS Rx clock source -+ - description: Uniphy1 NSS Tx clock source -+ - description: Uniphy2 NSS Rx clock source -+ - description: Uniphy2 NSS Tx clock source -+ - description: GCC NSSCC clock source -+ -+ '#interconnect-cells': -+ const: 1 -+ -+ clock-names: -+ items: -+ - const: xo -+ - const: nss_1200 -+ - const: ppe_353 -+ - const: gpll0_out -+ - const: uniphy0_rx -+ - const: uniphy0_tx -+ - const: uniphy1_rx -+ - const: uniphy1_tx -+ - const: uniphy2_rx -+ - const: uniphy2_tx -+ - const: bus -+ -+required: -+ - compatible -+ - clocks -+ - clock-names -+ -+allOf: -+ - $ref: qcom,gcc.yaml# -+ -+unevaluatedProperties: false -+ -+examples: -+ - | -+ #include -+ #include -+ clock-controller@39b00000 { -+ compatible = "qcom,ipq9574-nsscc"; -+ reg = <0x39b00000 0x80000>; -+ clocks = <&xo_board_clk>, -+ <&cmn_pll NSS_1200MHZ_CLK>, -+ <&cmn_pll PPE_353MHZ_CLK>, -+ <&gcc GPLL0_OUT_AUX>, -+ <&uniphy 0>, -+ <&uniphy 1>, -+ <&uniphy 2>, -+ <&uniphy 3>, -+ <&uniphy 4>, -+ <&uniphy 5>, -+ <&gcc GCC_NSSCC_CLK>; -+ clock-names = "xo", -+ "nss_1200", -+ "ppe_353", -+ "gpll0_out", -+ "uniphy0_rx", -+ "uniphy0_tx", -+ "uniphy1_rx", -+ "uniphy1_tx", -+ "uniphy2_rx", -+ "uniphy2_tx", -+ "bus"; -+ #clock-cells = <1>; -+ #reset-cells = <1>; -+ }; -+... ---- /dev/null -+++ b/include/dt-bindings/clock/qcom,ipq9574-nsscc.h -@@ -0,0 +1,152 @@ -+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ -+/* -+ * Copyright (c) 2023, 2025 The Linux Foundation. All rights reserved. -+ */ -+ -+#ifndef _DT_BINDINGS_CLOCK_IPQ_NSSCC_9574_H -+#define _DT_BINDINGS_CLOCK_IPQ_NSSCC_9574_H -+ -+#define NSS_CC_CE_APB_CLK 0 -+#define NSS_CC_CE_AXI_CLK 1 -+#define NSS_CC_CE_CLK_SRC 2 -+#define NSS_CC_CFG_CLK_SRC 3 -+#define NSS_CC_CLC_AXI_CLK 4 -+#define NSS_CC_CLC_CLK_SRC 5 -+#define NSS_CC_CRYPTO_CLK 6 -+#define NSS_CC_CRYPTO_CLK_SRC 7 -+#define NSS_CC_CRYPTO_PPE_CLK 8 -+#define NSS_CC_HAQ_AHB_CLK 9 -+#define NSS_CC_HAQ_AXI_CLK 10 -+#define NSS_CC_HAQ_CLK_SRC 11 -+#define NSS_CC_IMEM_AHB_CLK 12 -+#define NSS_CC_IMEM_CLK_SRC 13 -+#define NSS_CC_IMEM_QSB_CLK 14 -+#define NSS_CC_INT_CFG_CLK_SRC 15 -+#define NSS_CC_NSS_CSR_CLK 16 -+#define NSS_CC_NSSNOC_CE_APB_CLK 17 -+#define NSS_CC_NSSNOC_CE_AXI_CLK 18 -+#define NSS_CC_NSSNOC_CLC_AXI_CLK 19 -+#define NSS_CC_NSSNOC_CRYPTO_CLK 20 -+#define NSS_CC_NSSNOC_HAQ_AHB_CLK 21 -+#define NSS_CC_NSSNOC_HAQ_AXI_CLK 22 -+#define NSS_CC_NSSNOC_IMEM_AHB_CLK 23 -+#define NSS_CC_NSSNOC_IMEM_QSB_CLK 24 -+#define NSS_CC_NSSNOC_NSS_CSR_CLK 25 -+#define NSS_CC_NSSNOC_PPE_CFG_CLK 26 -+#define NSS_CC_NSSNOC_PPE_CLK 27 -+#define NSS_CC_NSSNOC_UBI32_AHB0_CLK 28 -+#define NSS_CC_NSSNOC_UBI32_AXI0_CLK 29 -+#define NSS_CC_NSSNOC_UBI32_INT0_AHB_CLK 30 -+#define NSS_CC_NSSNOC_UBI32_NC_AXI0_1_CLK 31 -+#define NSS_CC_NSSNOC_UBI32_NC_AXI0_CLK 32 -+#define NSS_CC_PORT1_MAC_CLK 33 -+#define NSS_CC_PORT1_RX_CLK 34 -+#define NSS_CC_PORT1_RX_CLK_SRC 35 -+#define NSS_CC_PORT1_RX_DIV_CLK_SRC 36 -+#define NSS_CC_PORT1_TX_CLK 37 -+#define NSS_CC_PORT1_TX_CLK_SRC 38 -+#define NSS_CC_PORT1_TX_DIV_CLK_SRC 39 -+#define NSS_CC_PORT2_MAC_CLK 40 -+#define NSS_CC_PORT2_RX_CLK 41 -+#define NSS_CC_PORT2_RX_CLK_SRC 42 -+#define NSS_CC_PORT2_RX_DIV_CLK_SRC 43 -+#define NSS_CC_PORT2_TX_CLK 44 -+#define NSS_CC_PORT2_TX_CLK_SRC 45 -+#define NSS_CC_PORT2_TX_DIV_CLK_SRC 46 -+#define NSS_CC_PORT3_MAC_CLK 47 -+#define NSS_CC_PORT3_RX_CLK 48 -+#define NSS_CC_PORT3_RX_CLK_SRC 49 -+#define NSS_CC_PORT3_RX_DIV_CLK_SRC 50 -+#define NSS_CC_PORT3_TX_CLK 51 -+#define NSS_CC_PORT3_TX_CLK_SRC 52 -+#define NSS_CC_PORT3_TX_DIV_CLK_SRC 53 -+#define NSS_CC_PORT4_MAC_CLK 54 -+#define NSS_CC_PORT4_RX_CLK 55 -+#define NSS_CC_PORT4_RX_CLK_SRC 56 -+#define NSS_CC_PORT4_RX_DIV_CLK_SRC 57 -+#define NSS_CC_PORT4_TX_CLK 58 -+#define NSS_CC_PORT4_TX_CLK_SRC 59 -+#define NSS_CC_PORT4_TX_DIV_CLK_SRC 60 -+#define NSS_CC_PORT5_MAC_CLK 61 -+#define NSS_CC_PORT5_RX_CLK 62 -+#define NSS_CC_PORT5_RX_CLK_SRC 63 -+#define NSS_CC_PORT5_RX_DIV_CLK_SRC 64 -+#define NSS_CC_PORT5_TX_CLK 65 -+#define NSS_CC_PORT5_TX_CLK_SRC 66 -+#define NSS_CC_PORT5_TX_DIV_CLK_SRC 67 -+#define NSS_CC_PORT6_MAC_CLK 68 -+#define NSS_CC_PORT6_RX_CLK 69 -+#define NSS_CC_PORT6_RX_CLK_SRC 70 -+#define NSS_CC_PORT6_RX_DIV_CLK_SRC 71 -+#define NSS_CC_PORT6_TX_CLK 72 -+#define NSS_CC_PORT6_TX_CLK_SRC 73 -+#define NSS_CC_PORT6_TX_DIV_CLK_SRC 74 -+#define NSS_CC_PPE_CLK_SRC 75 -+#define NSS_CC_PPE_EDMA_CFG_CLK 76 -+#define NSS_CC_PPE_EDMA_CLK 77 -+#define NSS_CC_PPE_SWITCH_BTQ_CLK 78 -+#define NSS_CC_PPE_SWITCH_CFG_CLK 79 -+#define NSS_CC_PPE_SWITCH_CLK 80 -+#define NSS_CC_PPE_SWITCH_IPE_CLK 81 -+#define NSS_CC_UBI0_CLK_SRC 82 -+#define NSS_CC_UBI0_DIV_CLK_SRC 83 -+#define NSS_CC_UBI1_CLK_SRC 84 -+#define NSS_CC_UBI1_DIV_CLK_SRC 85 -+#define NSS_CC_UBI2_CLK_SRC 86 -+#define NSS_CC_UBI2_DIV_CLK_SRC 87 -+#define NSS_CC_UBI32_AHB0_CLK 88 -+#define NSS_CC_UBI32_AHB1_CLK 89 -+#define NSS_CC_UBI32_AHB2_CLK 90 -+#define NSS_CC_UBI32_AHB3_CLK 91 -+#define NSS_CC_UBI32_AXI0_CLK 92 -+#define NSS_CC_UBI32_AXI1_CLK 93 -+#define NSS_CC_UBI32_AXI2_CLK 94 -+#define NSS_CC_UBI32_AXI3_CLK 95 -+#define NSS_CC_UBI32_CORE0_CLK 96 -+#define NSS_CC_UBI32_CORE1_CLK 97 -+#define NSS_CC_UBI32_CORE2_CLK 98 -+#define NSS_CC_UBI32_CORE3_CLK 99 -+#define NSS_CC_UBI32_INTR0_AHB_CLK 100 -+#define NSS_CC_UBI32_INTR1_AHB_CLK 101 -+#define NSS_CC_UBI32_INTR2_AHB_CLK 102 -+#define NSS_CC_UBI32_INTR3_AHB_CLK 103 -+#define NSS_CC_UBI32_NC_AXI0_CLK 104 -+#define NSS_CC_UBI32_NC_AXI1_CLK 105 -+#define NSS_CC_UBI32_NC_AXI2_CLK 106 -+#define NSS_CC_UBI32_NC_AXI3_CLK 107 -+#define NSS_CC_UBI32_UTCM0_CLK 108 -+#define NSS_CC_UBI32_UTCM1_CLK 109 -+#define NSS_CC_UBI32_UTCM2_CLK 110 -+#define NSS_CC_UBI32_UTCM3_CLK 111 -+#define NSS_CC_UBI3_CLK_SRC 112 -+#define NSS_CC_UBI3_DIV_CLK_SRC 113 -+#define NSS_CC_UBI_AXI_CLK_SRC 114 -+#define NSS_CC_UBI_NC_AXI_BFDCD_CLK_SRC 115 -+#define NSS_CC_UNIPHY_PORT1_RX_CLK 116 -+#define NSS_CC_UNIPHY_PORT1_TX_CLK 117 -+#define NSS_CC_UNIPHY_PORT2_RX_CLK 118 -+#define NSS_CC_UNIPHY_PORT2_TX_CLK 119 -+#define NSS_CC_UNIPHY_PORT3_RX_CLK 120 -+#define NSS_CC_UNIPHY_PORT3_TX_CLK 121 -+#define NSS_CC_UNIPHY_PORT4_RX_CLK 122 -+#define NSS_CC_UNIPHY_PORT4_TX_CLK 123 -+#define NSS_CC_UNIPHY_PORT5_RX_CLK 124 -+#define NSS_CC_UNIPHY_PORT5_TX_CLK 125 -+#define NSS_CC_UNIPHY_PORT6_RX_CLK 126 -+#define NSS_CC_UNIPHY_PORT6_TX_CLK 127 -+#define NSS_CC_XGMAC0_PTP_REF_CLK 128 -+#define NSS_CC_XGMAC0_PTP_REF_DIV_CLK_SRC 129 -+#define NSS_CC_XGMAC1_PTP_REF_CLK 130 -+#define NSS_CC_XGMAC1_PTP_REF_DIV_CLK_SRC 131 -+#define NSS_CC_XGMAC2_PTP_REF_CLK 132 -+#define NSS_CC_XGMAC2_PTP_REF_DIV_CLK_SRC 133 -+#define NSS_CC_XGMAC3_PTP_REF_CLK 134 -+#define NSS_CC_XGMAC3_PTP_REF_DIV_CLK_SRC 135 -+#define NSS_CC_XGMAC4_PTP_REF_CLK 136 -+#define NSS_CC_XGMAC4_PTP_REF_DIV_CLK_SRC 137 -+#define NSS_CC_XGMAC5_PTP_REF_CLK 138 -+#define NSS_CC_XGMAC5_PTP_REF_DIV_CLK_SRC 139 -+#define UBI32_PLL 140 -+#define UBI32_PLL_MAIN 141 -+ -+#endif ---- /dev/null -+++ b/include/dt-bindings/reset/qcom,ipq9574-nsscc.h -@@ -0,0 +1,134 @@ -+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ -+/* -+ * Copyright (c) 2023, 2025 The Linux Foundation. All rights reserved. -+ */ -+ -+#ifndef _DT_BINDINGS_RESET_IPQ_NSSCC_9574_H -+#define _DT_BINDINGS_RESET_IPQ_NSSCC_9574_H -+ -+#define EDMA_HW_RESET 0 -+#define NSS_CC_CE_BCR 1 -+#define NSS_CC_CLC_BCR 2 -+#define NSS_CC_EIP197_BCR 3 -+#define NSS_CC_HAQ_BCR 4 -+#define NSS_CC_IMEM_BCR 5 -+#define NSS_CC_MAC_BCR 6 -+#define NSS_CC_PPE_BCR 7 -+#define NSS_CC_UBI_BCR 8 -+#define NSS_CC_UNIPHY_BCR 9 -+#define UBI3_CLKRST_CLAMP_ENABLE 10 -+#define UBI3_CORE_CLAMP_ENABLE 11 -+#define UBI2_CLKRST_CLAMP_ENABLE 12 -+#define UBI2_CORE_CLAMP_ENABLE 13 -+#define UBI1_CLKRST_CLAMP_ENABLE 14 -+#define UBI1_CORE_CLAMP_ENABLE 15 -+#define UBI0_CLKRST_CLAMP_ENABLE 16 -+#define UBI0_CORE_CLAMP_ENABLE 17 -+#define NSSNOC_NSS_CSR_ARES 18 -+#define NSS_CSR_ARES 19 -+#define PPE_BTQ_ARES 20 -+#define PPE_IPE_ARES 21 -+#define PPE_ARES 22 -+#define PPE_CFG_ARES 23 -+#define PPE_EDMA_ARES 24 -+#define PPE_EDMA_CFG_ARES 25 -+#define CRY_PPE_ARES 26 -+#define NSSNOC_PPE_ARES 27 -+#define NSSNOC_PPE_CFG_ARES 28 -+#define PORT1_MAC_ARES 29 -+#define PORT2_MAC_ARES 30 -+#define PORT3_MAC_ARES 31 -+#define PORT4_MAC_ARES 32 -+#define PORT5_MAC_ARES 33 -+#define PORT6_MAC_ARES 34 -+#define XGMAC0_PTP_REF_ARES 35 -+#define XGMAC1_PTP_REF_ARES 36 -+#define XGMAC2_PTP_REF_ARES 37 -+#define XGMAC3_PTP_REF_ARES 38 -+#define XGMAC4_PTP_REF_ARES 39 -+#define XGMAC5_PTP_REF_ARES 40 -+#define HAQ_AHB_ARES 41 -+#define HAQ_AXI_ARES 42 -+#define NSSNOC_HAQ_AHB_ARES 43 -+#define NSSNOC_HAQ_AXI_ARES 44 -+#define CE_APB_ARES 45 -+#define CE_AXI_ARES 46 -+#define NSSNOC_CE_APB_ARES 47 -+#define NSSNOC_CE_AXI_ARES 48 -+#define CRYPTO_ARES 49 -+#define NSSNOC_CRYPTO_ARES 50 -+#define NSSNOC_NC_AXI0_1_ARES 51 -+#define UBI0_CORE_ARES 52 -+#define UBI1_CORE_ARES 53 -+#define UBI2_CORE_ARES 54 -+#define UBI3_CORE_ARES 55 -+#define NC_AXI0_ARES 56 -+#define UTCM0_ARES 57 -+#define NC_AXI1_ARES 58 -+#define UTCM1_ARES 59 -+#define NC_AXI2_ARES 60 -+#define UTCM2_ARES 61 -+#define NC_AXI3_ARES 62 -+#define UTCM3_ARES 63 -+#define NSSNOC_NC_AXI0_ARES 64 -+#define AHB0_ARES 65 -+#define INTR0_AHB_ARES 66 -+#define AHB1_ARES 67 -+#define INTR1_AHB_ARES 68 -+#define AHB2_ARES 69 -+#define INTR2_AHB_ARES 70 -+#define AHB3_ARES 71 -+#define INTR3_AHB_ARES 72 -+#define NSSNOC_AHB0_ARES 73 -+#define NSSNOC_INT0_AHB_ARES 74 -+#define AXI0_ARES 75 -+#define AXI1_ARES 76 -+#define AXI2_ARES 77 -+#define AXI3_ARES 78 -+#define NSSNOC_AXI0_ARES 79 -+#define IMEM_QSB_ARES 80 -+#define NSSNOC_IMEM_QSB_ARES 81 -+#define IMEM_AHB_ARES 82 -+#define NSSNOC_IMEM_AHB_ARES 83 -+#define UNIPHY_PORT1_RX_ARES 84 -+#define UNIPHY_PORT1_TX_ARES 85 -+#define UNIPHY_PORT2_RX_ARES 86 -+#define UNIPHY_PORT2_TX_ARES 87 -+#define UNIPHY_PORT3_RX_ARES 88 -+#define UNIPHY_PORT3_TX_ARES 89 -+#define UNIPHY_PORT4_RX_ARES 90 -+#define UNIPHY_PORT4_TX_ARES 91 -+#define UNIPHY_PORT5_RX_ARES 92 -+#define UNIPHY_PORT5_TX_ARES 93 -+#define UNIPHY_PORT6_RX_ARES 94 -+#define UNIPHY_PORT6_TX_ARES 95 -+#define PORT1_RX_ARES 96 -+#define PORT1_TX_ARES 97 -+#define PORT2_RX_ARES 98 -+#define PORT2_TX_ARES 99 -+#define PORT3_RX_ARES 100 -+#define PORT3_TX_ARES 101 -+#define PORT4_RX_ARES 102 -+#define PORT4_TX_ARES 103 -+#define PORT5_RX_ARES 104 -+#define PORT5_TX_ARES 105 -+#define PORT6_RX_ARES 106 -+#define PORT6_TX_ARES 107 -+#define PPE_FULL_RESET 108 -+#define UNIPHY0_SOFT_RESET 109 -+#define UNIPHY1_SOFT_RESET 110 -+#define UNIPHY2_SOFT_RESET 111 -+#define UNIPHY_PORT1_ARES 112 -+#define UNIPHY_PORT2_ARES 113 -+#define UNIPHY_PORT3_ARES 114 -+#define UNIPHY_PORT4_ARES 115 -+#define UNIPHY_PORT5_ARES 116 -+#define UNIPHY_PORT6_ARES 117 -+#define NSSPORT1_RESET 118 -+#define NSSPORT2_RESET 119 -+#define NSSPORT3_RESET 120 -+#define NSSPORT4_RESET 121 -+#define NSSPORT5_RESET 122 -+#define NSSPORT6_RESET 123 -+ -+#endif diff --git a/target/linux/qualcommbe/patches-6.12/0020-v6.15-clk-qcom-gcc-ipq9574-Add-support-for-gpll0_out.patch b/target/linux/qualcommbe/patches-6.12/0020-v6.15-clk-qcom-gcc-ipq9574-Add-support-for-gpll0_out.patch deleted file mode 100644 index 357fb18a71..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0020-v6.15-clk-qcom-gcc-ipq9574-Add-support-for-gpll0_out.patch +++ /dev/null @@ -1,49 +0,0 @@ -From c4e7d95921b074980ffd389254bcbfc045dd2a49 Mon Sep 17 00:00:00 2001 -From: Devi Priya -Date: Thu, 13 Mar 2025 16:33:55 +0530 -Subject: [PATCH 20/22] v6.15: clk: qcom: gcc-ipq9574: Add support for - gpll0_out_aux clock - -Add support for gpll0_out_aux clock which acts as the parent for -certain networking subsystem (nss) clocks. - -Reviewed-by: Dmitry Baryshkov -Signed-off-by: Devi Priya -Signed-off-by: Manikanta Mylavarapu -Link: https://lore.kernel.org/r/20250313110359.242491-3-quic_mmanikan@quicinc.com -Signed-off-by: Bjorn Andersson ---- - drivers/clk/qcom/gcc-ipq9574.c | 15 +++++++++++++++ - 1 file changed, 15 insertions(+) - ---- a/drivers/clk/qcom/gcc-ipq9574.c -+++ b/drivers/clk/qcom/gcc-ipq9574.c -@@ -108,6 +108,20 @@ static struct clk_alpha_pll_postdiv gpll - }, - }; - -+static struct clk_alpha_pll_postdiv gpll0_out_aux = { -+ .offset = 0x20000, -+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], -+ .width = 4, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "gpll0_out_aux", -+ .parent_hws = (const struct clk_hw *[]) { -+ &gpll0_main.clkr.hw -+ }, -+ .num_parents = 1, -+ .ops = &clk_alpha_pll_postdiv_ro_ops, -+ }, -+}; -+ - static struct clk_alpha_pll gpll4_main = { - .offset = 0x22000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], -@@ -4222,6 +4236,7 @@ static struct clk_regmap *gcc_ipq9574_cl - [GCC_PCIE1_PIPE_CLK] = &gcc_pcie1_pipe_clk.clkr, - [GCC_PCIE2_PIPE_CLK] = &gcc_pcie2_pipe_clk.clkr, - [GCC_PCIE3_PIPE_CLK] = &gcc_pcie3_pipe_clk.clkr, -+ [GPLL0_OUT_AUX] = &gpll0_out_aux.clkr, - }; - - static const struct qcom_reset_map gcc_ipq9574_resets[] = { diff --git a/target/linux/qualcommbe/patches-6.12/0021-v6.15-clk-qcom-Add-NSS-clock-Controller-driver-for-I.patch b/target/linux/qualcommbe/patches-6.12/0021-v6.15-clk-qcom-Add-NSS-clock-Controller-driver-for-I.patch deleted file mode 100644 index e6d95f8bf3..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0021-v6.15-clk-qcom-Add-NSS-clock-Controller-driver-for-I.patch +++ /dev/null @@ -1,3160 +0,0 @@ -From 8b42bea7cf2a21e854becf29760a947bef5cde0b Mon Sep 17 00:00:00 2001 -From: Devi Priya -Date: Thu, 13 Mar 2025 16:33:57 +0530 -Subject: [PATCH 21/22] v6.15: clk: qcom: Add NSS clock Controller driver for - IPQ9574 - -Add Networking Sub System Clock Controller (NSSCC) driver for ipq9574 based -devices. - -Reviewed-by: Konrad Dybcio -Signed-off-by: Devi Priya -Signed-off-by: Manikanta Mylavarapu -Link: https://lore.kernel.org/r/20250313110359.242491-5-quic_mmanikan@quicinc.com -Signed-off-by: Bjorn Andersson ---- - drivers/clk/qcom/Kconfig | 7 + - drivers/clk/qcom/Makefile | 1 + - drivers/clk/qcom/nsscc-ipq9574.c | 3110 ++++++++++++++++++++++++++++++ - 3 files changed, 3118 insertions(+) - create mode 100644 drivers/clk/qcom/nsscc-ipq9574.c - ---- a/drivers/clk/qcom/Kconfig -+++ b/drivers/clk/qcom/Kconfig -@@ -264,6 +264,13 @@ config IPQ_GCC_9574 - i2c, USB, SD/eMMC, etc. Select this for the root clock - of ipq9574. - -+config IPQ_NSSCC_9574 -+ tristate "IPQ9574 NSS Clock Controller" -+ depends on ARM64 || COMPILE_TEST -+ depends on IPQ_GCC_9574 -+ help -+ Support for NSS clock controller on ipq9574 devices. -+ - config IPQ_NSSCC_QCA8K - tristate "QCA8K(QCA8386 or QCA8084) NSS Clock Controller" - depends on MDIO_BUS ---- a/drivers/clk/qcom/Makefile -+++ b/drivers/clk/qcom/Makefile -@@ -37,6 +37,7 @@ obj-$(CONFIG_IPQ_GCC_6018) += gcc-ipq601 - obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o - obj-$(CONFIG_IPQ_GCC_8074) += gcc-ipq8074.o - obj-$(CONFIG_IPQ_GCC_9574) += gcc-ipq9574.o -+obj-$(CONFIG_IPQ_NSSCC_9574) += nsscc-ipq9574.o - obj-$(CONFIG_IPQ_LCC_806X) += lcc-ipq806x.o - obj-$(CONFIG_IPQ_NSSCC_QCA8K) += nsscc-qca8k.o - obj-$(CONFIG_MDM_GCC_9607) += gcc-mdm9607.o ---- /dev/null -+++ b/drivers/clk/qcom/nsscc-ipq9574.c -@@ -0,0 +1,3110 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (c) 2021, The Linux Foundation. All rights reserved. -+ * Copyright (c) 2023, 2025 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "clk-alpha-pll.h" -+#include "clk-branch.h" -+#include "clk-pll.h" -+#include "clk-rcg.h" -+#include "clk-regmap.h" -+#include "clk-regmap-divider.h" -+#include "clk-regmap-mux.h" -+#include "common.h" -+#include "reset.h" -+ -+/* Need to match the order of clocks in DT binding */ -+enum { -+ DT_XO, -+ DT_BIAS_PLL_CC_CLK, -+ DT_BIAS_PLL_UBI_NC_CLK, -+ DT_GCC_GPLL0_OUT_AUX, -+ DT_UNIPHY0_NSS_RX_CLK, -+ DT_UNIPHY0_NSS_TX_CLK, -+ DT_UNIPHY1_NSS_RX_CLK, -+ DT_UNIPHY1_NSS_TX_CLK, -+ DT_UNIPHY2_NSS_RX_CLK, -+ DT_UNIPHY2_NSS_TX_CLK, -+}; -+ -+enum { -+ P_XO, -+ P_BIAS_PLL_CC_CLK, -+ P_BIAS_PLL_UBI_NC_CLK, -+ P_GCC_GPLL0_OUT_AUX, -+ P_UBI32_PLL_OUT_MAIN, -+ P_UNIPHY0_NSS_RX_CLK, -+ P_UNIPHY0_NSS_TX_CLK, -+ P_UNIPHY1_NSS_RX_CLK, -+ P_UNIPHY1_NSS_TX_CLK, -+ P_UNIPHY2_NSS_RX_CLK, -+ P_UNIPHY2_NSS_TX_CLK, -+}; -+ -+static const struct alpha_pll_config ubi32_pll_config = { -+ .l = 0x3e, -+ .alpha = 0x6666, -+ .config_ctl_val = 0x200d4aa8, -+ .config_ctl_hi_val = 0x3c, -+ .main_output_mask = BIT(0), -+ .aux_output_mask = BIT(1), -+ .pre_div_val = 0x0, -+ .pre_div_mask = BIT(12), -+ .post_div_val = 0x0, -+ .post_div_mask = GENMASK(9, 8), -+ .alpha_en_mask = BIT(24), -+ .test_ctl_val = 0x1c0000c0, -+ .test_ctl_hi_val = 0x4000, -+}; -+ -+static struct clk_alpha_pll ubi32_pll_main = { -+ .offset = 0x28000, -+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_NSS_HUAYRA], -+ .flags = SUPPORTS_DYNAMIC_UPDATE, -+ .clkr = { -+ .hw.init = &(const struct clk_init_data) { -+ .name = "ubi32_pll_main", -+ .parent_data = &(const struct clk_parent_data) { -+ .index = DT_XO, -+ }, -+ .num_parents = 1, -+ .ops = &clk_alpha_pll_huayra_ops, -+ }, -+ }, -+}; -+ -+static struct clk_alpha_pll_postdiv ubi32_pll = { -+ .offset = 0x28000, -+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_NSS_HUAYRA], -+ .width = 2, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "ubi32_pll", -+ .parent_hws = (const struct clk_hw *[]) { -+ &ubi32_pll_main.clkr.hw -+ }, -+ .num_parents = 1, -+ .ops = &clk_alpha_pll_postdiv_ro_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+}; -+ -+static const struct parent_map nss_cc_parent_map_0[] = { -+ { P_XO, 0 }, -+ { P_BIAS_PLL_CC_CLK, 1 }, -+ { P_UNIPHY0_NSS_RX_CLK, 2 }, -+ { P_UNIPHY0_NSS_TX_CLK, 3 }, -+ { P_UNIPHY1_NSS_RX_CLK, 4 }, -+ { P_UNIPHY1_NSS_TX_CLK, 5 }, -+}; -+ -+static const struct clk_parent_data nss_cc_parent_data_0[] = { -+ { .index = DT_XO }, -+ { .index = DT_BIAS_PLL_CC_CLK }, -+ { .index = DT_UNIPHY0_NSS_RX_CLK }, -+ { .index = DT_UNIPHY0_NSS_TX_CLK }, -+ { .index = DT_UNIPHY1_NSS_RX_CLK }, -+ { .index = DT_UNIPHY1_NSS_TX_CLK }, -+}; -+ -+static const struct parent_map nss_cc_parent_map_1[] = { -+ { P_XO, 0 }, -+ { P_BIAS_PLL_UBI_NC_CLK, 1 }, -+ { P_GCC_GPLL0_OUT_AUX, 2 }, -+ { P_BIAS_PLL_CC_CLK, 6 }, -+}; -+ -+static const struct clk_parent_data nss_cc_parent_data_1[] = { -+ { .index = DT_XO }, -+ { .index = DT_BIAS_PLL_UBI_NC_CLK }, -+ { .index = DT_GCC_GPLL0_OUT_AUX }, -+ { .index = DT_BIAS_PLL_CC_CLK }, -+}; -+ -+static const struct parent_map nss_cc_parent_map_2[] = { -+ { P_XO, 0 }, -+ { P_UBI32_PLL_OUT_MAIN, 1 }, -+ { P_GCC_GPLL0_OUT_AUX, 2 }, -+}; -+ -+static const struct clk_parent_data nss_cc_parent_data_2[] = { -+ { .index = DT_XO }, -+ { .hw = &ubi32_pll.clkr.hw }, -+ { .index = DT_GCC_GPLL0_OUT_AUX }, -+}; -+ -+static const struct parent_map nss_cc_parent_map_3[] = { -+ { P_XO, 0 }, -+ { P_BIAS_PLL_CC_CLK, 1 }, -+ { P_GCC_GPLL0_OUT_AUX, 2 }, -+}; -+ -+static const struct clk_parent_data nss_cc_parent_data_3[] = { -+ { .index = DT_XO }, -+ { .index = DT_BIAS_PLL_CC_CLK }, -+ { .index = DT_GCC_GPLL0_OUT_AUX }, -+}; -+ -+static const struct parent_map nss_cc_parent_map_4[] = { -+ { P_XO, 0 }, -+ { P_BIAS_PLL_CC_CLK, 1 }, -+ { P_UNIPHY0_NSS_RX_CLK, 2 }, -+ { P_UNIPHY0_NSS_TX_CLK, 3 }, -+}; -+ -+static const struct clk_parent_data nss_cc_parent_data_4[] = { -+ { .index = DT_XO }, -+ { .index = DT_BIAS_PLL_CC_CLK }, -+ { .index = DT_UNIPHY0_NSS_RX_CLK }, -+ { .index = DT_UNIPHY0_NSS_TX_CLK }, -+}; -+ -+static const struct parent_map nss_cc_parent_map_5[] = { -+ { P_XO, 0 }, -+ { P_BIAS_PLL_CC_CLK, 1 }, -+ { P_UNIPHY2_NSS_RX_CLK, 2 }, -+ { P_UNIPHY2_NSS_TX_CLK, 3 }, -+}; -+ -+static const struct clk_parent_data nss_cc_parent_data_5[] = { -+ { .index = DT_XO }, -+ { .index = DT_BIAS_PLL_CC_CLK }, -+ { .index = DT_UNIPHY2_NSS_RX_CLK }, -+ { .index = DT_UNIPHY2_NSS_TX_CLK }, -+}; -+ -+static const struct parent_map nss_cc_parent_map_6[] = { -+ { P_XO, 0 }, -+ { P_GCC_GPLL0_OUT_AUX, 2 }, -+ { P_BIAS_PLL_CC_CLK, 6 }, -+}; -+ -+static const struct clk_parent_data nss_cc_parent_data_6[] = { -+ { .index = DT_XO }, -+ { .index = DT_GCC_GPLL0_OUT_AUX }, -+ { .index = DT_BIAS_PLL_CC_CLK }, -+}; -+ -+static const struct parent_map nss_cc_parent_map_7[] = { -+ { P_XO, 0 }, -+ { P_UBI32_PLL_OUT_MAIN, 1 }, -+ { P_GCC_GPLL0_OUT_AUX, 2 }, -+ { P_BIAS_PLL_CC_CLK, 6 }, -+}; -+ -+static const struct clk_parent_data nss_cc_parent_data_7[] = { -+ { .index = DT_XO }, -+ { .hw = &ubi32_pll.clkr.hw }, -+ { .index = DT_GCC_GPLL0_OUT_AUX }, -+ { .index = DT_BIAS_PLL_CC_CLK }, -+}; -+ -+static const struct freq_tbl ftbl_nss_cc_ce_clk_src[] = { -+ F(24000000, P_XO, 1, 0, 0), -+ F(353000000, P_BIAS_PLL_UBI_NC_CLK, 1, 0, 0), -+ { } -+}; -+ -+static struct clk_rcg2 nss_cc_ce_clk_src = { -+ .cmd_rcgr = 0x28404, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_1, -+ .freq_tbl = ftbl_nss_cc_ce_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ce_clk_src", -+ .parent_data = nss_cc_parent_data_1, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_1), -+ .ops = &clk_rcg2_ops, -+ }, -+}; -+ -+static const struct freq_tbl ftbl_nss_cc_cfg_clk_src[] = { -+ F(100000000, P_GCC_GPLL0_OUT_AUX, 8, 0, 0), -+ { } -+}; -+ -+static struct clk_rcg2 nss_cc_cfg_clk_src = { -+ .cmd_rcgr = 0x28104, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_3, -+ .freq_tbl = ftbl_nss_cc_cfg_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_cfg_clk_src", -+ .parent_data = nss_cc_parent_data_3, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_3), -+ .ops = &clk_rcg2_ops, -+ }, -+}; -+ -+static const struct freq_tbl ftbl_nss_cc_clc_clk_src[] = { -+ F(533333333, P_GCC_GPLL0_OUT_AUX, 1.5, 0, 0), -+ { } -+}; -+ -+static struct clk_rcg2 nss_cc_clc_clk_src = { -+ .cmd_rcgr = 0x28604, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_6, -+ .freq_tbl = ftbl_nss_cc_clc_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_clc_clk_src", -+ .parent_data = nss_cc_parent_data_6, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_6), -+ .ops = &clk_rcg2_ops, -+ }, -+}; -+ -+static const struct freq_tbl ftbl_nss_cc_crypto_clk_src[] = { -+ F(24000000, P_XO, 1, 0, 0), -+ F(300000000, P_BIAS_PLL_CC_CLK, 4, 0, 0), -+ F(600000000, P_BIAS_PLL_CC_CLK, 2, 0, 0), -+ { } -+}; -+ -+static struct clk_rcg2 nss_cc_crypto_clk_src = { -+ .cmd_rcgr = 0x16008, -+ .mnd_width = 16, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_3, -+ .freq_tbl = ftbl_nss_cc_crypto_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_crypto_clk_src", -+ .parent_data = nss_cc_parent_data_3, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_3), -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_rcg2_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_haq_clk_src = { -+ .cmd_rcgr = 0x28304, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_1, -+ .freq_tbl = ftbl_nss_cc_ce_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_haq_clk_src", -+ .parent_data = nss_cc_parent_data_1, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_1), -+ .ops = &clk_rcg2_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_imem_clk_src = { -+ .cmd_rcgr = 0xe008, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_1, -+ .freq_tbl = ftbl_nss_cc_ce_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_imem_clk_src", -+ .parent_data = nss_cc_parent_data_1, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_1), -+ .ops = &clk_rcg2_ops, -+ }, -+}; -+ -+static const struct freq_tbl ftbl_nss_cc_int_cfg_clk_src[] = { -+ F(200000000, P_GCC_GPLL0_OUT_AUX, 4, 0, 0), -+ { } -+}; -+ -+static struct clk_rcg2 nss_cc_int_cfg_clk_src = { -+ .cmd_rcgr = 0x287b4, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_3, -+ .freq_tbl = ftbl_nss_cc_int_cfg_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_int_cfg_clk_src", -+ .parent_data = nss_cc_parent_data_3, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_3), -+ .ops = &clk_rcg2_ops, -+ }, -+}; -+ -+static const struct freq_conf ftbl_nss_cc_port1_rx_clk_src_25[] = { -+ C(P_UNIPHY0_NSS_RX_CLK, 12.5, 0, 0), -+ C(P_UNIPHY0_NSS_RX_CLK, 5, 0, 0), -+}; -+ -+static const struct freq_conf ftbl_nss_cc_port1_rx_clk_src_125[] = { -+ C(P_UNIPHY0_NSS_RX_CLK, 2.5, 0, 0), -+ C(P_UNIPHY0_NSS_RX_CLK, 1, 0, 0), -+}; -+ -+static const struct freq_multi_tbl ftbl_nss_cc_port1_rx_clk_src[] = { -+ FMS(24000000, P_XO, 1, 0, 0), -+ FM(25000000, ftbl_nss_cc_port1_rx_clk_src_25), -+ FMS(78125000, P_UNIPHY0_NSS_RX_CLK, 4, 0, 0), -+ FM(125000000, ftbl_nss_cc_port1_rx_clk_src_125), -+ FMS(312500000, P_UNIPHY0_NSS_RX_CLK, 1, 0, 0), -+ { } -+}; -+ -+static const struct freq_conf ftbl_nss_cc_port1_tx_clk_src_25[] = { -+ C(P_UNIPHY0_NSS_TX_CLK, 12.5, 0, 0), -+ C(P_UNIPHY0_NSS_TX_CLK, 5, 0, 0), -+}; -+ -+static const struct freq_conf ftbl_nss_cc_port1_tx_clk_src_125[] = { -+ C(P_UNIPHY0_NSS_TX_CLK, 2.5, 0, 0), -+ C(P_UNIPHY0_NSS_TX_CLK, 1, 0, 0), -+}; -+ -+static const struct freq_multi_tbl ftbl_nss_cc_port1_tx_clk_src[] = { -+ FMS(24000000, P_XO, 1, 0, 0), -+ FM(25000000, ftbl_nss_cc_port1_tx_clk_src_25), -+ FMS(78125000, P_UNIPHY0_NSS_TX_CLK, 4, 0, 0), -+ FM(125000000, ftbl_nss_cc_port1_tx_clk_src_125), -+ FMS(312500000, P_UNIPHY0_NSS_TX_CLK, 1, 0, 0), -+ { } -+}; -+ -+static const struct freq_conf ftbl_nss_cc_port5_rx_clk_src_25[] = { -+ C(P_UNIPHY1_NSS_RX_CLK, 12.5, 0, 0), -+ C(P_UNIPHY0_NSS_RX_CLK, 5, 0, 0), -+}; -+ -+static const struct freq_conf ftbl_nss_cc_port5_rx_clk_src_125[] = { -+ C(P_UNIPHY1_NSS_RX_CLK, 2.5, 0, 0), -+ C(P_UNIPHY0_NSS_RX_CLK, 1, 0, 0), -+}; -+ -+static const struct freq_conf ftbl_nss_cc_port5_rx_clk_src_312p5[] = { -+ C(P_UNIPHY1_NSS_RX_CLK, 1, 0, 0), -+ C(P_UNIPHY0_NSS_RX_CLK, 1, 0, 0), -+}; -+ -+static const struct freq_multi_tbl ftbl_nss_cc_port5_rx_clk_src[] = { -+ FMS(24000000, P_XO, 1, 0, 0), -+ FM(25000000, ftbl_nss_cc_port5_rx_clk_src_25), -+ FMS(78125000, P_UNIPHY1_NSS_RX_CLK, 4, 0, 0), -+ FM(125000000, ftbl_nss_cc_port5_rx_clk_src_125), -+ FMS(156250000, P_UNIPHY1_NSS_RX_CLK, 2, 0, 0), -+ FM(312500000, ftbl_nss_cc_port5_rx_clk_src_312p5), -+ { } -+}; -+ -+static const struct freq_conf ftbl_nss_cc_port5_tx_clk_src_25[] = { -+ C(P_UNIPHY1_NSS_TX_CLK, 12.5, 0, 0), -+ C(P_UNIPHY0_NSS_TX_CLK, 5, 0, 0), -+}; -+ -+static const struct freq_conf ftbl_nss_cc_port5_tx_clk_src_125[] = { -+ C(P_UNIPHY1_NSS_TX_CLK, 2.5, 0, 0), -+ C(P_UNIPHY0_NSS_TX_CLK, 1, 0, 0), -+}; -+ -+static const struct freq_conf ftbl_nss_cc_port5_tx_clk_src_312p5[] = { -+ C(P_UNIPHY1_NSS_TX_CLK, 1, 0, 0), -+ C(P_UNIPHY0_NSS_TX_CLK, 1, 0, 0), -+}; -+ -+static const struct freq_multi_tbl ftbl_nss_cc_port5_tx_clk_src[] = { -+ FMS(24000000, P_XO, 1, 0, 0), -+ FM(25000000, ftbl_nss_cc_port5_tx_clk_src_25), -+ FMS(78125000, P_UNIPHY1_NSS_TX_CLK, 4, 0, 0), -+ FM(125000000, ftbl_nss_cc_port5_tx_clk_src_125), -+ FMS(156250000, P_UNIPHY1_NSS_TX_CLK, 2, 0, 0), -+ FM(312500000, ftbl_nss_cc_port5_tx_clk_src_312p5), -+ { } -+}; -+ -+static const struct freq_conf ftbl_nss_cc_port6_rx_clk_src_25[] = { -+ C(P_UNIPHY2_NSS_RX_CLK, 12.5, 0, 0), -+ C(P_UNIPHY2_NSS_RX_CLK, 5, 0, 0), -+}; -+ -+static const struct freq_conf ftbl_nss_cc_port6_rx_clk_src_125[] = { -+ C(P_UNIPHY2_NSS_RX_CLK, 2.5, 0, 0), -+ C(P_UNIPHY2_NSS_RX_CLK, 1, 0, 0), -+}; -+ -+static const struct freq_multi_tbl ftbl_nss_cc_port6_rx_clk_src[] = { -+ FMS(24000000, P_XO, 1, 0, 0), -+ FM(25000000, ftbl_nss_cc_port6_rx_clk_src_25), -+ FMS(78125000, P_UNIPHY2_NSS_RX_CLK, 4, 0, 0), -+ FM(125000000, ftbl_nss_cc_port6_rx_clk_src_125), -+ FMS(156250000, P_UNIPHY2_NSS_RX_CLK, 2, 0, 0), -+ FMS(312500000, P_UNIPHY2_NSS_RX_CLK, 1, 0, 0), -+ { } -+}; -+ -+static const struct freq_conf ftbl_nss_cc_port6_tx_clk_src_25[] = { -+ C(P_UNIPHY2_NSS_TX_CLK, 12.5, 0, 0), -+ C(P_UNIPHY2_NSS_TX_CLK, 5, 0, 0), -+}; -+ -+static const struct freq_conf ftbl_nss_cc_port6_tx_clk_src_125[] = { -+ C(P_UNIPHY2_NSS_TX_CLK, 2.5, 0, 0), -+ C(P_UNIPHY2_NSS_TX_CLK, 1, 0, 0), -+}; -+ -+static const struct freq_multi_tbl ftbl_nss_cc_port6_tx_clk_src[] = { -+ FMS(24000000, P_XO, 1, 0, 0), -+ FM(25000000, ftbl_nss_cc_port6_tx_clk_src_25), -+ FMS(78125000, P_UNIPHY2_NSS_TX_CLK, 4, 0, 0), -+ FM(125000000, ftbl_nss_cc_port6_tx_clk_src_125), -+ FMS(156250000, P_UNIPHY2_NSS_TX_CLK, 2, 0, 0), -+ FMS(312500000, P_UNIPHY2_NSS_TX_CLK, 1, 0, 0), -+ { } -+}; -+ -+static struct clk_rcg2 nss_cc_port1_rx_clk_src = { -+ .cmd_rcgr = 0x28110, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_4, -+ .freq_multi_tbl = ftbl_nss_cc_port1_rx_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port1_rx_clk_src", -+ .parent_data = nss_cc_parent_data_4, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_4), -+ .ops = &clk_rcg2_fm_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_port1_tx_clk_src = { -+ .cmd_rcgr = 0x2811c, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_4, -+ .freq_multi_tbl = ftbl_nss_cc_port1_tx_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port1_tx_clk_src", -+ .parent_data = nss_cc_parent_data_4, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_4), -+ .ops = &clk_rcg2_fm_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_port2_rx_clk_src = { -+ .cmd_rcgr = 0x28128, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_4, -+ .freq_multi_tbl = ftbl_nss_cc_port1_rx_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port2_rx_clk_src", -+ .parent_data = nss_cc_parent_data_4, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_4), -+ .ops = &clk_rcg2_fm_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_port2_tx_clk_src = { -+ .cmd_rcgr = 0x28134, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_4, -+ .freq_multi_tbl = ftbl_nss_cc_port1_tx_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port2_tx_clk_src", -+ .parent_data = nss_cc_parent_data_4, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_4), -+ .ops = &clk_rcg2_fm_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_port3_rx_clk_src = { -+ .cmd_rcgr = 0x28140, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_4, -+ .freq_multi_tbl = ftbl_nss_cc_port1_rx_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port3_rx_clk_src", -+ .parent_data = nss_cc_parent_data_4, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_4), -+ .ops = &clk_rcg2_fm_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_port3_tx_clk_src = { -+ .cmd_rcgr = 0x2814c, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_4, -+ .freq_multi_tbl = ftbl_nss_cc_port1_tx_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port3_tx_clk_src", -+ .parent_data = nss_cc_parent_data_4, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_4), -+ .ops = &clk_rcg2_fm_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_port4_rx_clk_src = { -+ .cmd_rcgr = 0x28158, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_4, -+ .freq_multi_tbl = ftbl_nss_cc_port1_rx_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port4_rx_clk_src", -+ .parent_data = nss_cc_parent_data_4, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_4), -+ .ops = &clk_rcg2_fm_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_port4_tx_clk_src = { -+ .cmd_rcgr = 0x28164, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_4, -+ .freq_multi_tbl = ftbl_nss_cc_port1_tx_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port4_tx_clk_src", -+ .parent_data = nss_cc_parent_data_4, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_4), -+ .ops = &clk_rcg2_fm_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_port5_rx_clk_src = { -+ .cmd_rcgr = 0x28170, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_0, -+ .freq_multi_tbl = ftbl_nss_cc_port5_rx_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port5_rx_clk_src", -+ .parent_data = nss_cc_parent_data_0, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_0), -+ .ops = &clk_rcg2_fm_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_port5_tx_clk_src = { -+ .cmd_rcgr = 0x2817c, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_0, -+ .freq_multi_tbl = ftbl_nss_cc_port5_tx_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port5_tx_clk_src", -+ .parent_data = nss_cc_parent_data_0, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_0), -+ .ops = &clk_rcg2_fm_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_port6_rx_clk_src = { -+ .cmd_rcgr = 0x28188, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_5, -+ .freq_multi_tbl = ftbl_nss_cc_port6_rx_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port6_rx_clk_src", -+ .parent_data = nss_cc_parent_data_5, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_5), -+ .ops = &clk_rcg2_fm_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_port6_tx_clk_src = { -+ .cmd_rcgr = 0x28194, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_5, -+ .freq_multi_tbl = ftbl_nss_cc_port6_tx_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port6_tx_clk_src", -+ .parent_data = nss_cc_parent_data_5, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_5), -+ .ops = &clk_rcg2_fm_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_ppe_clk_src = { -+ .cmd_rcgr = 0x28204, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_1, -+ .freq_tbl = ftbl_nss_cc_ce_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ppe_clk_src", -+ .parent_data = nss_cc_parent_data_1, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_1), -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_rcg2_ops, -+ }, -+}; -+ -+static const struct freq_tbl ftbl_nss_cc_ubi0_clk_src[] = { -+ F(24000000, P_XO, 1, 0, 0), -+ F(187200000, P_UBI32_PLL_OUT_MAIN, 8, 0, 0), -+ F(748800000, P_UBI32_PLL_OUT_MAIN, 2, 0, 0), -+ F(1497600000, P_UBI32_PLL_OUT_MAIN, 1, 0, 0), -+ F(1689600000, P_UBI32_PLL_OUT_MAIN, 1, 0, 0), -+ { } -+}; -+ -+static struct clk_rcg2 nss_cc_ubi0_clk_src = { -+ .cmd_rcgr = 0x28704, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_2, -+ .freq_tbl = ftbl_nss_cc_ubi0_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi0_clk_src", -+ .parent_data = nss_cc_parent_data_2, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_2), -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_rcg2_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_ubi1_clk_src = { -+ .cmd_rcgr = 0x2870c, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_2, -+ .freq_tbl = ftbl_nss_cc_ubi0_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi1_clk_src", -+ .parent_data = nss_cc_parent_data_2, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_2), -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_rcg2_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_ubi2_clk_src = { -+ .cmd_rcgr = 0x28714, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_2, -+ .freq_tbl = ftbl_nss_cc_ubi0_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi2_clk_src", -+ .parent_data = nss_cc_parent_data_2, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_2), -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_rcg2_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_ubi3_clk_src = { -+ .cmd_rcgr = 0x2871c, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_2, -+ .freq_tbl = ftbl_nss_cc_ubi0_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi3_clk_src", -+ .parent_data = nss_cc_parent_data_2, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_2), -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_rcg2_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_ubi_axi_clk_src = { -+ .cmd_rcgr = 0x28724, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_7, -+ .freq_tbl = ftbl_nss_cc_clc_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi_axi_clk_src", -+ .parent_data = nss_cc_parent_data_7, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_7), -+ .ops = &clk_rcg2_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_ubi_nc_axi_bfdcd_clk_src = { -+ .cmd_rcgr = 0x2872c, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_1, -+ .freq_tbl = ftbl_nss_cc_ce_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi_nc_axi_bfdcd_clk_src", -+ .parent_data = nss_cc_parent_data_1, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_1), -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_rcg2_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_port1_rx_div_clk_src = { -+ .reg = 0x28118, -+ .shift = 0, -+ .width = 9, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port1_rx_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port1_rx_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_port1_tx_div_clk_src = { -+ .reg = 0x28124, -+ .shift = 0, -+ .width = 9, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port1_tx_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port1_tx_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_port2_rx_div_clk_src = { -+ .reg = 0x28130, -+ .shift = 0, -+ .width = 9, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port2_rx_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port2_rx_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_port2_tx_div_clk_src = { -+ .reg = 0x2813c, -+ .shift = 0, -+ .width = 9, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port2_tx_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port2_tx_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_port3_rx_div_clk_src = { -+ .reg = 0x28148, -+ .shift = 0, -+ .width = 9, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port3_rx_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port3_rx_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_port3_tx_div_clk_src = { -+ .reg = 0x28154, -+ .shift = 0, -+ .width = 9, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port3_tx_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port3_tx_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_port4_rx_div_clk_src = { -+ .reg = 0x28160, -+ .shift = 0, -+ .width = 9, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port4_rx_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port4_rx_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_port4_tx_div_clk_src = { -+ .reg = 0x2816c, -+ .shift = 0, -+ .width = 9, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port4_tx_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port4_tx_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_port5_rx_div_clk_src = { -+ .reg = 0x28178, -+ .shift = 0, -+ .width = 9, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port5_rx_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port5_rx_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_port5_tx_div_clk_src = { -+ .reg = 0x28184, -+ .shift = 0, -+ .width = 9, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port5_tx_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port5_tx_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_port6_rx_div_clk_src = { -+ .reg = 0x28190, -+ .shift = 0, -+ .width = 9, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port6_rx_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port6_rx_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_port6_tx_div_clk_src = { -+ .reg = 0x2819c, -+ .shift = 0, -+ .width = 9, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port6_tx_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port6_tx_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_ubi0_div_clk_src = { -+ .reg = 0x287a4, -+ .shift = 0, -+ .width = 4, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi0_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi0_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ro_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_ubi1_div_clk_src = { -+ .reg = 0x287a8, -+ .shift = 0, -+ .width = 4, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi1_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi1_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ro_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_ubi2_div_clk_src = { -+ .reg = 0x287ac, -+ .shift = 0, -+ .width = 4, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi2_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi2_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ro_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_ubi3_div_clk_src = { -+ .reg = 0x287b0, -+ .shift = 0, -+ .width = 4, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi3_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi3_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ro_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_xgmac0_ptp_ref_div_clk_src = { -+ .reg = 0x28214, -+ .shift = 0, -+ .width = 4, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_xgmac0_ptp_ref_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ro_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_xgmac1_ptp_ref_div_clk_src = { -+ .reg = 0x28218, -+ .shift = 0, -+ .width = 4, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_xgmac1_ptp_ref_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ro_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_xgmac2_ptp_ref_div_clk_src = { -+ .reg = 0x2821c, -+ .shift = 0, -+ .width = 4, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_xgmac2_ptp_ref_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ro_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_xgmac3_ptp_ref_div_clk_src = { -+ .reg = 0x28220, -+ .shift = 0, -+ .width = 4, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_xgmac3_ptp_ref_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ro_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_xgmac4_ptp_ref_div_clk_src = { -+ .reg = 0x28224, -+ .shift = 0, -+ .width = 4, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_xgmac4_ptp_ref_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ro_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_xgmac5_ptp_ref_div_clk_src = { -+ .reg = 0x28228, -+ .shift = 0, -+ .width = 4, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_xgmac5_ptp_ref_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ro_ops, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ce_apb_clk = { -+ .halt_reg = 0x2840c, -+ .clkr = { -+ .enable_reg = 0x2840c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ce_apb_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ce_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ce_axi_clk = { -+ .halt_reg = 0x28410, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28410, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ce_axi_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ce_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_clc_axi_clk = { -+ .halt_reg = 0x2860c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2860c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_clc_axi_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_clc_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_crypto_clk = { -+ .halt_reg = 0x1601c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x1601c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_crypto_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_crypto_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_crypto_ppe_clk = { -+ .halt_reg = 0x28240, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28240, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_crypto_ppe_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_haq_ahb_clk = { -+ .halt_reg = 0x2830c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2830c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_haq_ahb_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_haq_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_haq_axi_clk = { -+ .halt_reg = 0x28310, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28310, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_haq_axi_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_haq_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_imem_ahb_clk = { -+ .halt_reg = 0xe018, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0xe018, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_imem_ahb_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_cfg_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_imem_qsb_clk = { -+ .halt_reg = 0xe010, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0xe010, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_imem_qsb_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_imem_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nss_csr_clk = { -+ .halt_reg = 0x281d0, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x281d0, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nss_csr_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_cfg_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_ce_apb_clk = { -+ .halt_reg = 0x28414, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28414, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_ce_apb_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ce_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_ce_axi_clk = { -+ .halt_reg = 0x28418, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28418, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_ce_axi_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ce_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_clc_axi_clk = { -+ .halt_reg = 0x28610, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28610, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_clc_axi_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_clc_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_crypto_clk = { -+ .halt_reg = 0x16020, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x16020, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_crypto_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_crypto_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_haq_ahb_clk = { -+ .halt_reg = 0x28314, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28314, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_haq_ahb_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_haq_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_haq_axi_clk = { -+ .halt_reg = 0x28318, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28318, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_haq_axi_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_haq_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_imem_ahb_clk = { -+ .halt_reg = 0xe01c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0xe01c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_imem_ahb_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_cfg_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_imem_qsb_clk = { -+ .halt_reg = 0xe014, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0xe014, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_imem_qsb_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_imem_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_nss_csr_clk = { -+ .halt_reg = 0x281d4, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x281d4, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_nss_csr_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_cfg_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_ppe_cfg_clk = { -+ .halt_reg = 0x28248, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28248, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_ppe_cfg_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_ppe_clk = { -+ .halt_reg = 0x28244, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28244, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_ppe_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_ubi32_ahb0_clk = { -+ .halt_reg = 0x28788, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28788, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_ubi32_ahb0_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_cfg_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_ubi32_axi0_clk = { -+ .halt_reg = 0x287a0, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x287a0, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_ubi32_axi0_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi_axi_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_ubi32_int0_ahb_clk = { -+ .halt_reg = 0x2878c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2878c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_ubi32_int0_ahb_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_int_cfg_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_ubi32_nc_axi0_1_clk = { -+ .halt_reg = 0x287bc, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x287bc, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_ubi32_nc_axi0_1_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_ubi32_nc_axi0_clk = { -+ .halt_reg = 0x28764, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28764, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_ubi32_nc_axi0_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port1_mac_clk = { -+ .halt_reg = 0x2824c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2824c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port1_mac_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port1_rx_clk = { -+ .halt_reg = 0x281a0, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x281a0, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port1_rx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port1_rx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port1_tx_clk = { -+ .halt_reg = 0x281a4, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x281a4, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port1_tx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port1_tx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port2_mac_clk = { -+ .halt_reg = 0x28250, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28250, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port2_mac_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port2_rx_clk = { -+ .halt_reg = 0x281a8, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x281a8, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port2_rx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port2_rx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port2_tx_clk = { -+ .halt_reg = 0x281ac, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x281ac, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port2_tx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port2_tx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port3_mac_clk = { -+ .halt_reg = 0x28254, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28254, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port3_mac_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port3_rx_clk = { -+ .halt_reg = 0x281b0, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x281b0, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port3_rx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port3_rx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port3_tx_clk = { -+ .halt_reg = 0x281b4, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x281b4, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port3_tx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port3_tx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port4_mac_clk = { -+ .halt_reg = 0x28258, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28258, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port4_mac_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port4_rx_clk = { -+ .halt_reg = 0x281b8, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x281b8, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port4_rx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port4_rx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port4_tx_clk = { -+ .halt_reg = 0x281bc, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x281bc, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port4_tx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port4_tx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port5_mac_clk = { -+ .halt_reg = 0x2825c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2825c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port5_mac_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port5_rx_clk = { -+ .halt_reg = 0x281c0, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x281c0, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port5_rx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port5_rx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port5_tx_clk = { -+ .halt_reg = 0x281c4, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x281c4, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port5_tx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port5_tx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port6_mac_clk = { -+ .halt_reg = 0x28260, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28260, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port6_mac_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port6_rx_clk = { -+ .halt_reg = 0x281c8, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x281c8, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port6_rx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port6_rx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port6_tx_clk = { -+ .halt_reg = 0x281cc, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x281cc, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port6_tx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port6_tx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ppe_edma_cfg_clk = { -+ .halt_reg = 0x2823c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2823c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ppe_edma_cfg_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ppe_edma_clk = { -+ .halt_reg = 0x28238, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28238, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ppe_edma_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ppe_switch_btq_clk = { -+ .halt_reg = 0x2827c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2827c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ppe_switch_btq_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ppe_switch_cfg_clk = { -+ .halt_reg = 0x28234, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28234, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ppe_switch_cfg_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ppe_switch_clk = { -+ .halt_reg = 0x28230, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28230, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ppe_switch_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ppe_switch_ipe_clk = { -+ .halt_reg = 0x2822c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2822c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ppe_switch_ipe_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_ahb0_clk = { -+ .halt_reg = 0x28768, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28768, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_ahb0_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_cfg_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_ahb1_clk = { -+ .halt_reg = 0x28770, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28770, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_ahb1_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_cfg_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_ahb2_clk = { -+ .halt_reg = 0x28778, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28778, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_ahb2_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_cfg_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_ahb3_clk = { -+ .halt_reg = 0x28780, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28780, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_ahb3_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_cfg_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_axi0_clk = { -+ .halt_reg = 0x28790, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28790, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_axi0_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi_axi_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_axi1_clk = { -+ .halt_reg = 0x28794, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28794, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_axi1_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi_axi_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_axi2_clk = { -+ .halt_reg = 0x28798, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28798, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_axi2_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi_axi_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_axi3_clk = { -+ .halt_reg = 0x2879c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2879c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_axi3_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi_axi_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_core0_clk = { -+ .halt_reg = 0x28734, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28734, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_core0_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi0_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_core1_clk = { -+ .halt_reg = 0x28738, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28738, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_core1_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi1_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_core2_clk = { -+ .halt_reg = 0x2873c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2873c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_core2_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi2_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_core3_clk = { -+ .halt_reg = 0x28740, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28740, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_core3_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi3_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_intr0_ahb_clk = { -+ .halt_reg = 0x2876c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2876c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_intr0_ahb_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_int_cfg_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_intr1_ahb_clk = { -+ .halt_reg = 0x28774, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28774, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_intr1_ahb_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_int_cfg_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_intr2_ahb_clk = { -+ .halt_reg = 0x2877c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2877c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_intr2_ahb_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_int_cfg_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_intr3_ahb_clk = { -+ .halt_reg = 0x28784, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28784, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_intr3_ahb_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_int_cfg_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_nc_axi0_clk = { -+ .halt_reg = 0x28744, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28744, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_nc_axi0_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_nc_axi1_clk = { -+ .halt_reg = 0x2874c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2874c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_nc_axi1_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_nc_axi2_clk = { -+ .halt_reg = 0x28754, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28754, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_nc_axi2_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_nc_axi3_clk = { -+ .halt_reg = 0x2875c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2875c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_nc_axi3_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_utcm0_clk = { -+ .halt_reg = 0x28748, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28748, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_utcm0_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_utcm1_clk = { -+ .halt_reg = 0x28750, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28750, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_utcm1_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_utcm2_clk = { -+ .halt_reg = 0x28758, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28758, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_utcm2_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_utcm3_clk = { -+ .halt_reg = 0x28760, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28760, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_utcm3_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_uniphy_port1_rx_clk = { -+ .halt_reg = 0x28904, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28904, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_uniphy_port1_rx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port1_rx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_uniphy_port1_tx_clk = { -+ .halt_reg = 0x28908, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28908, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_uniphy_port1_tx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port1_tx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_uniphy_port2_rx_clk = { -+ .halt_reg = 0x2890c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2890c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_uniphy_port2_rx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port2_rx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_uniphy_port2_tx_clk = { -+ .halt_reg = 0x28910, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28910, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_uniphy_port2_tx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port2_tx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_uniphy_port3_rx_clk = { -+ .halt_reg = 0x28914, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28914, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_uniphy_port3_rx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port3_rx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_uniphy_port3_tx_clk = { -+ .halt_reg = 0x28918, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28918, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_uniphy_port3_tx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port3_tx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_uniphy_port4_rx_clk = { -+ .halt_reg = 0x2891c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2891c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_uniphy_port4_rx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port4_rx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_uniphy_port4_tx_clk = { -+ .halt_reg = 0x28920, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28920, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_uniphy_port4_tx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port4_tx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_uniphy_port5_rx_clk = { -+ .halt_reg = 0x28924, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28924, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_uniphy_port5_rx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port5_rx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_uniphy_port5_tx_clk = { -+ .halt_reg = 0x28928, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28928, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_uniphy_port5_tx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port5_tx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_uniphy_port6_rx_clk = { -+ .halt_reg = 0x2892c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2892c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_uniphy_port6_rx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port6_rx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_uniphy_port6_tx_clk = { -+ .halt_reg = 0x28930, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28930, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_uniphy_port6_tx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port6_tx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_xgmac0_ptp_ref_clk = { -+ .halt_reg = 0x28264, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28264, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_xgmac0_ptp_ref_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_xgmac0_ptp_ref_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_xgmac1_ptp_ref_clk = { -+ .halt_reg = 0x28268, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28268, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_xgmac1_ptp_ref_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_xgmac1_ptp_ref_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_xgmac2_ptp_ref_clk = { -+ .halt_reg = 0x2826c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2826c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_xgmac2_ptp_ref_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_xgmac2_ptp_ref_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_xgmac3_ptp_ref_clk = { -+ .halt_reg = 0x28270, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28270, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_xgmac3_ptp_ref_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_xgmac3_ptp_ref_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_xgmac4_ptp_ref_clk = { -+ .halt_reg = 0x28274, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28274, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_xgmac4_ptp_ref_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_xgmac4_ptp_ref_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_xgmac5_ptp_ref_clk = { -+ .halt_reg = 0x28278, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28278, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_xgmac5_ptp_ref_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_xgmac5_ptp_ref_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_regmap *nss_cc_ipq9574_clocks[] = { -+ [NSS_CC_CE_APB_CLK] = &nss_cc_ce_apb_clk.clkr, -+ [NSS_CC_CE_AXI_CLK] = &nss_cc_ce_axi_clk.clkr, -+ [NSS_CC_CE_CLK_SRC] = &nss_cc_ce_clk_src.clkr, -+ [NSS_CC_CFG_CLK_SRC] = &nss_cc_cfg_clk_src.clkr, -+ [NSS_CC_CLC_AXI_CLK] = &nss_cc_clc_axi_clk.clkr, -+ [NSS_CC_CLC_CLK_SRC] = &nss_cc_clc_clk_src.clkr, -+ [NSS_CC_CRYPTO_CLK] = &nss_cc_crypto_clk.clkr, -+ [NSS_CC_CRYPTO_CLK_SRC] = &nss_cc_crypto_clk_src.clkr, -+ [NSS_CC_CRYPTO_PPE_CLK] = &nss_cc_crypto_ppe_clk.clkr, -+ [NSS_CC_HAQ_AHB_CLK] = &nss_cc_haq_ahb_clk.clkr, -+ [NSS_CC_HAQ_AXI_CLK] = &nss_cc_haq_axi_clk.clkr, -+ [NSS_CC_HAQ_CLK_SRC] = &nss_cc_haq_clk_src.clkr, -+ [NSS_CC_IMEM_AHB_CLK] = &nss_cc_imem_ahb_clk.clkr, -+ [NSS_CC_IMEM_CLK_SRC] = &nss_cc_imem_clk_src.clkr, -+ [NSS_CC_IMEM_QSB_CLK] = &nss_cc_imem_qsb_clk.clkr, -+ [NSS_CC_INT_CFG_CLK_SRC] = &nss_cc_int_cfg_clk_src.clkr, -+ [NSS_CC_NSS_CSR_CLK] = &nss_cc_nss_csr_clk.clkr, -+ [NSS_CC_NSSNOC_CE_APB_CLK] = &nss_cc_nssnoc_ce_apb_clk.clkr, -+ [NSS_CC_NSSNOC_CE_AXI_CLK] = &nss_cc_nssnoc_ce_axi_clk.clkr, -+ [NSS_CC_NSSNOC_CLC_AXI_CLK] = &nss_cc_nssnoc_clc_axi_clk.clkr, -+ [NSS_CC_NSSNOC_CRYPTO_CLK] = &nss_cc_nssnoc_crypto_clk.clkr, -+ [NSS_CC_NSSNOC_HAQ_AHB_CLK] = &nss_cc_nssnoc_haq_ahb_clk.clkr, -+ [NSS_CC_NSSNOC_HAQ_AXI_CLK] = &nss_cc_nssnoc_haq_axi_clk.clkr, -+ [NSS_CC_NSSNOC_IMEM_AHB_CLK] = &nss_cc_nssnoc_imem_ahb_clk.clkr, -+ [NSS_CC_NSSNOC_IMEM_QSB_CLK] = &nss_cc_nssnoc_imem_qsb_clk.clkr, -+ [NSS_CC_NSSNOC_NSS_CSR_CLK] = &nss_cc_nssnoc_nss_csr_clk.clkr, -+ [NSS_CC_NSSNOC_PPE_CFG_CLK] = &nss_cc_nssnoc_ppe_cfg_clk.clkr, -+ [NSS_CC_NSSNOC_PPE_CLK] = &nss_cc_nssnoc_ppe_clk.clkr, -+ [NSS_CC_NSSNOC_UBI32_AHB0_CLK] = &nss_cc_nssnoc_ubi32_ahb0_clk.clkr, -+ [NSS_CC_NSSNOC_UBI32_AXI0_CLK] = &nss_cc_nssnoc_ubi32_axi0_clk.clkr, -+ [NSS_CC_NSSNOC_UBI32_INT0_AHB_CLK] = -+ &nss_cc_nssnoc_ubi32_int0_ahb_clk.clkr, -+ [NSS_CC_NSSNOC_UBI32_NC_AXI0_1_CLK] = -+ &nss_cc_nssnoc_ubi32_nc_axi0_1_clk.clkr, -+ [NSS_CC_NSSNOC_UBI32_NC_AXI0_CLK] = -+ &nss_cc_nssnoc_ubi32_nc_axi0_clk.clkr, -+ [NSS_CC_PORT1_MAC_CLK] = &nss_cc_port1_mac_clk.clkr, -+ [NSS_CC_PORT1_RX_CLK] = &nss_cc_port1_rx_clk.clkr, -+ [NSS_CC_PORT1_RX_CLK_SRC] = &nss_cc_port1_rx_clk_src.clkr, -+ [NSS_CC_PORT1_RX_DIV_CLK_SRC] = &nss_cc_port1_rx_div_clk_src.clkr, -+ [NSS_CC_PORT1_TX_CLK] = &nss_cc_port1_tx_clk.clkr, -+ [NSS_CC_PORT1_TX_CLK_SRC] = &nss_cc_port1_tx_clk_src.clkr, -+ [NSS_CC_PORT1_TX_DIV_CLK_SRC] = &nss_cc_port1_tx_div_clk_src.clkr, -+ [NSS_CC_PORT2_MAC_CLK] = &nss_cc_port2_mac_clk.clkr, -+ [NSS_CC_PORT2_RX_CLK] = &nss_cc_port2_rx_clk.clkr, -+ [NSS_CC_PORT2_RX_CLK_SRC] = &nss_cc_port2_rx_clk_src.clkr, -+ [NSS_CC_PORT2_RX_DIV_CLK_SRC] = &nss_cc_port2_rx_div_clk_src.clkr, -+ [NSS_CC_PORT2_TX_CLK] = &nss_cc_port2_tx_clk.clkr, -+ [NSS_CC_PORT2_TX_CLK_SRC] = &nss_cc_port2_tx_clk_src.clkr, -+ [NSS_CC_PORT2_TX_DIV_CLK_SRC] = &nss_cc_port2_tx_div_clk_src.clkr, -+ [NSS_CC_PORT3_MAC_CLK] = &nss_cc_port3_mac_clk.clkr, -+ [NSS_CC_PORT3_RX_CLK] = &nss_cc_port3_rx_clk.clkr, -+ [NSS_CC_PORT3_RX_CLK_SRC] = &nss_cc_port3_rx_clk_src.clkr, -+ [NSS_CC_PORT3_RX_DIV_CLK_SRC] = &nss_cc_port3_rx_div_clk_src.clkr, -+ [NSS_CC_PORT3_TX_CLK] = &nss_cc_port3_tx_clk.clkr, -+ [NSS_CC_PORT3_TX_CLK_SRC] = &nss_cc_port3_tx_clk_src.clkr, -+ [NSS_CC_PORT3_TX_DIV_CLK_SRC] = &nss_cc_port3_tx_div_clk_src.clkr, -+ [NSS_CC_PORT4_MAC_CLK] = &nss_cc_port4_mac_clk.clkr, -+ [NSS_CC_PORT4_RX_CLK] = &nss_cc_port4_rx_clk.clkr, -+ [NSS_CC_PORT4_RX_CLK_SRC] = &nss_cc_port4_rx_clk_src.clkr, -+ [NSS_CC_PORT4_RX_DIV_CLK_SRC] = &nss_cc_port4_rx_div_clk_src.clkr, -+ [NSS_CC_PORT4_TX_CLK] = &nss_cc_port4_tx_clk.clkr, -+ [NSS_CC_PORT4_TX_CLK_SRC] = &nss_cc_port4_tx_clk_src.clkr, -+ [NSS_CC_PORT4_TX_DIV_CLK_SRC] = &nss_cc_port4_tx_div_clk_src.clkr, -+ [NSS_CC_PORT5_MAC_CLK] = &nss_cc_port5_mac_clk.clkr, -+ [NSS_CC_PORT5_RX_CLK] = &nss_cc_port5_rx_clk.clkr, -+ [NSS_CC_PORT5_RX_CLK_SRC] = &nss_cc_port5_rx_clk_src.clkr, -+ [NSS_CC_PORT5_RX_DIV_CLK_SRC] = &nss_cc_port5_rx_div_clk_src.clkr, -+ [NSS_CC_PORT5_TX_CLK] = &nss_cc_port5_tx_clk.clkr, -+ [NSS_CC_PORT5_TX_CLK_SRC] = &nss_cc_port5_tx_clk_src.clkr, -+ [NSS_CC_PORT5_TX_DIV_CLK_SRC] = &nss_cc_port5_tx_div_clk_src.clkr, -+ [NSS_CC_PORT6_MAC_CLK] = &nss_cc_port6_mac_clk.clkr, -+ [NSS_CC_PORT6_RX_CLK] = &nss_cc_port6_rx_clk.clkr, -+ [NSS_CC_PORT6_RX_CLK_SRC] = &nss_cc_port6_rx_clk_src.clkr, -+ [NSS_CC_PORT6_RX_DIV_CLK_SRC] = &nss_cc_port6_rx_div_clk_src.clkr, -+ [NSS_CC_PORT6_TX_CLK] = &nss_cc_port6_tx_clk.clkr, -+ [NSS_CC_PORT6_TX_CLK_SRC] = &nss_cc_port6_tx_clk_src.clkr, -+ [NSS_CC_PORT6_TX_DIV_CLK_SRC] = &nss_cc_port6_tx_div_clk_src.clkr, -+ [NSS_CC_PPE_CLK_SRC] = &nss_cc_ppe_clk_src.clkr, -+ [NSS_CC_PPE_EDMA_CFG_CLK] = &nss_cc_ppe_edma_cfg_clk.clkr, -+ [NSS_CC_PPE_EDMA_CLK] = &nss_cc_ppe_edma_clk.clkr, -+ [NSS_CC_PPE_SWITCH_BTQ_CLK] = &nss_cc_ppe_switch_btq_clk.clkr, -+ [NSS_CC_PPE_SWITCH_CFG_CLK] = &nss_cc_ppe_switch_cfg_clk.clkr, -+ [NSS_CC_PPE_SWITCH_CLK] = &nss_cc_ppe_switch_clk.clkr, -+ [NSS_CC_PPE_SWITCH_IPE_CLK] = &nss_cc_ppe_switch_ipe_clk.clkr, -+ [NSS_CC_UBI0_CLK_SRC] = &nss_cc_ubi0_clk_src.clkr, -+ [NSS_CC_UBI0_DIV_CLK_SRC] = &nss_cc_ubi0_div_clk_src.clkr, -+ [NSS_CC_UBI1_CLK_SRC] = &nss_cc_ubi1_clk_src.clkr, -+ [NSS_CC_UBI1_DIV_CLK_SRC] = &nss_cc_ubi1_div_clk_src.clkr, -+ [NSS_CC_UBI2_CLK_SRC] = &nss_cc_ubi2_clk_src.clkr, -+ [NSS_CC_UBI2_DIV_CLK_SRC] = &nss_cc_ubi2_div_clk_src.clkr, -+ [NSS_CC_UBI32_AHB0_CLK] = &nss_cc_ubi32_ahb0_clk.clkr, -+ [NSS_CC_UBI32_AHB1_CLK] = &nss_cc_ubi32_ahb1_clk.clkr, -+ [NSS_CC_UBI32_AHB2_CLK] = &nss_cc_ubi32_ahb2_clk.clkr, -+ [NSS_CC_UBI32_AHB3_CLK] = &nss_cc_ubi32_ahb3_clk.clkr, -+ [NSS_CC_UBI32_AXI0_CLK] = &nss_cc_ubi32_axi0_clk.clkr, -+ [NSS_CC_UBI32_AXI1_CLK] = &nss_cc_ubi32_axi1_clk.clkr, -+ [NSS_CC_UBI32_AXI2_CLK] = &nss_cc_ubi32_axi2_clk.clkr, -+ [NSS_CC_UBI32_AXI3_CLK] = &nss_cc_ubi32_axi3_clk.clkr, -+ [NSS_CC_UBI32_CORE0_CLK] = &nss_cc_ubi32_core0_clk.clkr, -+ [NSS_CC_UBI32_CORE1_CLK] = &nss_cc_ubi32_core1_clk.clkr, -+ [NSS_CC_UBI32_CORE2_CLK] = &nss_cc_ubi32_core2_clk.clkr, -+ [NSS_CC_UBI32_CORE3_CLK] = &nss_cc_ubi32_core3_clk.clkr, -+ [NSS_CC_UBI32_INTR0_AHB_CLK] = &nss_cc_ubi32_intr0_ahb_clk.clkr, -+ [NSS_CC_UBI32_INTR1_AHB_CLK] = &nss_cc_ubi32_intr1_ahb_clk.clkr, -+ [NSS_CC_UBI32_INTR2_AHB_CLK] = &nss_cc_ubi32_intr2_ahb_clk.clkr, -+ [NSS_CC_UBI32_INTR3_AHB_CLK] = &nss_cc_ubi32_intr3_ahb_clk.clkr, -+ [NSS_CC_UBI32_NC_AXI0_CLK] = &nss_cc_ubi32_nc_axi0_clk.clkr, -+ [NSS_CC_UBI32_NC_AXI1_CLK] = &nss_cc_ubi32_nc_axi1_clk.clkr, -+ [NSS_CC_UBI32_NC_AXI2_CLK] = &nss_cc_ubi32_nc_axi2_clk.clkr, -+ [NSS_CC_UBI32_NC_AXI3_CLK] = &nss_cc_ubi32_nc_axi3_clk.clkr, -+ [NSS_CC_UBI32_UTCM0_CLK] = &nss_cc_ubi32_utcm0_clk.clkr, -+ [NSS_CC_UBI32_UTCM1_CLK] = &nss_cc_ubi32_utcm1_clk.clkr, -+ [NSS_CC_UBI32_UTCM2_CLK] = &nss_cc_ubi32_utcm2_clk.clkr, -+ [NSS_CC_UBI32_UTCM3_CLK] = &nss_cc_ubi32_utcm3_clk.clkr, -+ [NSS_CC_UBI3_CLK_SRC] = &nss_cc_ubi3_clk_src.clkr, -+ [NSS_CC_UBI3_DIV_CLK_SRC] = &nss_cc_ubi3_div_clk_src.clkr, -+ [NSS_CC_UBI_AXI_CLK_SRC] = &nss_cc_ubi_axi_clk_src.clkr, -+ [NSS_CC_UBI_NC_AXI_BFDCD_CLK_SRC] = -+ &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr, -+ [NSS_CC_UNIPHY_PORT1_RX_CLK] = &nss_cc_uniphy_port1_rx_clk.clkr, -+ [NSS_CC_UNIPHY_PORT1_TX_CLK] = &nss_cc_uniphy_port1_tx_clk.clkr, -+ [NSS_CC_UNIPHY_PORT2_RX_CLK] = &nss_cc_uniphy_port2_rx_clk.clkr, -+ [NSS_CC_UNIPHY_PORT2_TX_CLK] = &nss_cc_uniphy_port2_tx_clk.clkr, -+ [NSS_CC_UNIPHY_PORT3_RX_CLK] = &nss_cc_uniphy_port3_rx_clk.clkr, -+ [NSS_CC_UNIPHY_PORT3_TX_CLK] = &nss_cc_uniphy_port3_tx_clk.clkr, -+ [NSS_CC_UNIPHY_PORT4_RX_CLK] = &nss_cc_uniphy_port4_rx_clk.clkr, -+ [NSS_CC_UNIPHY_PORT4_TX_CLK] = &nss_cc_uniphy_port4_tx_clk.clkr, -+ [NSS_CC_UNIPHY_PORT5_RX_CLK] = &nss_cc_uniphy_port5_rx_clk.clkr, -+ [NSS_CC_UNIPHY_PORT5_TX_CLK] = &nss_cc_uniphy_port5_tx_clk.clkr, -+ [NSS_CC_UNIPHY_PORT6_RX_CLK] = &nss_cc_uniphy_port6_rx_clk.clkr, -+ [NSS_CC_UNIPHY_PORT6_TX_CLK] = &nss_cc_uniphy_port6_tx_clk.clkr, -+ [NSS_CC_XGMAC0_PTP_REF_CLK] = &nss_cc_xgmac0_ptp_ref_clk.clkr, -+ [NSS_CC_XGMAC0_PTP_REF_DIV_CLK_SRC] = -+ &nss_cc_xgmac0_ptp_ref_div_clk_src.clkr, -+ [NSS_CC_XGMAC1_PTP_REF_CLK] = &nss_cc_xgmac1_ptp_ref_clk.clkr, -+ [NSS_CC_XGMAC1_PTP_REF_DIV_CLK_SRC] = -+ &nss_cc_xgmac1_ptp_ref_div_clk_src.clkr, -+ [NSS_CC_XGMAC2_PTP_REF_CLK] = &nss_cc_xgmac2_ptp_ref_clk.clkr, -+ [NSS_CC_XGMAC2_PTP_REF_DIV_CLK_SRC] = -+ &nss_cc_xgmac2_ptp_ref_div_clk_src.clkr, -+ [NSS_CC_XGMAC3_PTP_REF_CLK] = &nss_cc_xgmac3_ptp_ref_clk.clkr, -+ [NSS_CC_XGMAC3_PTP_REF_DIV_CLK_SRC] = -+ &nss_cc_xgmac3_ptp_ref_div_clk_src.clkr, -+ [NSS_CC_XGMAC4_PTP_REF_CLK] = &nss_cc_xgmac4_ptp_ref_clk.clkr, -+ [NSS_CC_XGMAC4_PTP_REF_DIV_CLK_SRC] = -+ &nss_cc_xgmac4_ptp_ref_div_clk_src.clkr, -+ [NSS_CC_XGMAC5_PTP_REF_CLK] = &nss_cc_xgmac5_ptp_ref_clk.clkr, -+ [NSS_CC_XGMAC5_PTP_REF_DIV_CLK_SRC] = -+ &nss_cc_xgmac5_ptp_ref_div_clk_src.clkr, -+ [UBI32_PLL] = &ubi32_pll.clkr, -+ [UBI32_PLL_MAIN] = &ubi32_pll_main.clkr, -+}; -+ -+static const struct qcom_reset_map nss_cc_ipq9574_resets[] = { -+ [NSS_CC_CE_BCR] = { 0x28400, 0 }, -+ [NSS_CC_CLC_BCR] = { 0x28600, 0 }, -+ [NSS_CC_EIP197_BCR] = { 0x16004, 0 }, -+ [NSS_CC_HAQ_BCR] = { 0x28300, 0 }, -+ [NSS_CC_IMEM_BCR] = { 0xe004, 0 }, -+ [NSS_CC_MAC_BCR] = { 0x28100, 0 }, -+ [NSS_CC_PPE_BCR] = { 0x28200, 0 }, -+ [NSS_CC_UBI_BCR] = { 0x28700, 0 }, -+ [NSS_CC_UNIPHY_BCR] = { 0x28900, 0 }, -+ [UBI3_CLKRST_CLAMP_ENABLE] = { 0x28a04, 9 }, -+ [UBI3_CORE_CLAMP_ENABLE] = { 0x28a04, 8 }, -+ [UBI2_CLKRST_CLAMP_ENABLE] = { 0x28a04, 7 }, -+ [UBI2_CORE_CLAMP_ENABLE] = { 0x28a04, 6 }, -+ [UBI1_CLKRST_CLAMP_ENABLE] = { 0x28a04, 5 }, -+ [UBI1_CORE_CLAMP_ENABLE] = { 0x28a04, 4 }, -+ [UBI0_CLKRST_CLAMP_ENABLE] = { 0x28a04, 3 }, -+ [UBI0_CORE_CLAMP_ENABLE] = { 0x28a04, 2 }, -+ [NSSNOC_NSS_CSR_ARES] = { 0x28a04, 1 }, -+ [NSS_CSR_ARES] = { 0x28a04, 0 }, -+ [PPE_BTQ_ARES] = { 0x28a08, 20 }, -+ [PPE_IPE_ARES] = { 0x28a08, 19 }, -+ [PPE_ARES] = { 0x28a08, 18 }, -+ [PPE_CFG_ARES] = { 0x28a08, 17 }, -+ [PPE_EDMA_ARES] = { 0x28a08, 16 }, -+ [PPE_EDMA_CFG_ARES] = { 0x28a08, 15 }, -+ [CRY_PPE_ARES] = { 0x28a08, 14 }, -+ [NSSNOC_PPE_ARES] = { 0x28a08, 13 }, -+ [NSSNOC_PPE_CFG_ARES] = { 0x28a08, 12 }, -+ [PORT1_MAC_ARES] = { 0x28a08, 11 }, -+ [PORT2_MAC_ARES] = { 0x28a08, 10 }, -+ [PORT3_MAC_ARES] = { 0x28a08, 9 }, -+ [PORT4_MAC_ARES] = { 0x28a08, 8 }, -+ [PORT5_MAC_ARES] = { 0x28a08, 7 }, -+ [PORT6_MAC_ARES] = { 0x28a08, 6 }, -+ [XGMAC0_PTP_REF_ARES] = { 0x28a08, 5 }, -+ [XGMAC1_PTP_REF_ARES] = { 0x28a08, 4 }, -+ [XGMAC2_PTP_REF_ARES] = { 0x28a08, 3 }, -+ [XGMAC3_PTP_REF_ARES] = { 0x28a08, 2 }, -+ [XGMAC4_PTP_REF_ARES] = { 0x28a08, 1 }, -+ [XGMAC5_PTP_REF_ARES] = { 0x28a08, 0 }, -+ [HAQ_AHB_ARES] = { 0x28a0c, 3 }, -+ [HAQ_AXI_ARES] = { 0x28a0c, 2 }, -+ [NSSNOC_HAQ_AHB_ARES] = { 0x28a0c, 1 }, -+ [NSSNOC_HAQ_AXI_ARES] = { 0x28a0c, 0 }, -+ [CE_APB_ARES] = { 0x28a10, 3 }, -+ [CE_AXI_ARES] = { 0x28a10, 2 }, -+ [NSSNOC_CE_APB_ARES] = { 0x28a10, 1 }, -+ [NSSNOC_CE_AXI_ARES] = { 0x28a10, 0 }, -+ [CRYPTO_ARES] = { 0x28a14, 1 }, -+ [NSSNOC_CRYPTO_ARES] = { 0x28a14, 0 }, -+ [NSSNOC_NC_AXI0_1_ARES] = { 0x28a1c, 28 }, -+ [UBI0_CORE_ARES] = { 0x28a1c, 27 }, -+ [UBI1_CORE_ARES] = { 0x28a1c, 26 }, -+ [UBI2_CORE_ARES] = { 0x28a1c, 25 }, -+ [UBI3_CORE_ARES] = { 0x28a1c, 24 }, -+ [NC_AXI0_ARES] = { 0x28a1c, 23 }, -+ [UTCM0_ARES] = { 0x28a1c, 22 }, -+ [NC_AXI1_ARES] = { 0x28a1c, 21 }, -+ [UTCM1_ARES] = { 0x28a1c, 20 }, -+ [NC_AXI2_ARES] = { 0x28a1c, 19 }, -+ [UTCM2_ARES] = { 0x28a1c, 18 }, -+ [NC_AXI3_ARES] = { 0x28a1c, 17 }, -+ [UTCM3_ARES] = { 0x28a1c, 16 }, -+ [NSSNOC_NC_AXI0_ARES] = { 0x28a1c, 15 }, -+ [AHB0_ARES] = { 0x28a1c, 14 }, -+ [INTR0_AHB_ARES] = { 0x28a1c, 13 }, -+ [AHB1_ARES] = { 0x28a1c, 12 }, -+ [INTR1_AHB_ARES] = { 0x28a1c, 11 }, -+ [AHB2_ARES] = { 0x28a1c, 10 }, -+ [INTR2_AHB_ARES] = { 0x28a1c, 9 }, -+ [AHB3_ARES] = { 0x28a1c, 8 }, -+ [INTR3_AHB_ARES] = { 0x28a1c, 7 }, -+ [NSSNOC_AHB0_ARES] = { 0x28a1c, 6 }, -+ [NSSNOC_INT0_AHB_ARES] = { 0x28a1c, 5 }, -+ [AXI0_ARES] = { 0x28a1c, 4 }, -+ [AXI1_ARES] = { 0x28a1c, 3 }, -+ [AXI2_ARES] = { 0x28a1c, 2 }, -+ [AXI3_ARES] = { 0x28a1c, 1 }, -+ [NSSNOC_AXI0_ARES] = { 0x28a1c, 0 }, -+ [IMEM_QSB_ARES] = { 0x28a20, 3 }, -+ [NSSNOC_IMEM_QSB_ARES] = { 0x28a20, 2 }, -+ [IMEM_AHB_ARES] = { 0x28a20, 1 }, -+ [NSSNOC_IMEM_AHB_ARES] = { 0x28a20, 0 }, -+ [UNIPHY_PORT1_RX_ARES] = { 0x28a24, 23 }, -+ [UNIPHY_PORT1_TX_ARES] = { 0x28a24, 22 }, -+ [UNIPHY_PORT2_RX_ARES] = { 0x28a24, 21 }, -+ [UNIPHY_PORT2_TX_ARES] = { 0x28a24, 20 }, -+ [UNIPHY_PORT3_RX_ARES] = { 0x28a24, 19 }, -+ [UNIPHY_PORT3_TX_ARES] = { 0x28a24, 18 }, -+ [UNIPHY_PORT4_RX_ARES] = { 0x28a24, 17 }, -+ [UNIPHY_PORT4_TX_ARES] = { 0x28a24, 16 }, -+ [UNIPHY_PORT5_RX_ARES] = { 0x28a24, 15 }, -+ [UNIPHY_PORT5_TX_ARES] = { 0x28a24, 14 }, -+ [UNIPHY_PORT6_RX_ARES] = { 0x28a24, 13 }, -+ [UNIPHY_PORT6_TX_ARES] = { 0x28a24, 12 }, -+ [PORT1_RX_ARES] = { 0x28a24, 11 }, -+ [PORT1_TX_ARES] = { 0x28a24, 10 }, -+ [PORT2_RX_ARES] = { 0x28a24, 9 }, -+ [PORT2_TX_ARES] = { 0x28a24, 8 }, -+ [PORT3_RX_ARES] = { 0x28a24, 7 }, -+ [PORT3_TX_ARES] = { 0x28a24, 6 }, -+ [PORT4_RX_ARES] = { 0x28a24, 5 }, -+ [PORT4_TX_ARES] = { 0x28a24, 4 }, -+ [PORT5_RX_ARES] = { 0x28a24, 3 }, -+ [PORT5_TX_ARES] = { 0x28a24, 2 }, -+ [PORT6_RX_ARES] = { 0x28a24, 1 }, -+ [PORT6_TX_ARES] = { 0x28a24, 0 }, -+ [PPE_FULL_RESET] = { .reg = 0x28a08, .bitmask = GENMASK(20, 17) }, -+ [UNIPHY0_SOFT_RESET] = { .reg = 0x28a24, .bitmask = GENMASK(23, 14) }, -+ [UNIPHY1_SOFT_RESET] = { .reg = 0x28a24, .bitmask = GENMASK(15, 14) }, -+ [UNIPHY2_SOFT_RESET] = { .reg = 0x28a24, .bitmask = GENMASK(13, 12) }, -+ [UNIPHY_PORT1_ARES] = { .reg = 0x28a24, .bitmask = GENMASK(23, 22) }, -+ [UNIPHY_PORT2_ARES] = { .reg = 0x28a24, .bitmask = GENMASK(21, 20) }, -+ [UNIPHY_PORT3_ARES] = { .reg = 0x28a24, .bitmask = GENMASK(19, 18) }, -+ [UNIPHY_PORT4_ARES] = { .reg = 0x28a24, .bitmask = GENMASK(17, 16) }, -+ [UNIPHY_PORT5_ARES] = { .reg = 0x28a24, .bitmask = GENMASK(15, 14) }, -+ [UNIPHY_PORT6_ARES] = { .reg = 0x28a24, .bitmask = GENMASK(13, 12) }, -+ [NSSPORT1_RESET] = { .reg = 0x28a24, .bitmask = GENMASK(11, 10) }, -+ [NSSPORT2_RESET] = { .reg = 0x28a24, .bitmask = GENMASK(9, 8) }, -+ [NSSPORT3_RESET] = { .reg = 0x28a24, .bitmask = GENMASK(7, 6) }, -+ [NSSPORT4_RESET] = { .reg = 0x28a24, .bitmask = GENMASK(5, 4) }, -+ [NSSPORT5_RESET] = { .reg = 0x28a24, .bitmask = GENMASK(3, 2) }, -+ [NSSPORT6_RESET] = { .reg = 0x28a24, .bitmask = GENMASK(1, 0) }, -+ [EDMA_HW_RESET] = { .reg = 0x28a08, .bitmask = GENMASK(16, 15) }, -+}; -+ -+static const struct regmap_config nss_cc_ipq9574_regmap_config = { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .max_register = 0x28a34, -+ .fast_io = true, -+}; -+ -+static struct qcom_icc_hws_data icc_ipq9574_nss_hws[] = { -+ { MASTER_NSSNOC_PPE, SLAVE_NSSNOC_PPE, NSS_CC_NSSNOC_PPE_CLK }, -+ { MASTER_NSSNOC_PPE_CFG, SLAVE_NSSNOC_PPE_CFG, NSS_CC_NSSNOC_PPE_CFG_CLK }, -+ { MASTER_NSSNOC_NSS_CSR, SLAVE_NSSNOC_NSS_CSR, NSS_CC_NSSNOC_NSS_CSR_CLK }, -+ { MASTER_NSSNOC_IMEM_QSB, SLAVE_NSSNOC_IMEM_QSB, NSS_CC_NSSNOC_IMEM_QSB_CLK }, -+ { MASTER_NSSNOC_IMEM_AHB, SLAVE_NSSNOC_IMEM_AHB, NSS_CC_NSSNOC_IMEM_AHB_CLK }, -+}; -+ -+#define IPQ_NSSCC_ID (9574 * 2) /* some unique value */ -+ -+static const struct qcom_cc_desc nss_cc_ipq9574_desc = { -+ .config = &nss_cc_ipq9574_regmap_config, -+ .clks = nss_cc_ipq9574_clocks, -+ .num_clks = ARRAY_SIZE(nss_cc_ipq9574_clocks), -+ .resets = nss_cc_ipq9574_resets, -+ .num_resets = ARRAY_SIZE(nss_cc_ipq9574_resets), -+ .icc_hws = icc_ipq9574_nss_hws, -+ .num_icc_hws = ARRAY_SIZE(icc_ipq9574_nss_hws), -+ .icc_first_node_id = IPQ_NSSCC_ID, -+}; -+ -+static const struct dev_pm_ops nss_cc_ipq9574_pm_ops = { -+ SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL) -+}; -+ -+static const struct of_device_id nss_cc_ipq9574_match_table[] = { -+ { .compatible = "qcom,ipq9574-nsscc" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, nss_cc_ipq9574_match_table); -+ -+static int nss_cc_ipq9574_probe(struct platform_device *pdev) -+{ -+ struct regmap *regmap; -+ int ret; -+ -+ ret = devm_pm_runtime_enable(&pdev->dev); -+ if (ret) -+ return dev_err_probe(&pdev->dev, ret, "Fail to enable runtime PM\n"); -+ -+ ret = devm_pm_clk_create(&pdev->dev); -+ if (ret) -+ return dev_err_probe(&pdev->dev, ret, "Fail to create PM clock\n"); -+ -+ ret = pm_clk_add(&pdev->dev, "bus"); -+ if (ret) -+ return dev_err_probe(&pdev->dev, ret, "Fail to add bus clock\n"); -+ -+ ret = pm_runtime_resume_and_get(&pdev->dev); -+ if (ret) -+ return dev_err_probe(&pdev->dev, ret, "Fail to resume\n"); -+ -+ regmap = qcom_cc_map(pdev, &nss_cc_ipq9574_desc); -+ if (IS_ERR(regmap)) { -+ pm_runtime_put(&pdev->dev); -+ return dev_err_probe(&pdev->dev, PTR_ERR(regmap), -+ "Fail to map clock controller registers\n"); -+ } -+ -+ clk_alpha_pll_configure(&ubi32_pll_main, regmap, &ubi32_pll_config); -+ -+ ret = qcom_cc_really_probe(&pdev->dev, &nss_cc_ipq9574_desc, regmap); -+ pm_runtime_put(&pdev->dev); -+ -+ return ret; -+} -+ -+static struct platform_driver nss_cc_ipq9574_driver = { -+ .probe = nss_cc_ipq9574_probe, -+ .driver = { -+ .name = "qcom,nsscc-ipq9574", -+ .of_match_table = nss_cc_ipq9574_match_table, -+ .pm = &nss_cc_ipq9574_pm_ops, -+ .sync_state = icc_sync_state, -+ }, -+}; -+ -+module_platform_driver(nss_cc_ipq9574_driver); -+ -+MODULE_DESCRIPTION("Qualcomm Technologies, Inc. NSSCC IPQ9574 Driver"); -+MODULE_LICENSE("GPL"); diff --git a/target/linux/qualcommbe/patches-6.12/0022-v6.15-arm64-defconfig-Build-NSS-Clock-Controller-dri.patch b/target/linux/qualcommbe/patches-6.12/0022-v6.15-arm64-defconfig-Build-NSS-Clock-Controller-dri.patch deleted file mode 100644 index 2a2ad000c2..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0022-v6.15-arm64-defconfig-Build-NSS-Clock-Controller-dri.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 8f1b61ea1cb98735aa15a8875d729c21a2169fb9 Mon Sep 17 00:00:00 2001 -From: Devi Priya -Date: Thu, 13 Mar 2025 16:33:59 +0530 -Subject: [PATCH 22/22] v6.15: arm64: defconfig: Build NSS Clock Controller - driver for IPQ9574 - -NSSCC driver is needed to enable the ethernet interfaces present -in RDP433 based on IPQ9574. Since this is not necessary for bootup -enabling it as a module. - -Reviewed-by: Krzysztof Kozlowski -Signed-off-by: Devi Priya -Signed-off-by: Manikanta Mylavarapu -Link: https://lore.kernel.org/r/20250313110359.242491-7-quic_mmanikan@quicinc.com -Signed-off-by: Bjorn Andersson ---- - arch/arm64/configs/defconfig | 1 + - 1 file changed, 1 insertion(+) - ---- a/arch/arm64/configs/defconfig -+++ b/arch/arm64/configs/defconfig -@@ -1312,6 +1312,7 @@ CONFIG_IPQ_GCC_5332=y - CONFIG_IPQ_GCC_6018=y - CONFIG_IPQ_GCC_8074=y - CONFIG_IPQ_GCC_9574=y -+CONFIG_IPQ_NSSCC_9574=m - CONFIG_MSM_GCC_8916=y - CONFIG_MSM_MMCC_8994=m - CONFIG_MSM_GCC_8994=y diff --git a/target/linux/qualcommbe/patches-6.12/0023-v6.15-net-phy-move-PHY-package-code-from-phy_device..patch b/target/linux/qualcommbe/patches-6.12/0023-v6.15-net-phy-move-PHY-package-code-from-phy_device..patch deleted file mode 100644 index 3ea7f813d6..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0023-v6.15-net-phy-move-PHY-package-code-from-phy_device..patch +++ /dev/null @@ -1,524 +0,0 @@ -From 986ec7ee75f2f1f7f93eb0e05f61f297f6123fce Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Mon, 3 Mar 2025 21:14:02 +0100 -Subject: [PATCH] v6.15: net: phy: move PHY package code from phy_device.c to - own source file - -This patch is the first step in moving the PHY package related code -to its own source file. No functional change intended. - -Signed-off-by: Heiner Kallweit -Link: https://patch.msgid.link/57df5c19-fbcd-45a7-9afd-cd4f74d7fa76@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/Makefile | 3 +- - drivers/net/phy/phy_device.c | 237 --------------------------------- - drivers/net/phy/phy_package.c | 244 ++++++++++++++++++++++++++++++++++ - 3 files changed, 246 insertions(+), 238 deletions(-) - create mode 100644 drivers/net/phy/phy_package.c - ---- a/drivers/net/phy/Makefile -+++ b/drivers/net/phy/Makefile -@@ -2,7 +2,8 @@ - # Makefile for Linux PHY drivers - - libphy-y := phy.o phy-c45.o phy-core.o phy_device.o \ -- linkmode.o phy_link_topology.o -+ linkmode.o phy_link_topology.o \ -+ phy_package.o - mdio-bus-y += mdio_bus.o mdio_device.o - - ifdef CONFIG_MDIO_DEVICE ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -1781,243 +1781,6 @@ bool phy_driver_is_genphy_10g(struct phy - EXPORT_SYMBOL_GPL(phy_driver_is_genphy_10g); - - /** -- * phy_package_join - join a common PHY group -- * @phydev: target phy_device struct -- * @base_addr: cookie and base PHY address of PHY package for offset -- * calculation of global register access -- * @priv_size: if non-zero allocate this amount of bytes for private data -- * -- * This joins a PHY group and provides a shared storage for all phydevs in -- * this group. This is intended to be used for packages which contain -- * more than one PHY, for example a quad PHY transceiver. -- * -- * The base_addr parameter serves as cookie which has to have the same values -- * for all members of one group and as the base PHY address of the PHY package -- * for offset calculation to access generic registers of a PHY package. -- * Usually, one of the PHY addresses of the different PHYs in the package -- * provides access to these global registers. -- * The address which is given here, will be used in the phy_package_read() -- * and phy_package_write() convenience functions as base and added to the -- * passed offset in those functions. -- * -- * This will set the shared pointer of the phydev to the shared storage. -- * If this is the first call for a this cookie the shared storage will be -- * allocated. If priv_size is non-zero, the given amount of bytes are -- * allocated for the priv member. -- * -- * Returns < 1 on error, 0 on success. Esp. calling phy_package_join() -- * with the same cookie but a different priv_size is an error. -- */ --int phy_package_join(struct phy_device *phydev, int base_addr, size_t priv_size) --{ -- struct mii_bus *bus = phydev->mdio.bus; -- struct phy_package_shared *shared; -- int ret; -- -- if (base_addr < 0 || base_addr >= PHY_MAX_ADDR) -- return -EINVAL; -- -- mutex_lock(&bus->shared_lock); -- shared = bus->shared[base_addr]; -- if (!shared) { -- ret = -ENOMEM; -- shared = kzalloc(sizeof(*shared), GFP_KERNEL); -- if (!shared) -- goto err_unlock; -- if (priv_size) { -- shared->priv = kzalloc(priv_size, GFP_KERNEL); -- if (!shared->priv) -- goto err_free; -- shared->priv_size = priv_size; -- } -- shared->base_addr = base_addr; -- shared->np = NULL; -- refcount_set(&shared->refcnt, 1); -- bus->shared[base_addr] = shared; -- } else { -- ret = -EINVAL; -- if (priv_size && priv_size != shared->priv_size) -- goto err_unlock; -- refcount_inc(&shared->refcnt); -- } -- mutex_unlock(&bus->shared_lock); -- -- phydev->shared = shared; -- -- return 0; -- --err_free: -- kfree(shared); --err_unlock: -- mutex_unlock(&bus->shared_lock); -- return ret; --} --EXPORT_SYMBOL_GPL(phy_package_join); -- --/** -- * of_phy_package_join - join a common PHY group in PHY package -- * @phydev: target phy_device struct -- * @priv_size: if non-zero allocate this amount of bytes for private data -- * -- * This is a variant of phy_package_join for PHY package defined in DT. -- * -- * The parent node of the @phydev is checked as a valid PHY package node -- * structure (by matching the node name "ethernet-phy-package") and the -- * base_addr for the PHY package is passed to phy_package_join. -- * -- * With this configuration the shared struct will also have the np value -- * filled to use additional DT defined properties in PHY specific -- * probe_once and config_init_once PHY package OPs. -- * -- * Returns < 0 on error, 0 on success. Esp. calling phy_package_join() -- * with the same cookie but a different priv_size is an error. Or a parent -- * node is not detected or is not valid or doesn't match the expected node -- * name for PHY package. -- */ --int of_phy_package_join(struct phy_device *phydev, size_t priv_size) --{ -- struct device_node *node = phydev->mdio.dev.of_node; -- struct device_node *package_node; -- u32 base_addr; -- int ret; -- -- if (!node) -- return -EINVAL; -- -- package_node = of_get_parent(node); -- if (!package_node) -- return -EINVAL; -- -- if (!of_node_name_eq(package_node, "ethernet-phy-package")) { -- ret = -EINVAL; -- goto exit; -- } -- -- if (of_property_read_u32(package_node, "reg", &base_addr)) { -- ret = -EINVAL; -- goto exit; -- } -- -- ret = phy_package_join(phydev, base_addr, priv_size); -- if (ret) -- goto exit; -- -- phydev->shared->np = package_node; -- -- return 0; --exit: -- of_node_put(package_node); -- return ret; --} --EXPORT_SYMBOL_GPL(of_phy_package_join); -- --/** -- * phy_package_leave - leave a common PHY group -- * @phydev: target phy_device struct -- * -- * This leaves a PHY group created by phy_package_join(). If this phydev -- * was the last user of the shared data between the group, this data is -- * freed. Resets the phydev->shared pointer to NULL. -- */ --void phy_package_leave(struct phy_device *phydev) --{ -- struct phy_package_shared *shared = phydev->shared; -- struct mii_bus *bus = phydev->mdio.bus; -- -- if (!shared) -- return; -- -- /* Decrease the node refcount on leave if present */ -- if (shared->np) -- of_node_put(shared->np); -- -- if (refcount_dec_and_mutex_lock(&shared->refcnt, &bus->shared_lock)) { -- bus->shared[shared->base_addr] = NULL; -- mutex_unlock(&bus->shared_lock); -- kfree(shared->priv); -- kfree(shared); -- } -- -- phydev->shared = NULL; --} --EXPORT_SYMBOL_GPL(phy_package_leave); -- --static void devm_phy_package_leave(struct device *dev, void *res) --{ -- phy_package_leave(*(struct phy_device **)res); --} -- --/** -- * devm_phy_package_join - resource managed phy_package_join() -- * @dev: device that is registering this PHY package -- * @phydev: target phy_device struct -- * @base_addr: cookie and base PHY address of PHY package for offset -- * calculation of global register access -- * @priv_size: if non-zero allocate this amount of bytes for private data -- * -- * Managed phy_package_join(). Shared storage fetched by this function, -- * phy_package_leave() is automatically called on driver detach. See -- * phy_package_join() for more information. -- */ --int devm_phy_package_join(struct device *dev, struct phy_device *phydev, -- int base_addr, size_t priv_size) --{ -- struct phy_device **ptr; -- int ret; -- -- ptr = devres_alloc(devm_phy_package_leave, sizeof(*ptr), -- GFP_KERNEL); -- if (!ptr) -- return -ENOMEM; -- -- ret = phy_package_join(phydev, base_addr, priv_size); -- -- if (!ret) { -- *ptr = phydev; -- devres_add(dev, ptr); -- } else { -- devres_free(ptr); -- } -- -- return ret; --} --EXPORT_SYMBOL_GPL(devm_phy_package_join); -- --/** -- * devm_of_phy_package_join - resource managed of_phy_package_join() -- * @dev: device that is registering this PHY package -- * @phydev: target phy_device struct -- * @priv_size: if non-zero allocate this amount of bytes for private data -- * -- * Managed of_phy_package_join(). Shared storage fetched by this function, -- * phy_package_leave() is automatically called on driver detach. See -- * of_phy_package_join() for more information. -- */ --int devm_of_phy_package_join(struct device *dev, struct phy_device *phydev, -- size_t priv_size) --{ -- struct phy_device **ptr; -- int ret; -- -- ptr = devres_alloc(devm_phy_package_leave, sizeof(*ptr), -- GFP_KERNEL); -- if (!ptr) -- return -ENOMEM; -- -- ret = of_phy_package_join(phydev, priv_size); -- -- if (!ret) { -- *ptr = phydev; -- devres_add(dev, ptr); -- } else { -- devres_free(ptr); -- } -- -- return ret; --} --EXPORT_SYMBOL_GPL(devm_of_phy_package_join); -- --/** - * phy_detach - detach a PHY device from its network device - * @phydev: target phy_device struct - * ---- /dev/null -+++ b/drivers/net/phy/phy_package.c -@@ -0,0 +1,244 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+/* -+ * PHY package support -+ */ -+ -+#include -+#include -+ -+/** -+ * phy_package_join - join a common PHY group -+ * @phydev: target phy_device struct -+ * @base_addr: cookie and base PHY address of PHY package for offset -+ * calculation of global register access -+ * @priv_size: if non-zero allocate this amount of bytes for private data -+ * -+ * This joins a PHY group and provides a shared storage for all phydevs in -+ * this group. This is intended to be used for packages which contain -+ * more than one PHY, for example a quad PHY transceiver. -+ * -+ * The base_addr parameter serves as cookie which has to have the same values -+ * for all members of one group and as the base PHY address of the PHY package -+ * for offset calculation to access generic registers of a PHY package. -+ * Usually, one of the PHY addresses of the different PHYs in the package -+ * provides access to these global registers. -+ * The address which is given here, will be used in the phy_package_read() -+ * and phy_package_write() convenience functions as base and added to the -+ * passed offset in those functions. -+ * -+ * This will set the shared pointer of the phydev to the shared storage. -+ * If this is the first call for a this cookie the shared storage will be -+ * allocated. If priv_size is non-zero, the given amount of bytes are -+ * allocated for the priv member. -+ * -+ * Returns < 1 on error, 0 on success. Esp. calling phy_package_join() -+ * with the same cookie but a different priv_size is an error. -+ */ -+int phy_package_join(struct phy_device *phydev, int base_addr, size_t priv_size) -+{ -+ struct mii_bus *bus = phydev->mdio.bus; -+ struct phy_package_shared *shared; -+ int ret; -+ -+ if (base_addr < 0 || base_addr >= PHY_MAX_ADDR) -+ return -EINVAL; -+ -+ mutex_lock(&bus->shared_lock); -+ shared = bus->shared[base_addr]; -+ if (!shared) { -+ ret = -ENOMEM; -+ shared = kzalloc(sizeof(*shared), GFP_KERNEL); -+ if (!shared) -+ goto err_unlock; -+ if (priv_size) { -+ shared->priv = kzalloc(priv_size, GFP_KERNEL); -+ if (!shared->priv) -+ goto err_free; -+ shared->priv_size = priv_size; -+ } -+ shared->base_addr = base_addr; -+ shared->np = NULL; -+ refcount_set(&shared->refcnt, 1); -+ bus->shared[base_addr] = shared; -+ } else { -+ ret = -EINVAL; -+ if (priv_size && priv_size != shared->priv_size) -+ goto err_unlock; -+ refcount_inc(&shared->refcnt); -+ } -+ mutex_unlock(&bus->shared_lock); -+ -+ phydev->shared = shared; -+ -+ return 0; -+ -+err_free: -+ kfree(shared); -+err_unlock: -+ mutex_unlock(&bus->shared_lock); -+ return ret; -+} -+EXPORT_SYMBOL_GPL(phy_package_join); -+ -+/** -+ * of_phy_package_join - join a common PHY group in PHY package -+ * @phydev: target phy_device struct -+ * @priv_size: if non-zero allocate this amount of bytes for private data -+ * -+ * This is a variant of phy_package_join for PHY package defined in DT. -+ * -+ * The parent node of the @phydev is checked as a valid PHY package node -+ * structure (by matching the node name "ethernet-phy-package") and the -+ * base_addr for the PHY package is passed to phy_package_join. -+ * -+ * With this configuration the shared struct will also have the np value -+ * filled to use additional DT defined properties in PHY specific -+ * probe_once and config_init_once PHY package OPs. -+ * -+ * Returns < 0 on error, 0 on success. Esp. calling phy_package_join() -+ * with the same cookie but a different priv_size is an error. Or a parent -+ * node is not detected or is not valid or doesn't match the expected node -+ * name for PHY package. -+ */ -+int of_phy_package_join(struct phy_device *phydev, size_t priv_size) -+{ -+ struct device_node *node = phydev->mdio.dev.of_node; -+ struct device_node *package_node; -+ u32 base_addr; -+ int ret; -+ -+ if (!node) -+ return -EINVAL; -+ -+ package_node = of_get_parent(node); -+ if (!package_node) -+ return -EINVAL; -+ -+ if (!of_node_name_eq(package_node, "ethernet-phy-package")) { -+ ret = -EINVAL; -+ goto exit; -+ } -+ -+ if (of_property_read_u32(package_node, "reg", &base_addr)) { -+ ret = -EINVAL; -+ goto exit; -+ } -+ -+ ret = phy_package_join(phydev, base_addr, priv_size); -+ if (ret) -+ goto exit; -+ -+ phydev->shared->np = package_node; -+ -+ return 0; -+exit: -+ of_node_put(package_node); -+ return ret; -+} -+EXPORT_SYMBOL_GPL(of_phy_package_join); -+ -+/** -+ * phy_package_leave - leave a common PHY group -+ * @phydev: target phy_device struct -+ * -+ * This leaves a PHY group created by phy_package_join(). If this phydev -+ * was the last user of the shared data between the group, this data is -+ * freed. Resets the phydev->shared pointer to NULL. -+ */ -+void phy_package_leave(struct phy_device *phydev) -+{ -+ struct phy_package_shared *shared = phydev->shared; -+ struct mii_bus *bus = phydev->mdio.bus; -+ -+ if (!shared) -+ return; -+ -+ /* Decrease the node refcount on leave if present */ -+ if (shared->np) -+ of_node_put(shared->np); -+ -+ if (refcount_dec_and_mutex_lock(&shared->refcnt, &bus->shared_lock)) { -+ bus->shared[shared->base_addr] = NULL; -+ mutex_unlock(&bus->shared_lock); -+ kfree(shared->priv); -+ kfree(shared); -+ } -+ -+ phydev->shared = NULL; -+} -+EXPORT_SYMBOL_GPL(phy_package_leave); -+ -+static void devm_phy_package_leave(struct device *dev, void *res) -+{ -+ phy_package_leave(*(struct phy_device **)res); -+} -+ -+/** -+ * devm_phy_package_join - resource managed phy_package_join() -+ * @dev: device that is registering this PHY package -+ * @phydev: target phy_device struct -+ * @base_addr: cookie and base PHY address of PHY package for offset -+ * calculation of global register access -+ * @priv_size: if non-zero allocate this amount of bytes for private data -+ * -+ * Managed phy_package_join(). Shared storage fetched by this function, -+ * phy_package_leave() is automatically called on driver detach. See -+ * phy_package_join() for more information. -+ */ -+int devm_phy_package_join(struct device *dev, struct phy_device *phydev, -+ int base_addr, size_t priv_size) -+{ -+ struct phy_device **ptr; -+ int ret; -+ -+ ptr = devres_alloc(devm_phy_package_leave, sizeof(*ptr), -+ GFP_KERNEL); -+ if (!ptr) -+ return -ENOMEM; -+ -+ ret = phy_package_join(phydev, base_addr, priv_size); -+ -+ if (!ret) { -+ *ptr = phydev; -+ devres_add(dev, ptr); -+ } else { -+ devres_free(ptr); -+ } -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(devm_phy_package_join); -+ -+/** -+ * devm_of_phy_package_join - resource managed of_phy_package_join() -+ * @dev: device that is registering this PHY package -+ * @phydev: target phy_device struct -+ * @priv_size: if non-zero allocate this amount of bytes for private data -+ * -+ * Managed of_phy_package_join(). Shared storage fetched by this function, -+ * phy_package_leave() is automatically called on driver detach. See -+ * of_phy_package_join() for more information. -+ */ -+int devm_of_phy_package_join(struct device *dev, struct phy_device *phydev, -+ size_t priv_size) -+{ -+ struct phy_device **ptr; -+ int ret; -+ -+ ptr = devres_alloc(devm_phy_package_leave, sizeof(*ptr), -+ GFP_KERNEL); -+ if (!ptr) -+ return -ENOMEM; -+ -+ ret = of_phy_package_join(phydev, priv_size); -+ -+ if (!ret) { -+ *ptr = phydev; -+ devres_add(dev, ptr); -+ } else { -+ devres_free(ptr); -+ } -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(devm_of_phy_package_join); diff --git a/target/linux/qualcommbe/patches-6.12/0024-v6.15-net-phy-add-getters-for-public-members-in-stru.patch b/target/linux/qualcommbe/patches-6.12/0024-v6.15-net-phy-add-getters-for-public-members-in-stru.patch deleted file mode 100644 index a05083d6fe..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0024-v6.15-net-phy-add-getters-for-public-members-in-stru.patch +++ /dev/null @@ -1,60 +0,0 @@ -From e9ee1dd2ff2c130b2fb2bd01936224a8a6b49a7e Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Mon, 3 Mar 2025 21:15:09 +0100 -Subject: [PATCH] v6.15: net: phy: add getters for public members in struct - phy_package_shared - -Add getters for public members, this prepares for making struct -phy_package_shared private to phylib. Declare the getters in a new header -file phylib.h, which will be used by PHY drivers only. - -Signed-off-by: Heiner Kallweit -Link: https://patch.msgid.link/c6da0b27-4479-4717-9e16-643821b76bd8@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phy_package.c | 14 ++++++++++++++ - drivers/net/phy/phylib.h | 15 +++++++++++++++ - 2 files changed, 29 insertions(+) - create mode 100644 drivers/net/phy/phylib.h - ---- a/drivers/net/phy/phy_package.c -+++ b/drivers/net/phy/phy_package.c -@@ -6,6 +6,20 @@ - #include - #include - -+#include "phylib.h" -+ -+struct device_node *phy_package_get_node(struct phy_device *phydev) -+{ -+ return phydev->shared->np; -+} -+EXPORT_SYMBOL_GPL(phy_package_get_node); -+ -+void *phy_package_get_priv(struct phy_device *phydev) -+{ -+ return phydev->shared->priv; -+} -+EXPORT_SYMBOL_GPL(phy_package_get_priv); -+ - /** - * phy_package_join - join a common PHY group - * @phydev: target phy_device struct ---- /dev/null -+++ b/drivers/net/phy/phylib.h -@@ -0,0 +1,15 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+/* -+ * phylib header -+ */ -+ -+#ifndef __PHYLIB_H -+#define __PHYLIB_H -+ -+struct device_node; -+struct phy_device; -+ -+struct device_node *phy_package_get_node(struct phy_device *phydev); -+void *phy_package_get_priv(struct phy_device *phydev); -+ -+#endif /* __PHYLIB_H */ diff --git a/target/linux/qualcommbe/patches-6.12/0100-arm64-dts-qcom-ipq9574-Add-nsscc-node.patch b/target/linux/qualcommbe/patches-6.12/0100-arm64-dts-qcom-ipq9574-Add-nsscc-node.patch deleted file mode 100644 index c38a7eb09f..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0100-arm64-dts-qcom-ipq9574-Add-nsscc-node.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 52ebd52aa1906961142a2aba55d47a53b956847c Mon Sep 17 00:00:00 2001 -From: Devi Priya -Date: Thu, 13 Mar 2025 16:33:58 +0530 -Subject: [PATCH] arm64: dts: qcom: ipq9574: Add nsscc node - -Add a node for the nss clock controller found on ipq9574 based devices. - -Reviewed-by: Konrad Dybcio -Signed-off-by: Devi Priya -Signed-off-by: Manikanta Mylavarapu -Link: https://lore.kernel.org/r/20250313110359.242491-6-quic_mmanikan@quicinc.com -Signed-off-by: Bjorn Andersson ---- - arch/arm64/boot/dts/qcom/ipq9574.dtsi | 29 +++++++++++++++++++++++++++ - 1 file changed, 29 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi -@@ -1195,6 +1195,35 @@ - status = "disabled"; - }; - -+ nsscc: clock-controller@39b00000 { -+ compatible = "qcom,ipq9574-nsscc"; -+ reg = <0x39b00000 0x80000>; -+ clocks = <&xo_board_clk>, -+ <&cmn_pll NSS_1200MHZ_CLK>, -+ <&cmn_pll PPE_353MHZ_CLK>, -+ <&gcc GPLL0_OUT_AUX>, -+ <0>, -+ <0>, -+ <0>, -+ <0>, -+ <0>, -+ <0>, -+ <&gcc GCC_NSSCC_CLK>; -+ clock-names = "xo", -+ "nss_1200", -+ "ppe_353", -+ "gpll0_out", -+ "uniphy0_rx", -+ "uniphy0_tx", -+ "uniphy1_rx", -+ "uniphy1_tx", -+ "uniphy2_rx", -+ "uniphy2_tx", -+ "bus"; -+ #clock-cells = <1>; -+ #reset-cells = <1>; -+ #interconnect-cells = <1>; -+ }; - }; - - thermal-zones { diff --git a/target/linux/qualcommbe/patches-6.12/0101-arm64-dts-qcom-ipq9574-fix-the-msi-interrupt-numbers.patch b/target/linux/qualcommbe/patches-6.12/0101-arm64-dts-qcom-ipq9574-fix-the-msi-interrupt-numbers.patch deleted file mode 100644 index b09fccf32b..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0101-arm64-dts-qcom-ipq9574-fix-the-msi-interrupt-numbers.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 2f2f5ae4d52ea882ba58f6b2fa6373a3d3db2bce Mon Sep 17 00:00:00 2001 -From: Manikanta Mylavarapu -Date: Thu, 13 Mar 2025 12:44:22 +0530 -Subject: [PATCH] arm64: dts: qcom: ipq9574: fix the msi interrupt numbers of - pcie3 - -The MSI interrupt numbers of the PCIe3 controller are incorrect. Due -to this, the functional bring up of the QDSP6 processor on the PCIe -endpoint has failed. Correct the MSI interrupt numbers to properly -bring up the QDSP6 processor on the PCIe endpoint. - -Fixes: d80c7fbfa908 ("arm64: dts: qcom: ipq9574: Add PCIe PHYs and controller nodes") -Signed-off-by: Manikanta Mylavarapu -Link: https://lore.kernel.org/r/20250313071422.510-1-quic_mmanikan@quicinc.com -Signed-off-by: Bjorn Andersson ---- - arch/arm64/boot/dts/qcom/ipq9574.dtsi | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi -@@ -974,14 +974,14 @@ - ranges = <0x01000000 0x0 0x00000000 0x18200000 0x0 0x100000>, - <0x02000000 0x0 0x18300000 0x18300000 0x0 0x7d00000>; - -- interrupts = , -- , -- , -- , -- , -- , -- , -- ; -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ , -+ ; - interrupt-names = "msi0", - "msi1", - "msi2", diff --git a/target/linux/qualcommbe/patches-6.12/0103-arm64-dts-qcom-ipq9574-Add-SPI-nand-support.patch b/target/linux/qualcommbe/patches-6.12/0103-arm64-dts-qcom-ipq9574-Add-SPI-nand-support.patch deleted file mode 100644 index 7bec20d943..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0103-arm64-dts-qcom-ipq9574-Add-SPI-nand-support.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 583299efa34c4a484b211f84c63aee78b6c2b469 Mon Sep 17 00:00:00 2001 -From: Md Sadre Alam -Date: Thu, 6 Mar 2025 17:03:55 +0530 -Subject: [PATCH] arm64: dts: qcom: ipq9574: Add SPI nand support - -Add SPI NAND support for ipq9574 SoC. - -Signed-off-by: Md Sadre Alam -Link: https://lore.kernel.org/r/20250306113357.126602-2-quic_mdalam@quicinc.com -Signed-off-by: Bjorn Andersson ---- - arch/arm64/boot/dts/qcom/ipq9574.dtsi | 27 +++++++++++++++++++++++++++ - 1 file changed, 27 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi -@@ -675,6 +675,33 @@ - status = "disabled"; - }; - -+ qpic_bam: dma-controller@7984000 { -+ compatible = "qcom,bam-v1.7.4", "qcom,bam-v1.7.0"; -+ reg = <0x07984000 0x1c000>; -+ interrupts = ; -+ clocks = <&gcc GCC_QPIC_AHB_CLK>; -+ clock-names = "bam_clk"; -+ #dma-cells = <1>; -+ qcom,ee = <0>; -+ status = "disabled"; -+ }; -+ -+ qpic_nand: spi@79b0000 { -+ compatible = "qcom,ipq9574-snand"; -+ reg = <0x079b0000 0x10000>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ clocks = <&gcc GCC_QPIC_CLK>, -+ <&gcc GCC_QPIC_AHB_CLK>, -+ <&gcc GCC_QPIC_IO_MACRO_CLK>; -+ clock-names = "core", "aon", "iom"; -+ dmas = <&qpic_bam 0>, -+ <&qpic_bam 1>, -+ <&qpic_bam 2>; -+ dma-names = "tx", "rx", "cmd"; -+ status = "disabled"; -+ }; -+ - usb_0_qusbphy: phy@7b000 { - compatible = "qcom,ipq9574-qusb2-phy"; - reg = <0x0007b000 0x180>; diff --git a/target/linux/qualcommbe/patches-6.12/0104-arm64-dts-qcom-ipq9574-Enable-SPI-NAND-for-ipq9574.patch b/target/linux/qualcommbe/patches-6.12/0104-arm64-dts-qcom-ipq9574-Enable-SPI-NAND-for-ipq9574.patch deleted file mode 100644 index 393923a343..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0104-arm64-dts-qcom-ipq9574-Enable-SPI-NAND-for-ipq9574.patch +++ /dev/null @@ -1,68 +0,0 @@ -From a7c88bc81632974c0708308493aefb1f871b65fa Mon Sep 17 00:00:00 2001 -From: Md Sadre Alam -Date: Thu, 6 Mar 2025 17:03:56 +0530 -Subject: [PATCH] arm64: dts: qcom: ipq9574: Enable SPI NAND for ipq9574 - -Enable SPI NAND support for ipq9574 SoC. - -Reviewed-by: Konrad Dybcio -Signed-off-by: Md Sadre Alam -Link: https://lore.kernel.org/r/20250306113357.126602-3-quic_mdalam@quicinc.com -Signed-off-by: Bjorn Andersson ---- - .../boot/dts/qcom/ipq9574-rdp-common.dtsi | 44 +++++++++++++++++++ - 1 file changed, 44 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq9574-rdp-common.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574-rdp-common.dtsi -@@ -146,6 +146,50 @@ - drive-strength = <8>; - bias-pull-up; - }; -+ -+ qpic_snand_default_state: qpic-snand-default-state { -+ clock-pins { -+ pins = "gpio5"; -+ function = "qspi_clk"; -+ drive-strength = <8>; -+ bias-disable; -+ }; -+ -+ cs-pins { -+ pins = "gpio4"; -+ function = "qspi_cs"; -+ drive-strength = <8>; -+ bias-disable; -+ }; -+ -+ data-pins { -+ pins = "gpio0", "gpio1", "gpio2", "gpio3"; -+ function = "qspi_data"; -+ drive-strength = <8>; -+ bias-disable; -+ }; -+ }; -+}; -+ -+&qpic_bam { -+ status = "okay"; -+}; -+ -+&qpic_nand { -+ pinctrl-0 = <&qpic_snand_default_state>; -+ pinctrl-names = "default"; -+ -+ status = "okay"; -+ -+ flash@0 { -+ compatible = "spi-nand"; -+ reg = <0>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ nand-ecc-engine = <&qpic_nand>; -+ nand-ecc-strength = <4>; -+ nand-ecc-step-size = <512>; -+ }; - }; - - &usb_0_dwc3 { diff --git a/target/linux/qualcommbe/patches-6.12/0105-arm64-dts-qcom-ipq9574-Remove-eMMC-node.patch b/target/linux/qualcommbe/patches-6.12/0105-arm64-dts-qcom-ipq9574-Remove-eMMC-node.patch deleted file mode 100644 index d188539aaa..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0105-arm64-dts-qcom-ipq9574-Remove-eMMC-node.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0156e327aa854be5eb9cbec9d020be1026b5b446 Mon Sep 17 00:00:00 2001 -From: Md Sadre Alam -Date: Thu, 6 Mar 2025 17:03:57 +0530 -Subject: [PATCH] arm64: dts: qcom: ipq9574: Remove eMMC node - -Remove eMMC node for rdp433, since rdp433 -default boot mode is norplusnand - -Reviewed-by: Konrad Dybcio -Signed-off-by: Md Sadre Alam -Link: https://lore.kernel.org/r/20250306113357.126602-4-quic_mdalam@quicinc.com -Signed-off-by: Bjorn Andersson ---- - arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts | 12 ------------ - 1 file changed, 12 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts -+++ b/arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts -@@ -55,18 +55,6 @@ - status = "okay"; - }; - --&sdhc_1 { -- pinctrl-0 = <&sdc_default_state>; -- pinctrl-names = "default"; -- mmc-ddr-1_8v; -- mmc-hs200-1_8v; -- mmc-hs400-1_8v; -- mmc-hs400-enhanced-strobe; -- max-frequency = <384000000>; -- bus-width = <8>; -- status = "okay"; --}; -- - &tlmm { - - pcie1_default: pcie1-default-state { diff --git a/target/linux/qualcommbe/patches-6.12/0301-arm64-dts-qcom-Add-IPQ9574-MDIO-device-node.patch b/target/linux/qualcommbe/patches-6.12/0301-arm64-dts-qcom-Add-IPQ9574-MDIO-device-node.patch deleted file mode 100644 index c094e6e016..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0301-arm64-dts-qcom-Add-IPQ9574-MDIO-device-node.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 657833a74f532262d415fa2ca354b69f4a97353c Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Thu, 23 Nov 2023 15:41:20 +0800 -Subject: [PATCH] arm64: dts: qcom: Add IPQ9574 MDIO device node - -The MDIO bus master block is used to accessing the MDIO slave -device (such as PHY device), the dedicated MDIO PINs needs to -be configured. - -Change-Id: Ia64083529e693256dbd8f8af4071c02afdded8f9 -Signed-off-by: Luo Jie ---- - arch/arm64/boot/dts/qcom/ipq9574.dtsi | 18 ++++++++++++++++++ - 1 file changed, 18 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi -@@ -295,6 +295,8 @@ - mdio: mdio@90000 { - compatible = "qcom,ipq9574-mdio", "qcom,ipq4019-mdio"; - reg = <0x00090000 0x64>; -+ pinctrl-0 = <&mdio_pins>; -+ pinctrl-names = "default"; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&gcc GCC_MDIO_AHB_CLK>; -@@ -414,6 +416,22 @@ - interrupt-controller; - #interrupt-cells = <2>; - -+ mdio_pins: mdio-pins { -+ mdc-state { -+ pins = "gpio38"; -+ function = "mdc"; -+ drive-strength = <8>; -+ bias-disable; -+ }; -+ -+ mdio-state { -+ pins = "gpio39"; -+ function = "mdio"; -+ drive-strength = <8>; -+ bias-pull-up; -+ }; -+ }; -+ - uart2_pins: uart2-state { - pins = "gpio34", "gpio35"; - function = "blsp2_uart"; diff --git a/target/linux/qualcommbe/patches-6.12/0302-arm64-dts-qcom-ipq9574-Use-usb-phy-for-node-names.patch b/target/linux/qualcommbe/patches-6.12/0302-arm64-dts-qcom-ipq9574-Use-usb-phy-for-node-names.patch deleted file mode 100644 index cc7192158a..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0302-arm64-dts-qcom-ipq9574-Use-usb-phy-for-node-names.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 91467ca0db1654644b2168f882f223d47dcfb9c1 Mon Sep 17 00:00:00 2001 -From: Alexandru Gagniuc -Date: Sat, 30 Mar 2024 20:03:30 -0500 -Subject: [PATCH] arm64: dts: qcom: ipq9574: Use 'usb-phy' for node names - -The devicetree spec allows node names of "usb-phy". So be more -specific for the USB PHYs, and name the nodes "usb-phy" instead of -just "phy". - -Signed-off-by: Alexandru Gagniuc ---- - arch/arm64/boot/dts/qcom/ipq9574.dtsi | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi -@@ -720,7 +720,7 @@ - status = "disabled"; - }; - -- usb_0_qusbphy: phy@7b000 { -+ usb_0_qusbphy: usb-phy@7b000 { - compatible = "qcom,ipq9574-qusb2-phy"; - reg = <0x0007b000 0x180>; - #phy-cells = <0>; -@@ -734,7 +734,7 @@ - status = "disabled"; - }; - -- usb_0_qmpphy: phy@7d000 { -+ usb_0_qmpphy: usb-phy@7d000 { - compatible = "qcom,ipq9574-qmp-usb3-phy"; - reg = <0x0007d000 0xa00>; - #phy-cells = <0>; diff --git a/target/linux/qualcommbe/patches-6.12/0304-arm64-dts-qcom-ipq9574-add-QPIC-SPI-NAND-default-par.patch b/target/linux/qualcommbe/patches-6.12/0304-arm64-dts-qcom-ipq9574-add-QPIC-SPI-NAND-default-par.patch deleted file mode 100644 index b76039c448..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0304-arm64-dts-qcom-ipq9574-add-QPIC-SPI-NAND-default-par.patch +++ /dev/null @@ -1,51 +0,0 @@ -From be44d0251a2540f3b8d7205e0bc6659704366711 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Thu, 30 Jan 2025 00:39:30 +0100 -Subject: [PATCH] arm64: dts: qcom: ipq9574: add QPIC SPI NAND default - partition nodes - -Add QPIC SPI NAND default partition nodes for RDP reference board. - -Signed-off-by: Christian Marangi ---- - .../boot/dts/qcom/ipq9574-rdp-common.dtsi | 28 +++++++++++++++++++ - 1 file changed, 28 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq9574-rdp-common.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574-rdp-common.dtsi -@@ -189,6 +189,35 @@ - nand-ecc-engine = <&qpic_nand>; - nand-ecc-strength = <4>; - nand-ecc-step-size = <512>; -+ -+ partitions { -+ compatible = "fixed-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "0:training"; -+ reg = <0x0 0x80000>; -+ read-only; -+ }; -+ -+ partition@80000 { -+ label = "0:license"; -+ reg = <0x80000 0x40000>; -+ read-only; -+ }; -+ -+ partition@c0000 { -+ label = "rootfs"; -+ reg = <0xc0000 0x3c00000>; -+ linux,rootfs; -+ }; -+ -+ partition@3cc0000 { -+ label = "rootfs_1"; -+ reg = <0x3cc0000 0x3c00000>; -+ }; -+ }; - }; - }; - diff --git a/target/linux/qualcommbe/patches-6.12/0305-arm64-dts-qcom-add-partition-table-for-ipq9574-rdp-c.patch b/target/linux/qualcommbe/patches-6.12/0305-arm64-dts-qcom-add-partition-table-for-ipq9574-rdp-c.patch deleted file mode 100644 index 04314f59ea..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0305-arm64-dts-qcom-add-partition-table-for-ipq9574-rdp-c.patch +++ /dev/null @@ -1,174 +0,0 @@ -From 47c7ae9715d76054d98e8407dbb8ca1cf42fd587 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 9 Dec 2024 17:50:31 +0100 -Subject: [PATCH] arm64: dts: qcom: add partition table for ipq9574 rdp common - -Add partition table for ipq9574 SoC common to every RDB board. - -Signed-off-by: Christian Marangi ---- - .../boot/dts/qcom/ipq9574-rdp-common.dtsi | 146 +++++++++++++++++- - 1 file changed, 145 insertions(+), 1 deletion(-) - ---- a/arch/arm64/boot/dts/qcom/ipq9574-rdp-common.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574-rdp-common.dtsi -@@ -74,11 +74,158 @@ - status = "okay"; - - flash@0 { -- compatible = "micron,n25q128a11", "jedec,spi-nor"; -+ compatible = "jedec,spi-nor"; - reg = <0>; - #address-cells = <1>; - #size-cells = <1>; - spi-max-frequency = <50000000>; -+ -+ partitions { -+ compatible = "fixed-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "0:sbl1"; -+ reg = <0x0 0xc0000>; -+ read-only; -+ }; -+ -+ partition@c0000 { -+ label = "0:mibib"; -+ reg = <0xc0000 0x10000>; -+ read-only; -+ }; -+ -+ partition@d0000 { -+ label = "0:bootconfig"; -+ reg = <0xd0000 0x20000>; -+ read-only; -+ }; -+ -+ partition@f0000 { -+ label = "0:bootconfig1"; -+ reg = <0xf0000 0x20000>; -+ read-only; -+ }; -+ -+ partition@110000 { -+ label = "0:qsee"; -+ reg = <0x110000 0x180000>; -+ read-only; -+ }; -+ -+ partition@290000 { -+ label = "0:qsee_1"; -+ reg = <0x290000 0x180000>; -+ read-only; -+ }; -+ -+ partition@410000 { -+ label = "0:devcfg"; -+ reg = <0x410000 0x10000>; -+ read-only; -+ }; -+ -+ partition@420000 { -+ label = "0:devcfg_1"; -+ reg = <0x420000 0x10000>; -+ read-only; -+ }; -+ -+ partition@430000 { -+ label = "0:apdp"; -+ reg = <0x430000 0x10000>; -+ read-only; -+ }; -+ -+ partition@440000 { -+ label = "0:apdp_1"; -+ reg = <0x440000 0x10000>; -+ read-only; -+ }; -+ -+ partition@450000 { -+ label = "0:tme"; -+ reg = <0x450000 0x40000>; -+ read-only; -+ }; -+ -+ partition@490000 { -+ label = "0:tme_1"; -+ reg = <0x490000 0x40000>; -+ read-only; -+ }; -+ -+ partition@4d0000 { -+ label = "0:rpm"; -+ reg = <0x4d0000 0x20000>; -+ read-only; -+ }; -+ -+ partition@4f0000 { -+ label = "0:rpm_1"; -+ reg = <0x4f0000 0x20000>; -+ read-only; -+ }; -+ -+ partition@510000 { -+ label = "0:cdt"; -+ reg = <0x510000 0x10000>; -+ read-only; -+ }; -+ -+ partition@520000 { -+ label = "0:cdt_1"; -+ reg = <0x520000 0x10000>; -+ read-only; -+ }; -+ -+ partition@530000 { -+ label = "0:appsblenv"; -+ reg = <0x530000 0x10000>; -+ -+ nvmem-layout { -+ compatible = "u-boot,env"; -+ -+ macaddr_lan: ethaddr { -+ #nvmem-cell-cells = <1>; -+ }; -+ }; -+ }; -+ -+ partition@540000 { -+ label = "0:appsbl"; -+ reg = <0x540000 0xa0000>; -+ read-only; -+ }; -+ -+ partition@5e0000 { -+ label = "0:appsbl_1"; -+ reg = <0x5e0000 0xa0000>; -+ read-only; -+ }; -+ -+ partition@680000 { -+ label = "0:art"; -+ reg = <0x680000 0x100000>; -+ read-only; -+ }; -+ -+ partition@780000 { -+ label = "0:ethphyfw"; -+ reg = <0x780000 0x80000>; -+ read-only; -+ -+ nvmem-layout { -+ compatible = "fixed-layout"; -+ -+ aqr_fw: aqr-fw@0 { -+ reg = <0x0 0x5fc02>; -+ }; -+ }; -+ }; -+ }; - }; - }; - diff --git a/target/linux/qualcommbe/patches-6.12/0306-dt-bindings-net-Document-Qualcomm-QCA8084-PHY-packag.patch b/target/linux/qualcommbe/patches-6.12/0306-dt-bindings-net-Document-Qualcomm-QCA8084-PHY-packag.patch deleted file mode 100644 index a9223c5a35..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0306-dt-bindings-net-Document-Qualcomm-QCA8084-PHY-packag.patch +++ /dev/null @@ -1,536 +0,0 @@ -From 7b1c4e22532ded6b20ee41936fa38b5ca1e61ff9 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Mon, 29 Jan 2024 17:57:20 +0800 -Subject: [PATCH] dt-bindings: net: Document Qualcomm QCA8084 PHY package - -QCA8084 is quad PHY chip, which integrates 4 PHYs, 2 PCS -interfaces (PCS0 and PCS1) and clock controller, which can -also be integrated to the switch chip named as QCA8386. - -1. MDIO address of 4 PHYs, 2 PCS and 1 XPCS (PCS1 includes - PCS and XPCS, PCS0 includes PCS) can be configured. -2. The package mode of PHY is optionally configured for the - interface mode of two PCSes working correctly. -3. The package level clock and reset need to be initialized. -4. The clock and reset per PHY device need to be initialized - so that the PHY register can be accessed. - -Change-Id: Idb2338d2673152cbd3c57e95968faa59e9d4a80f -Signed-off-by: Luo Jie -Alex G: Update to match the patches that will be upstream. -Signed-off-by: Alexandru Gagniuc ---- - .../devicetree/bindings/net/qcom,qca8084.yaml | 488 ++++++++++++++++++ - include/dt-bindings/net/qcom,qca808x.h | 14 + - 2 files changed, 502 insertions(+) - create mode 100644 Documentation/devicetree/bindings/net/qcom,qca8084.yaml - create mode 100644 include/dt-bindings/net/qcom,qca808x.h - ---- /dev/null -+++ b/Documentation/devicetree/bindings/net/qcom,qca8084.yaml -@@ -0,0 +1,488 @@ -+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/net/qcom,qca8084.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Qualcomm QCA8084 Ethernet Quad PHY -+ -+maintainers: -+ - Luo Jie -+ -+description: -+ Qualcomm QCA8084 is PHY package of four-port Ethernet transceiver, -+ the Ethernet port supports link speed 10/100/1000/2500 Mbps. -+ There are two PCSes (PCS0 and PCS1) integrated in the PHY -+ package, PCS1 includes XPCS and PCS to support the interface -+ mode 10G-QXGMII and SGMII, PCS0 includes a PCS to support the -+ interface mode SGMII only. There is also a clock controller -+ integrated in the PHY package. This four-port Ethernet -+ transceiver can also be integrated to the switch chip named -+ as QCA8386. The PHY package mode needs to be configured as the -+ correct value to apply the interface mode of two PCSes as -+ mentioned below. -+ -+ QCA8084 expects an input reference clock 50 MHZ as the clock -+ source of the integrated clock controller, the integrated -+ clock controller supplies the clocks and resets to the -+ integrated PHY, PCS and PHY package. -+ -+ - | -+ +--| |--+-------------------+--| |--+ -+ | PCS1 |<------------+---->| PCS0 | -+ +-------+ | +-------+ -+ | | | -+ Ref 50M clk +--------+ | | -+ ------------>| | clk & rst | | -+ GPIO Reset |QCA8K-CC+------------+ | -+ ------------>| | | | -+ +--------+ | | -+ | V | -+ +--------+--------+--------+--------+ -+ | PHY0 | PHY1 | PHY2 | PHY3 | -+ +--------+--------+--------+--------+ -+ -+properties: -+ compatible: -+ const: qcom,qca8084-package -+ -+ clocks: -+ description: -+ PHY package level initial common clocks, which are needed to -+ be enabled after GPIO reset on the PHY package, these clocks -+ are supplied from the PHY integrated clock controller (QCA8K-CC). -+ items: -+ - description: APB bridge clock -+ - description: AHB clock -+ - description: Security control clock -+ - description: TLMM clock -+ - description: TLMM AHB clock -+ - description: CNOC AHB clock -+ - description: MDIO AHB clock -+ -+ clock-names: -+ items: -+ - const: apb_bridge -+ - const: ahb -+ - const: sec_ctrl_ahb -+ - const: tlmm -+ - const: tlmm_ahb -+ - const: cnoc_ahb -+ - const: mdio_ahb -+ -+ resets: -+ description: -+ PHY package level initial common reset, which are needed to -+ be deasserted after GPIO reset on the PHY package, this reset -+ is provided by the PHY integrated clock controller to do PHY -+ DSP reset. -+ maxItems: 1 -+ -+ qcom,package-mode: -+ description: | -+ The package mode of PHY supports to be configured as 3 modes -+ to apply the combinations of interface mode of two PCSes -+ correctly. This value should use one of the values defined in -+ dt-bindings/net/qcom,qca808x.h. The package mode 10G-QXGMII of -+ Quad PHY is used by default. -+ -+ package mode PCS1 PCS0 -+ phy mode (0) 10G-QXGMII for not used -+ PHY0-PHY3 -+ -+ switch mode (1) SGMII for SGMII for -+ switch MAC0 switch MAC5 (optional) -+ -+ switch bypass MAC5 (2) SGMII for SGMII for -+ switch MAC0 PHY3 -+ $ref: /schemas/types.yaml#/definitions/uint32 -+ enum: [0, 1, 2] -+ default: 0 -+ -+ qcom,phy-addr-fixup: -+ description: -+ MDIO address for PHY0-PHY3, PCS0 and PCS1 including PCS and XPCS, -+ which can be optionally customized by programming the security -+ control register of PHY package. The hardware default MDIO address -+ of PHY0-PHY3, PCS0 and PCS1 including PCS and XPCS is 0-6. -+ $ref: /schemas/types.yaml#/definitions/uint32-array -+ minItems: 7 -+ maxItems: 7 -+ -+patternProperties: -+ ^ethernet-phy@[a-f0-9]+$: -+ unevaluatedProperties: false -+ $ref: ethernet-phy.yaml# -+ -+ properties: -+ compatible: -+ const: ethernet-phy-id004d.d180 -+ -+ qcom,xpcs-channel: -+ description: -+ When PCS1 works on the interface mode 10G-QXGMII, the integrated -+ XPCS including 4 channels is used to connected with the Quad PHYs, -+ each PHY needs to be specified the XPCS channel ID to deliver the -+ PHY link status to the XPCS. -+ $ref: /schemas/types.yaml#/definitions/uint32 -+ enum: [0, 1, 2, 3] -+ -+ required: -+ - compatible -+ - reg -+ - clocks -+ - resets -+ -+ ^pcs-phy@[a-f0-9]+$: -+ type: object -+ additionalProperties: false -+ description: -+ PCS device has the independent MDIO address, which controls -+ the interface mode used and provides the clocks such as -+ 312.5 MHZ as RX and TX root clocks to the integrated clock -+ controller. -+ properties: -+ compatible: -+ const: qcom,qca8k-pcs-phy -+ -+ reg: -+ items: -+ - description: PCS MDIO address. -+ -+ clocks: -+ items: -+ - description: PCS clock. -+ - description: PCS RX root clock. -+ - description: PCS TX root clock. -+ -+ clock-names: -+ items: -+ - const: pcs -+ - const: pcs_rx_root -+ - const: pcs_tx_root -+ -+ resets: -+ items: -+ - description: PCS reset. -+ -+ required: -+ - compatible -+ - reg -+ - clocks -+ - resets -+ -+ ^xpcs-phy@[a-f0-9]+$: -+ type: object -+ additionalProperties: false -+ description: -+ XPCS device has the independent MDIO address, which includes 4 -+ channels to connect with Quad PHYs. -+ properties: -+ compatible: -+ const: qcom,qca8k-xpcs-phy -+ -+ reg: -+ items: -+ - description: XPCS MDIO address. -+ -+ resets: -+ items: -+ - description: XPCS reset. -+ -+ '#address-cells': -+ const: 1 -+ -+ '#size-cells': -+ const: 0 -+ -+ required: -+ - compatible -+ - reg -+ - resets -+ - '#address-cells' -+ - '#size-cells' -+ -+ patternProperties: -+ "^channel@[0-3]+$": -+ type: object -+ additionalProperties: false -+ description: -+ XPCS is used to support 10G-QXGMII mode, which inlcudes 4 channels -+ to be connected with Quad PHYs, each channels has the dedicated -+ clocks and resets from the integrated clock controller of QCA8084. -+ -+ properties: -+ reg: -+ items: -+ - description: XPCS channel ID -+ -+ clocks: -+ items: -+ - description: XPCS XGMII RX clock -+ - description: XPCS XGMII TX clock -+ - description: XPCS RX clock -+ - description: XPCS TX clock -+ - description: Port RX clock -+ - description: Port TX clock -+ - description: RX source clock -+ - description: TX source clock -+ -+ clock-names: -+ items: -+ - const: xgmii_rx -+ - const: xgmii_tx -+ - const: xpcs_rx -+ - const: xpcs_tx -+ - const: port_rx -+ - const: port_tx -+ - const: rx_src -+ - const: tx_src -+ -+ resets: -+ items: -+ - description: XPCS XGMII RX reset -+ - description: XPCS XGMII TX reset -+ - description: XPCS RX reset -+ - description: XPCS TX reset -+ - description: Port RX reset -+ - description: Port TX reset -+ -+ reset-names: -+ items: -+ - const: xgmii_rx -+ - const: xgmii_tx -+ - const: xpcs_rx -+ - const: xpcs_tx -+ - const: port_rx -+ - const: port_tx -+ -+ required: -+ - reg -+ - clocks -+ - clock-names -+ - resets -+ - reset-names -+ -+required: -+ - compatible -+ - clocks -+ - clock-names -+ - resets -+ -+allOf: -+ - $ref: ethernet-phy-package.yaml# -+ -+unevaluatedProperties: false -+ -+examples: -+ - | -+ #include -+ #include -+ #include -+ -+ mdio { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ ethernet-phy-package@1 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "qcom,qca8084-package"; -+ reg = <1>; -+ clocks = <&qca8k_nsscc NSS_CC_APB_BRIDGE_CLK>, -+ <&qca8k_nsscc NSS_CC_AHB_CLK>, -+ <&qca8k_nsscc NSS_CC_SEC_CTRL_AHB_CLK>, -+ <&qca8k_nsscc NSS_CC_TLMM_CLK>, -+ <&qca8k_nsscc NSS_CC_TLMM_AHB_CLK>, -+ <&qca8k_nsscc NSS_CC_CNOC_AHB_CLK>, -+ <&qca8k_nsscc NSS_CC_MDIO_AHB_CLK>; -+ clock-names = "apb_bridge", -+ "ahb", -+ "sec_ctrl_ahb", -+ "tlmm", -+ "tlmm_ahb", -+ "cnoc_ahb", -+ "mdio_ahb"; -+ resets = <&qca8k_nsscc NSS_CC_GEPHY_FULL_ARES>; -+ qcom,package-mode = ; -+ qcom,phy-addr-fixup = <1 2 3 4 5 6 7>; -+ -+ ethernet-phy@1 { -+ compatible = "ethernet-phy-id004d.d180"; -+ reg = <1>; -+ clocks = <&qca8k_nsscc NSS_CC_GEPHY0_SYS_CLK>; -+ resets = <&qca8k_nsscc NSS_CC_GEPHY0_SYS_ARES>; -+ qcom,xpcs-channel = <0>; -+ }; -+ -+ ethernet-phy@2 { -+ compatible = "ethernet-phy-id004d.d180"; -+ reg = <2>; -+ clocks = <&qca8k_nsscc NSS_CC_GEPHY1_SYS_CLK>; -+ resets = <&qca8k_nsscc NSS_CC_GEPHY1_SYS_ARES>; -+ qcom,xpcs-channel = <1>; -+ }; -+ -+ ethernet-phy@3 { -+ compatible = "ethernet-phy-id004d.d180"; -+ reg = <3>; -+ clocks = <&qca8k_nsscc NSS_CC_GEPHY2_SYS_CLK>; -+ resets = <&qca8k_nsscc NSS_CC_GEPHY2_SYS_ARES>; -+ qcom,xpcs-channel = <2>; -+ }; -+ -+ ethernet-phy@4 { -+ compatible = "ethernet-phy-id004d.d180"; -+ reg = <4>; -+ clocks = <&qca8k_nsscc NSS_CC_GEPHY3_SYS_CLK>; -+ resets = <&qca8k_nsscc NSS_CC_GEPHY3_SYS_ARES>; -+ qcom,xpcs-channel = <3>; -+ }; -+ -+ pcs-phy@6 { -+ compatible = "qcom,qca8k-pcs-phy"; -+ reg = <6>; -+ clocks = <&qca8k_nsscc NSS_CC_SRDS1_SYS_CLK>, -+ <&qca8k_uniphy1_tx312p5m>, -+ <&qca8k_uniphy1_rx312p5m>; -+ clock-names = "pcs", "pcs_rx_root", "pcs_tx_root"; -+ resets = <&qca8k_nsscc NSS_CC_SRDS1_SYS_ARES>; -+ }; -+ -+ xpcs-phy@7 { -+ compatible = "qcom,qca8k-xpcs-phy"; -+ reg = <7>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ resets = <&qca8k_nsscc NSS_CC_XPCS_ARES>; -+ -+ channel@0 { -+ reg = <0>; -+ clocks = <&qca8k_nsscc NSS_CC_MAC1_SRDS1_CH0_XGMII_TX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC1_SRDS1_CH0_XGMII_RX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC1_SRDS1_CH0_TX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC1_SRDS1_CH0_RX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC1_GEPHY0_RX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC1_GEPHY0_TX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC1_RX_CLK_SRC>, -+ <&qca8k_nsscc NSS_CC_MAC1_TX_CLK_SRC>; -+ clock-names = "xgmii_rx", -+ "xgmii_tx", -+ "xpcs_rx", -+ "xpcs_tx", -+ "port_rx", -+ "port_tx", -+ "rx_src", -+ "tx_src"; -+ resets = <&qca8k_nsscc NSS_CC_MAC1_SRDS1_CH0_XGMII_TX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC1_SRDS1_CH0_XGMII_RX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC1_SRDS1_CH0_TX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC1_SRDS1_CH0_RX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC1_GEPHY0_RX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC1_GEPHY0_TX_ARES>; -+ reset-names = "xgmii_rx", -+ "xgmii_tx", -+ "xpcs_rx", -+ "xpcs_tx", -+ "port_rx", -+ "port_tx"; -+ }; -+ -+ channel@1 { -+ reg = <1>; -+ clocks = <&qca8k_nsscc NSS_CC_MAC2_SRDS1_CH1_XGMII_TX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC2_SRDS1_CH1_XGMII_RX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC2_SRDS1_CH1_TX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC2_SRDS1_CH1_RX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC2_GEPHY1_RX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC2_GEPHY1_TX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC2_RX_CLK_SRC>, -+ <&qca8k_nsscc NSS_CC_MAC2_TX_CLK_SRC>; -+ clock-names = "xgmii_rx", -+ "xgmii_tx", -+ "xpcs_rx", -+ "xpcs_tx", -+ "port_rx", -+ "port_tx", -+ "rx_src", -+ "tx_src"; -+ resets = <&qca8k_nsscc NSS_CC_MAC2_SRDS1_CH1_XGMII_TX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC2_SRDS1_CH1_XGMII_RX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC2_SRDS1_CH1_TX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC2_SRDS1_CH1_RX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC2_GEPHY1_RX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC2_GEPHY1_TX_ARES>; -+ reset-names = "xgmii_rx", -+ "xgmii_tx", -+ "xpcs_rx", -+ "xpcs_tx", -+ "port_rx", -+ "port_tx"; -+ }; -+ -+ channel@2 { -+ reg = <2>; -+ clocks = <&qca8k_nsscc NSS_CC_MAC3_SRDS1_CH2_XGMII_TX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC3_SRDS1_CH2_XGMII_RX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC3_SRDS1_CH2_TX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC3_SRDS1_CH2_RX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC3_GEPHY2_RX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC3_GEPHY2_TX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC3_RX_CLK_SRC>, -+ <&qca8k_nsscc NSS_CC_MAC3_TX_CLK_SRC>; -+ clock-names = "xgmii_rx", -+ "xgmii_tx", -+ "xpcs_rx", -+ "xpcs_tx", -+ "port_rx", -+ "port_tx", -+ "rx_src", -+ "tx_src"; -+ resets = <&qca8k_nsscc NSS_CC_MAC3_SRDS1_CH2_XGMII_TX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC3_SRDS1_CH2_XGMII_RX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC3_SRDS1_CH2_TX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC3_SRDS1_CH2_RX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC3_GEPHY2_RX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC3_GEPHY2_TX_ARES>; -+ reset-names = "xgmii_rx", -+ "xgmii_tx", -+ "xpcs_rx", -+ "xpcs_tx", -+ "port_rx", -+ "port_tx"; -+ }; -+ -+ channel@3 { -+ reg = <3>; -+ clocks = <&qca8k_nsscc NSS_CC_MAC4_SRDS1_CH3_XGMII_TX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC4_SRDS1_CH3_XGMII_RX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC4_SRDS1_CH3_TX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC4_SRDS1_CH3_RX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC4_GEPHY3_RX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC4_GEPHY3_TX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC4_RX_CLK_SRC>, -+ <&qca8k_nsscc NSS_CC_MAC4_TX_CLK_SRC>; -+ clock-names = "xgmii_rx", -+ "xgmii_tx", -+ "xpcs_rx", -+ "xpcs_tx", -+ "port_rx", -+ "port_tx", -+ "rx_src", -+ "tx_src"; -+ resets = <&qca8k_nsscc NSS_CC_MAC4_SRDS1_CH3_XGMII_TX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC4_SRDS1_CH3_XGMII_RX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC4_SRDS1_CH3_TX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC4_SRDS1_CH3_RX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC4_GEPHY3_RX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC4_GEPHY3_TX_ARES>; -+ reset-names = "xgmii_rx", -+ "xgmii_tx", -+ "xpcs_rx", -+ "xpcs_tx", -+ "port_rx", -+ "port_tx"; -+ }; -+ }; -+ }; -+ }; ---- /dev/null -+++ b/include/dt-bindings/net/qcom,qca808x.h -@@ -0,0 +1,14 @@ -+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ -+/* -+ * Device Tree constants for the Qualcomm QCA808X PHYs -+ */ -+ -+#ifndef _DT_BINDINGS_QCOM_QCA808X_H -+#define _DT_BINDINGS_QCOM_QCA808X_H -+ -+/* PHY package modes of QCA8084 to apply the interface modes of two PCSes. */ -+#define QCA808X_PCS1_10G_QXGMII_PCS0_UNUNSED 0 -+#define QCA808X_PCS1_SGMII_MAC_PCS0_SGMII_MAC 1 -+#define QCA808X_PCS1_SGMII_MAC_PCS0_SGMII_PHY 2 -+ -+#endif diff --git a/target/linux/qualcommbe/patches-6.12/0307-net-phy-qca808x-Add-QCA8084-ethernet-phy-support.patch b/target/linux/qualcommbe/patches-6.12/0307-net-phy-qca808x-Add-QCA8084-ethernet-phy-support.patch deleted file mode 100644 index 360517f9b5..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0307-net-phy-qca808x-Add-QCA8084-ethernet-phy-support.patch +++ /dev/null @@ -1,144 +0,0 @@ -From 60c44842f9611be237ab3f68afe8ebf2d9595fb2 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Thu, 6 Apr 2023 18:09:07 +0800 -Subject: [PATCH] net: phy: qca808x: Add QCA8084 ethernet phy support - -Add QCA8084 Quad-PHY support, which is a four-port PHY with -maximum link capability of 2.5 Gbps. The features of each port -are almost same as QCA8081. The slave seed and fast retrain -configs are not needed for QCA8084. It includes two PCSes. - -PCS0 of QCA8084 supports the interface modes: -PHY_INTERFACE_MODE_2500BASEX and PHY_INTERFACE_MODE_SGMII. - -PCS1 of QCA8084 supports the interface modes: -PHY_INTERFACE_MODE_10G_QXGMII, PHY_INTERFACE_MODE_2500BASEX and -PHY_INTERFACE_MODE_SGMII. - -The additional CDT configurations needed for QCA8084 compared -with QCA8081. - -Change-Id: I12555fa70662682474ab4432204405b5e752fef6 -Signed-off-by: Luo Jie -Alex G: Update to match the patches that will be upstream. -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/phy/qcom/qca808x.c | 65 ++++++++++++++++++++++++++++++++-- - 1 file changed, 63 insertions(+), 2 deletions(-) - ---- a/drivers/net/phy/qcom/qca808x.c -+++ b/drivers/net/phy/qcom/qca808x.c -@@ -86,9 +86,16 @@ - #define QCA8081_PHY_FIFO_RSTN BIT(11) - - #define QCA8081_PHY_ID 0x004dd101 -+#define QCA8084_PHY_ID 0x004dd180 -+ -+#define QCA8084_MMD3_CDT_PULSE_CTRL 0x8075 -+#define QCA8084_CDT_PULSE_THRESH_VAL 0xa060 -+ -+#define QCA8084_MMD3_CDT_NEAR_CTRL 0x807f -+#define QCA8084_CDT_NEAR_BYPASS BIT(15) - - MODULE_DESCRIPTION("Qualcomm Atheros QCA808X PHY driver"); --MODULE_AUTHOR("Matus Ujhelyi"); -+MODULE_AUTHOR("Matus Ujhelyi, Luo Jie"); - MODULE_LICENSE("GPL"); - - struct qca808x_priv { -@@ -153,13 +160,18 @@ static bool qca808x_is_prefer_master(str - - 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); -+ return phydev_id_compare(phydev, QCA8081_PHY_ID) && -+ linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, -+ phydev->supported); - } - - static bool qca808x_is_1g_only(struct phy_device *phydev) - { - int ret; - -+ if (!phydev_id_compare(phydev, QCA8081_PHY_ID)) -+ return false; -+ - ret = phy_read_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_CHIP_TYPE); - if (ret < 0) - return true; -@@ -273,6 +285,23 @@ static int qca808x_read_status(struct ph - return ret; - - if (phydev->link) { -+ /* There are two PCSes available for QCA8084, which support -+ * the following interface modes. -+ * -+ * 1. PHY_INTERFACE_MODE_10G_QXGMII utilizes PCS1 for all -+ * available 4 ports, which is for all link speeds. -+ * -+ * 2. PHY_INTERFACE_MODE_2500BASEX utilizes PCS0 for the -+ * fourth port, which is only for the link speed 2500M same -+ * as QCA8081. -+ * -+ * 3. PHY_INTERFACE_MODE_SGMII utilizes PCS0 for the fourth -+ * port, which is for the link speed 10M, 100M and 1000M same -+ * as QCA8081. -+ */ -+ if (phydev->interface == PHY_INTERFACE_MODE_10G_QXGMII) -+ return 0; -+ - if (phydev->speed == SPEED_2500) - phydev->interface = PHY_INTERFACE_MODE_2500BASEX; - else -@@ -352,6 +381,18 @@ static int qca808x_cable_test_start(stru - phy_write_mmd(phydev, MDIO_MMD_PCS, 0x807a, 0xc060); - phy_write_mmd(phydev, MDIO_MMD_PCS, 0x807e, 0xb060); - -+ if (phydev_id_compare(phydev, QCA8084_PHY_ID)) { -+ /* Adjust the positive and negative pulse thereshold of CDT. */ -+ phy_write_mmd(phydev, MDIO_MMD_PCS, -+ QCA8084_MMD3_CDT_PULSE_CTRL, -+ QCA8084_CDT_PULSE_THRESH_VAL); -+ -+ /* Disable the near bypass of CDT. */ -+ phy_modify_mmd(phydev, MDIO_MMD_PCS, -+ QCA8084_MMD3_CDT_NEAR_CTRL, -+ QCA8084_CDT_NEAR_BYPASS, 0); -+ } -+ - return 0; - } - -@@ -651,12 +692,32 @@ static struct phy_driver qca808x_driver[ - .led_hw_control_set = qca808x_led_hw_control_set, - .led_hw_control_get = qca808x_led_hw_control_get, - .led_polarity_set = qca808x_led_polarity_set, -+}, { -+ /* Qualcomm QCA8084 */ -+ PHY_ID_MATCH_MODEL(QCA8084_PHY_ID), -+ .name = "Qualcomm QCA8084", -+ .flags = PHY_POLL_CABLE_TEST, -+ .config_intr = at803x_config_intr, -+ .handle_interrupt = at803x_handle_interrupt, -+ .get_tunable = at803x_get_tunable, -+ .set_tunable = at803x_set_tunable, -+ .set_wol = at803x_set_wol, -+ .get_wol = at803x_get_wol, -+ .get_features = qca808x_get_features, -+ .config_aneg = qca808x_config_aneg, -+ .suspend = genphy_suspend, -+ .resume = genphy_resume, -+ .read_status = qca808x_read_status, -+ .soft_reset = qca808x_soft_reset, -+ .cable_test_start = qca808x_cable_test_start, -+ .cable_test_get_status = qca808x_cable_test_get_status, - }, }; - - module_phy_driver(qca808x_driver); - - static const struct mdio_device_id __maybe_unused qca808x_tbl[] = { - { PHY_ID_MATCH_EXACT(QCA8081_PHY_ID) }, -+ { PHY_ID_MATCH_MODEL(QCA8084_PHY_ID) }, - { } - }; - diff --git a/target/linux/qualcommbe/patches-6.12/0308-net-phy-qca808x-Add-config_init-function-for-QCA8084.patch b/target/linux/qualcommbe/patches-6.12/0308-net-phy-qca808x-Add-config_init-function-for-QCA8084.patch deleted file mode 100644 index 8ac94c84c7..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0308-net-phy-qca808x-Add-config_init-function-for-QCA8084.patch +++ /dev/null @@ -1,85 +0,0 @@ -From c052b9a4ab869cc54976402b3f9dbdef5bdb9f27 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Wed, 8 Nov 2023 16:18:02 +0800 -Subject: [PATCH] net: phy: qca808x: Add config_init function for QCA8084 - -1. The ADC of QCA8084 PHY must be configured as edge inverted -and falling whenever it is initialized or reset. In addition, -the default MSE (Mean square error) threshold value is adjusted, -which comes into play during link partner detection to detect -the valid link signal. - -2. Add the possible interface modes. - When QCA8084 works on the interface mode SGMII or 2500BASE-X, the - interface mode can be switched according to the PHY link speed. - - When QCA8084 works on the 10G-QXGMII mode, which will be the only - possible interface mode. - -Change-Id: I832c0d0b069e95cc411a8a7b680a5f60e1d6041a -Signed-off-by: Luo Jie ---- - drivers/net/phy/qcom/qca808x.c | 38 ++++++++++++++++++++++++++++++++++ - 1 file changed, 38 insertions(+) - ---- a/drivers/net/phy/qcom/qca808x.c -+++ b/drivers/net/phy/qcom/qca808x.c -@@ -94,6 +94,15 @@ - #define QCA8084_MMD3_CDT_NEAR_CTRL 0x807f - #define QCA8084_CDT_NEAR_BYPASS BIT(15) - -+/* QCA8084 ADC clock edge */ -+#define QCA8084_ADC_CLK_SEL 0x8b80 -+#define QCA8084_ADC_CLK_SEL_ACLK GENMASK(7, 4) -+#define QCA8084_ADC_CLK_SEL_ACLK_FALL 0xf -+#define QCA8084_ADC_CLK_SEL_ACLK_RISE 0x0 -+ -+#define QCA8084_MSE_THRESHOLD 0x800a -+#define QCA8084_MSE_THRESHOLD_2P5G_VAL 0x51c6 -+ - MODULE_DESCRIPTION("Qualcomm Atheros QCA808X PHY driver"); - MODULE_AUTHOR("Matus Ujhelyi, Luo Jie"); - MODULE_LICENSE("GPL"); -@@ -663,6 +672,34 @@ static int qca808x_led_polarity_set(stru - active_low ? 0 : QCA808X_LED_ACTIVE_HIGH); - } - -+static int qca8084_config_init(struct phy_device *phydev) -+{ -+ int ret; -+ -+ if (phydev->interface == PHY_INTERFACE_MODE_10G_QXGMII) -+ __set_bit(PHY_INTERFACE_MODE_10G_QXGMII, -+ phydev->possible_interfaces); -+ else -+ qca808x_fill_possible_interfaces(phydev); -+ -+ /* Configure the ADC to convert the signal using falling edge -+ * instead of the default rising edge. -+ */ -+ ret = at803x_debug_reg_mask(phydev, QCA8084_ADC_CLK_SEL, -+ QCA8084_ADC_CLK_SEL_ACLK, -+ FIELD_PREP(QCA8084_ADC_CLK_SEL_ACLK, -+ QCA8084_ADC_CLK_SEL_ACLK_FALL)); -+ if (ret < 0) -+ return ret; -+ -+ /* Adjust MSE threshold value to avoid link issue with -+ * some link partner. -+ */ -+ return phy_write_mmd(phydev, MDIO_MMD_PMAPMD, -+ QCA8084_MSE_THRESHOLD, -+ QCA8084_MSE_THRESHOLD_2P5G_VAL); -+} -+ - static struct phy_driver qca808x_driver[] = { - { - /* Qualcomm QCA8081 */ -@@ -711,6 +748,7 @@ static struct phy_driver qca808x_driver[ - .soft_reset = qca808x_soft_reset, - .cable_test_start = qca808x_cable_test_start, - .cable_test_get_status = qca808x_cable_test_get_status, -+ .config_init = qca8084_config_init, - }, }; - - module_phy_driver(qca808x_driver); diff --git a/target/linux/qualcommbe/patches-6.12/0309-net-phy-qca808x-Add-link_change_notify-function-for-.patch b/target/linux/qualcommbe/patches-6.12/0309-net-phy-qca808x-Add-link_change_notify-function-for-.patch deleted file mode 100644 index e00a582831..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0309-net-phy-qca808x-Add-link_change_notify-function-for-.patch +++ /dev/null @@ -1,90 +0,0 @@ -From aec49c172cd9c739c1d97ff2d42b9718bb20b609 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Wed, 8 Nov 2023 18:01:14 +0800 -Subject: [PATCH] net: phy: qca808x: Add link_change_notify function for - QCA8084 - -When the link is changed, QCA8084 needs to do the fifo reset and -adjust the IPG level for the 10G-QXGMII link on the speed 1000M. - -Change-Id: I21de802c78496fb95f1c5119fe3894c9fdebbd65 -Signed-off-by: Luo Jie ---- - drivers/net/phy/qcom/qca808x.c | 52 ++++++++++++++++++++++++++++++++++ - 1 file changed, 52 insertions(+) - ---- a/drivers/net/phy/qcom/qca808x.c -+++ b/drivers/net/phy/qcom/qca808x.c -@@ -103,6 +103,14 @@ - #define QCA8084_MSE_THRESHOLD 0x800a - #define QCA8084_MSE_THRESHOLD_2P5G_VAL 0x51c6 - -+/* QCA8084 FIFO reset control */ -+#define QCA8084_FIFO_CONTROL 0x19 -+#define QCA8084_FIFO_MAC_2_PHY BIT(1) -+#define QCA8084_FIFO_PHY_2_MAC BIT(0) -+ -+#define QCA8084_MMD7_IPG_OP 0x901d -+#define QCA8084_IPG_10_TO_11_EN BIT(0) -+ - MODULE_DESCRIPTION("Qualcomm Atheros QCA808X PHY driver"); - MODULE_AUTHOR("Matus Ujhelyi, Luo Jie"); - MODULE_LICENSE("GPL"); -@@ -700,6 +708,49 @@ static int qca8084_config_init(struct ph - QCA8084_MSE_THRESHOLD_2P5G_VAL); - } - -+static void qca8084_link_change_notify(struct phy_device *phydev) -+{ -+ int ret; -+ -+ /* Assert the FIFO between PHY and MAC. */ -+ ret = phy_modify(phydev, QCA8084_FIFO_CONTROL, -+ QCA8084_FIFO_MAC_2_PHY | QCA8084_FIFO_PHY_2_MAC, -+ 0); -+ if (ret) { -+ phydev_err(phydev, "Asserting PHY FIFO failed\n"); -+ return; -+ } -+ -+ /* If the PHY is in 10G_QXGMII mode, the FIFO needs to be kept in -+ * reset state when link is down, otherwise the FIFO needs to be -+ * de-asserted after waiting 50 ms to make the assert completed. -+ */ -+ if (phydev->interface != PHY_INTERFACE_MODE_10G_QXGMII || -+ phydev->link) { -+ msleep(50); -+ -+ /* Deassert the FIFO between PHY and MAC. */ -+ ret = phy_modify(phydev, QCA8084_FIFO_CONTROL, -+ QCA8084_FIFO_MAC_2_PHY | -+ QCA8084_FIFO_PHY_2_MAC, -+ QCA8084_FIFO_MAC_2_PHY | -+ QCA8084_FIFO_PHY_2_MAC); -+ if (ret) { -+ phydev_err(phydev, "De-asserting PHY FIFO failed\n"); -+ return; -+ } -+ } -+ -+ /* Enable IPG level 10 to 11 tuning for link speed 1000M in the -+ * 10G_QXGMII mode. -+ */ -+ if (phydev->interface == PHY_INTERFACE_MODE_10G_QXGMII) -+ phy_modify_mmd(phydev, MDIO_MMD_AN, QCA8084_MMD7_IPG_OP, -+ QCA8084_IPG_10_TO_11_EN, -+ phydev->speed == SPEED_1000 ? -+ QCA8084_IPG_10_TO_11_EN : 0); -+} -+ - static struct phy_driver qca808x_driver[] = { - { - /* Qualcomm QCA8081 */ -@@ -749,6 +800,7 @@ static struct phy_driver qca808x_driver[ - .cable_test_start = qca808x_cable_test_start, - .cable_test_get_status = qca808x_cable_test_get_status, - .config_init = qca8084_config_init, -+ .link_change_notify = qca8084_link_change_notify, - }, }; - - module_phy_driver(qca808x_driver); diff --git a/target/linux/qualcommbe/patches-6.12/0310-net-phy-qca808x-Add-register-access-support-routines.patch b/target/linux/qualcommbe/patches-6.12/0310-net-phy-qca808x-Add-register-access-support-routines.patch deleted file mode 100644 index c1673ae645..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0310-net-phy-qca808x-Add-register-access-support-routines.patch +++ /dev/null @@ -1,125 +0,0 @@ -From cea8043def0c0867370c2efd5a1cd73bf4d3e5ba Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Wed, 29 Nov 2023 15:21:22 +0800 -Subject: [PATCH] net: phy: qca808x: Add register access support routines for - QCA8084 - -QCA8084 integrates clock controller and security control modules -besides of the PHY and PCS. The 32bit registers in these modules -are accessed using special MDIO sequences to read or write these -registers. - -The MDIO address of PHY and PCS are configured by writing to the -security control register. The package mode for QCA8084 is also -configured in a similar manner. - -Change-Id: I9317307ef9bbc738a6adcbc3ea1be8e6528d711e -Signed-off-by: Luo Jie ---- - drivers/net/phy/qcom/qca808x.c | 88 ++++++++++++++++++++++++++++++++++ - 1 file changed, 88 insertions(+) - ---- a/drivers/net/phy/qcom/qca808x.c -+++ b/drivers/net/phy/qcom/qca808x.c -@@ -111,6 +111,22 @@ - #define QCA8084_MMD7_IPG_OP 0x901d - #define QCA8084_IPG_10_TO_11_EN BIT(0) - -+/* QCA8084 includes secure control module, which supports customizing the -+ * MDIO address of PHY device and PCS device and configuring package mode -+ * for the interface mode of PCS. The register of secure control is accessed -+ * by MDIO bus with the special MDIO sequences, where the 32 bits register -+ * address is split into 3 MDIO operations with 16 bits address. -+ */ -+#define QCA8084_HIGH_ADDR_PREFIX 0x18 -+#define QCA8084_LOW_ADDR_PREFIX 0x10 -+ -+/* Bottom two bits of REG must be zero */ -+#define QCA8084_MII_REG_MASK GENMASK(4, 0) -+#define QCA8084_MII_PHY_ADDR_MASK GENMASK(7, 5) -+#define QCA8084_MII_PAGE_MASK GENMASK(23, 8) -+#define QCA8084_MII_SW_ADDR_MASK GENMASK(31, 24) -+#define QCA8084_MII_REG_DATA_UPPER_16_BITS BIT(1) -+ - MODULE_DESCRIPTION("Qualcomm Atheros QCA808X PHY driver"); - MODULE_AUTHOR("Matus Ujhelyi, Luo Jie"); - MODULE_LICENSE("GPL"); -@@ -119,6 +135,78 @@ struct qca808x_priv { - int led_polarity_mode; - }; - -+static int __qca8084_set_page(struct mii_bus *bus, u16 sw_addr, u16 page) -+{ -+ return __mdiobus_write(bus, QCA8084_HIGH_ADDR_PREFIX | (sw_addr >> 5), -+ sw_addr & 0x1f, page); -+} -+ -+static int __qca8084_mii_read(struct mii_bus *bus, u16 addr, u16 reg, u32 *val) -+{ -+ int ret, data; -+ -+ ret = __mdiobus_read(bus, addr, reg); -+ if (ret < 0) -+ return ret; -+ -+ data = ret; -+ ret = __mdiobus_read(bus, addr, -+ reg | QCA8084_MII_REG_DATA_UPPER_16_BITS); -+ if (ret < 0) -+ return ret; -+ -+ *val = data | ret << 16; -+ -+ return 0; -+} -+ -+static int __qca8084_mii_write(struct mii_bus *bus, u16 addr, u16 reg, u32 val) -+{ -+ int ret; -+ -+ ret = __mdiobus_write(bus, addr, reg, lower_16_bits(val)); -+ if (!ret) -+ ret = __mdiobus_write(bus, addr, -+ reg | QCA8084_MII_REG_DATA_UPPER_16_BITS, -+ upper_16_bits(val)); -+ -+ return ret; -+} -+ -+static int qca8084_mii_modify(struct phy_device *phydev, u32 regaddr, -+ u32 clear, u32 set) -+{ -+ u16 reg, addr, page, sw_addr; -+ struct mii_bus *bus; -+ u32 val; -+ int ret; -+ -+ bus = phydev->mdio.bus; -+ mutex_lock(&bus->mdio_lock); -+ -+ reg = FIELD_GET(QCA8084_MII_REG_MASK, regaddr); -+ addr = FIELD_GET(QCA8084_MII_PHY_ADDR_MASK, regaddr); -+ page = FIELD_GET(QCA8084_MII_PAGE_MASK, regaddr); -+ sw_addr = FIELD_GET(QCA8084_MII_SW_ADDR_MASK, regaddr); -+ -+ ret = __qca8084_set_page(bus, sw_addr, page); -+ if (ret < 0) -+ goto qca8084_mii_modify_exit; -+ -+ ret = __qca8084_mii_read(bus, QCA8084_LOW_ADDR_PREFIX | addr, -+ reg, &val); -+ if (ret < 0) -+ goto qca8084_mii_modify_exit; -+ -+ val &= ~clear; -+ val |= set; -+ ret = __qca8084_mii_write(bus, QCA8084_LOW_ADDR_PREFIX | addr, -+ reg, val); -+qca8084_mii_modify_exit: -+ mutex_unlock(&bus->mdio_lock); -+ return ret; -+}; -+ - static int qca808x_phy_fast_retrain_config(struct phy_device *phydev) - { - int ret; diff --git a/target/linux/qualcommbe/patches-6.12/0311-net-phy-qca808x-Add-QCA8084-probe-function.patch b/target/linux/qualcommbe/patches-6.12/0311-net-phy-qca808x-Add-QCA8084-probe-function.patch deleted file mode 100644 index e74fc0b09f..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0311-net-phy-qca808x-Add-QCA8084-probe-function.patch +++ /dev/null @@ -1,162 +0,0 @@ -From a7fe2c13f3188bf01b60fb15063d028c76dd2f1a Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Mon, 29 Jan 2024 10:51:38 +0800 -Subject: [PATCH] net: phy: qca808x: Add QCA8084 probe function - -Add the PHY package probe function. The MDIO slave address of -PHY, PCS and XPCS can be optionally customized by configuring -the PHY package level register. - -In addition, enable system clock of PHY and de-assert PHY in -the probe function so that the register of PHY device can be -accessed, and the features of PHY can be acquired. - -Change-Id: I2251b9c5c398a21a4ef547a727189a934ad3a44c -Signed-off-by: Luo Jie -Alex G: include - include "phylib.h" for phy_package_*() declarations - select PHY_PACKAGE in Kconfig - use phy_package_get_node() instead of phylib->shared->np -Signed-off-by: Alexandru Gagniuc - -freckup c89414adf2ec7c - -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/phy/qcom/Kconfig | 1 + - drivers/net/phy/qcom/qca808x.c | 92 ++++++++++++++++++++++++++++++++++ - 2 files changed, 93 insertions(+) - ---- a/drivers/net/phy/qcom/Kconfig -+++ b/drivers/net/phy/qcom/Kconfig -@@ -18,6 +18,7 @@ config QCA83XX_PHY - config QCA808X_PHY - tristate "Qualcomm QCA808x PHYs" - select QCOM_NET_PHYLIB -+ select PHY_PACKAGE - help - Currently supports the QCA8081 model - ---- a/drivers/net/phy/qcom/qca808x.c -+++ b/drivers/net/phy/qcom/qca808x.c -@@ -2,7 +2,11 @@ - - #include - #include -+#include -+#include -+#include - -+#include "../phylib.h" - #include "qcom.h" - - /* ADC threshold */ -@@ -127,6 +131,21 @@ - #define QCA8084_MII_SW_ADDR_MASK GENMASK(31, 24) - #define QCA8084_MII_REG_DATA_UPPER_16_BITS BIT(1) - -+/* QCA8084 integrates 4 PHYs, PCS0 and PCS1(includes PCS and XPCS). */ -+#define QCA8084_MDIO_DEVICE_NUM 7 -+ -+#define QCA8084_PCS_CFG 0xc90f014 -+#define QCA8084_PCS_ADDR0_MASK GENMASK(4, 0) -+#define QCA8084_PCS_ADDR1_MASK GENMASK(9, 5) -+#define QCA8084_PCS_ADDR2_MASK GENMASK(14, 10) -+ -+#define QCA8084_EPHY_CFG 0xc90f018 -+#define QCA8084_EPHY_ADDR0_MASK GENMASK(4, 0) -+#define QCA8084_EPHY_ADDR1_MASK GENMASK(9, 5) -+#define QCA8084_EPHY_ADDR2_MASK GENMASK(14, 10) -+#define QCA8084_EPHY_ADDR3_MASK GENMASK(19, 15) -+#define QCA8084_EPHY_LDO_EN GENMASK(21, 20) -+ - MODULE_DESCRIPTION("Qualcomm Atheros QCA808X PHY driver"); - MODULE_AUTHOR("Matus Ujhelyi, Luo Jie"); - MODULE_LICENSE("GPL"); -@@ -839,6 +858,78 @@ static void qca8084_link_change_notify(s - QCA8084_IPG_10_TO_11_EN : 0); - } - -+static int qca8084_phy_package_probe_once(struct phy_device *phydev) -+{ -+ int addr[QCA8084_MDIO_DEVICE_NUM] = {0, 1, 2, 3, 4, 5, 6}; -+ struct device_node *np = phy_package_get_node(phydev); -+ int ret, clear, set; -+ -+ /* Program the MDIO address of PHY and PCS optionally, the MDIO -+ * address 0-6 is used for PHY and PCS MDIO devices by default. -+ */ -+ ret = of_property_read_u32_array(np, "qcom,phy-addr-fixup", -+ addr, ARRAY_SIZE(addr)); -+ if (ret && ret != -EINVAL) -+ return ret; -+ -+ /* Configure the MDIO addresses for the four PHY devices. */ -+ clear = QCA8084_EPHY_ADDR0_MASK | QCA8084_EPHY_ADDR1_MASK | -+ QCA8084_EPHY_ADDR2_MASK | QCA8084_EPHY_ADDR3_MASK; -+ set = FIELD_PREP(QCA8084_EPHY_ADDR0_MASK, addr[0]); -+ set |= FIELD_PREP(QCA8084_EPHY_ADDR1_MASK, addr[1]); -+ set |= FIELD_PREP(QCA8084_EPHY_ADDR2_MASK, addr[2]); -+ set |= FIELD_PREP(QCA8084_EPHY_ADDR3_MASK, addr[3]); -+ -+ ret = qca8084_mii_modify(phydev, QCA8084_EPHY_CFG, clear, set); -+ if (ret) -+ return ret; -+ -+ /* Configure the MDIO addresses for PCS0 and PCS1 including -+ * PCS and XPCS. -+ */ -+ clear = QCA8084_PCS_ADDR0_MASK | QCA8084_PCS_ADDR1_MASK | -+ QCA8084_PCS_ADDR2_MASK; -+ set = FIELD_PREP(QCA8084_PCS_ADDR0_MASK, addr[4]); -+ set |= FIELD_PREP(QCA8084_PCS_ADDR1_MASK, addr[5]); -+ set |= FIELD_PREP(QCA8084_PCS_ADDR2_MASK, addr[6]); -+ -+ return qca8084_mii_modify(phydev, QCA8084_PCS_CFG, clear, set); -+} -+ -+static int qca8084_probe(struct phy_device *phydev) -+{ -+ struct device *dev = &phydev->mdio.dev; -+ struct reset_control *rstc; -+ struct clk *clk; -+ int ret; -+ -+ ret = devm_of_phy_package_join(dev, phydev, 0); -+ if (ret) -+ return ret; -+ -+ if (phy_package_probe_once(phydev)) { -+ ret = qca8084_phy_package_probe_once(phydev); -+ if (ret) -+ return ret; -+ } -+ -+ /* Enable clock of PHY device, so that the PHY register -+ * can be accessed to get PHY features. -+ */ -+ clk = devm_clk_get_enabled(dev, NULL); -+ if (IS_ERR(clk)) -+ return dev_err_probe(dev, PTR_ERR(clk), -+ "Enable PHY clock failed\n"); -+ -+ /* De-assert PHY reset after the clock of PHY enabled. */ -+ rstc = devm_reset_control_get_exclusive(dev, NULL); -+ if (IS_ERR(rstc)) -+ return dev_err_probe(dev, PTR_ERR(rstc), -+ "Get PHY reset failed\n"); -+ -+ return reset_control_deassert(rstc); -+} -+ - static struct phy_driver qca808x_driver[] = { - { - /* Qualcomm QCA8081 */ -@@ -889,6 +980,7 @@ static struct phy_driver qca808x_driver[ - .cable_test_get_status = qca808x_cable_test_get_status, - .config_init = qca8084_config_init, - .link_change_notify = qca8084_link_change_notify, -+ .probe = qca8084_probe, - }, }; - - module_phy_driver(qca808x_driver); diff --git a/target/linux/qualcommbe/patches-6.12/0312-net-phy-qca808x-Add-package-clocks-and-resets-for-QC.patch b/target/linux/qualcommbe/patches-6.12/0312-net-phy-qca808x-Add-package-clocks-and-resets-for-QC.patch deleted file mode 100644 index 50346520b3..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0312-net-phy-qca808x-Add-package-clocks-and-resets-for-QC.patch +++ /dev/null @@ -1,135 +0,0 @@ -From 57379fe257895b374d35ce6578ecd62ce1cc1a4d Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Tue, 9 Apr 2024 16:30:55 +0800 -Subject: [PATCH] net: phy: qca808x: Add package clocks and resets for QCA8084 - -Parse the PHY package clocks from the PHY package DTS node. -These package level clocks will be enabled in the PHY package -init function. - -Deassert PHY package reset, which is necessary for accessing -the PHY registers. - -Change-Id: I254d0aa0a1155d3618c6f1fc7d7a5b6ecadccbaa -Signed-off-by: Luo Jie -Alex G: Use accessors for struct phy_package_shared - Update to match the patches that will be upstream. -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/phy/qcom/qca808x.c | 74 ++++++++++++++++++++++++++++++++-- - 1 file changed, 71 insertions(+), 3 deletions(-) - ---- a/drivers/net/phy/qcom/qca808x.c -+++ b/drivers/net/phy/qcom/qca808x.c -@@ -150,10 +150,39 @@ MODULE_DESCRIPTION("Qualcomm Atheros QCA - MODULE_AUTHOR("Matus Ujhelyi, Luo Jie"); - MODULE_LICENSE("GPL"); - -+enum { -+ APB_BRIDGE_CLK, -+ AHB_CLK, -+ SEC_CTRL_AHB_CLK, -+ TLMM_CLK, -+ TLMM_AHB_CLK, -+ CNOC_AHB_CLK, -+ MDIO_AHB_CLK, -+ MDIO_MASTER_AHB_CLK, -+ SWITCH_CORE_CLK, -+ PACKAGE_CLK_MAX -+}; -+ - struct qca808x_priv { - int led_polarity_mode; - }; - -+struct qca808x_shared_priv { -+ struct clk *clk[PACKAGE_CLK_MAX]; -+}; -+ -+static const char *const qca8084_package_clk_name[PACKAGE_CLK_MAX] = { -+ [APB_BRIDGE_CLK] = "apb_bridge", -+ [AHB_CLK] = "ahb", -+ [SEC_CTRL_AHB_CLK] = "sec_ctrl_ahb", -+ [TLMM_CLK] = "tlmm", -+ [TLMM_AHB_CLK] = "tlmm_ahb", -+ [CNOC_AHB_CLK] = "cnoc_ahb", -+ [MDIO_AHB_CLK] = "mdio_ahb", -+ [MDIO_MASTER_AHB_CLK] = "mdio_master_ahb", -+ [SWITCH_CORE_CLK] = "switch_core", -+}; -+ - static int __qca8084_set_page(struct mii_bus *bus, u16 sw_addr, u16 page) - { - return __mdiobus_write(bus, QCA8084_HIGH_ADDR_PREFIX | (sw_addr >> 5), -@@ -858,11 +887,24 @@ static void qca8084_link_change_notify(s - QCA8084_IPG_10_TO_11_EN : 0); - } - -+/* QCA8084 is a four-port PHY, which integrates the clock controller, -+ * 4 PHY devices and 2 PCS interfaces (PCS0 and PCS1). PCS1 includes -+ * XPCS and PCS to support 10G-QXGMII and SGMII. PCS0 includes one PCS -+ * to support SGMII. -+ * -+ * The clocks and resets are sourced from the integrated clock controller -+ * of the PHY package. This integrated clock controller is driven by a -+ * QCA8K clock provider that supplies the clocks and resets to the four -+ * PHYs, PCS and PHY package. -+ */ - static int qca8084_phy_package_probe_once(struct phy_device *phydev) - { - int addr[QCA8084_MDIO_DEVICE_NUM] = {0, 1, 2, 3, 4, 5, 6}; - struct device_node *np = phy_package_get_node(phydev); -- int ret, clear, set; -+ struct qca808x_shared_priv *shared_priv; -+ struct reset_control *rstc; -+ int i, ret, clear, set; -+ struct clk *clk; - - /* Program the MDIO address of PHY and PCS optionally, the MDIO - * address 0-6 is used for PHY and PCS MDIO devices by default. -@@ -893,17 +935,43 @@ static int qca8084_phy_package_probe_onc - set |= FIELD_PREP(QCA8084_PCS_ADDR1_MASK, addr[5]); - set |= FIELD_PREP(QCA8084_PCS_ADDR2_MASK, addr[6]); - -- return qca8084_mii_modify(phydev, QCA8084_PCS_CFG, clear, set); -+ ret = qca8084_mii_modify(phydev, QCA8084_PCS_CFG, clear, set); -+ if (ret) -+ return ret; -+ -+ shared_priv = phy_package_get_priv(phydev); -+ for (i = 0; i < ARRAY_SIZE(qca8084_package_clk_name); i++) { -+ clk = of_clk_get_by_name(np, qca8084_package_clk_name[i]); -+ if (IS_ERR(clk)) { -+ if (PTR_ERR(clk) == -EINVAL) -+ clk = NULL; -+ else -+ return dev_err_probe(&phydev->mdio.dev, PTR_ERR(clk), -+ "package clock %s not ready\n", -+ qca8084_package_clk_name[i]); -+ } -+ -+ shared_priv->clk[i] = clk; -+ } -+ -+ rstc = of_reset_control_get_exclusive(np, NULL); -+ if (IS_ERR(rstc)) -+ return dev_err_probe(&phydev->mdio.dev, PTR_ERR(rstc), -+ "package reset not ready\n"); -+ -+ /* Deassert PHY package. */ -+ return reset_control_deassert(rstc); - } - - static int qca8084_probe(struct phy_device *phydev) - { -+ struct qca808x_shared_priv *shared_priv; - struct device *dev = &phydev->mdio.dev; - struct reset_control *rstc; - struct clk *clk; - int ret; - -- ret = devm_of_phy_package_join(dev, phydev, 0); -+ ret = devm_of_phy_package_join(dev, phydev, sizeof(*shared_priv)); - if (ret) - return ret; - diff --git a/target/linux/qualcommbe/patches-6.12/0313-net-phy-qca808x-Add-QCA8084-package-init-function.patch b/target/linux/qualcommbe/patches-6.12/0313-net-phy-qca808x-Add-QCA8084-package-init-function.patch deleted file mode 100644 index 5af66c290f..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0313-net-phy-qca808x-Add-QCA8084-package-init-function.patch +++ /dev/null @@ -1,177 +0,0 @@ -From d39dc53424bcc778f1e468015490577e7bf0c7b6 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Thu, 25 Jan 2024 17:13:24 +0800 -Subject: [PATCH] net: phy: qca808x: Add QCA8084 package init function - -The package mode of PHY is configured for the interface mode of two -PCSes working correctly. - -The PHY package level clocks are enabled and their rates configured. - -Change-Id: I63d4b22d2a70ee713cc6a6818b0f3c7aa098a5f5 -Signed-off-by: Luo Jie -Alex G: Use phy_package_get_*() accessors - Update to match the patches that will be upstream. -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/phy/qcom/qca808x.c | 118 +++++++++++++++++++++++++++++++++ - 1 file changed, 118 insertions(+) - ---- a/drivers/net/phy/qcom/qca808x.c -+++ b/drivers/net/phy/qcom/qca808x.c -@@ -1,5 +1,6 @@ - // SPDX-License-Identifier: GPL-2.0+ - -+#include - #include - #include - #include -@@ -146,6 +147,12 @@ - #define QCA8084_EPHY_ADDR3_MASK GENMASK(19, 15) - #define QCA8084_EPHY_LDO_EN GENMASK(21, 20) - -+#define QCA8084_WORK_MODE_CFG 0xc90f030 -+#define QCA8084_WORK_MODE_MASK GENMASK(5, 0) -+#define QCA8084_WORK_MODE_QXGMII (BIT(5) | GENMASK(3, 0)) -+#define QCA8084_WORK_MODE_SWITCH BIT(4) -+#define QCA8084_WORK_MODE_SWITCH_PORT4_SGMII BIT(5) -+ - MODULE_DESCRIPTION("Qualcomm Atheros QCA808X PHY driver"); - MODULE_AUTHOR("Matus Ujhelyi, Luo Jie"); - MODULE_LICENSE("GPL"); -@@ -168,6 +175,7 @@ struct qca808x_priv { - }; - - struct qca808x_shared_priv { -+ int package_mode; - struct clk *clk[PACKAGE_CLK_MAX]; - }; - -@@ -816,10 +824,111 @@ static int qca808x_led_polarity_set(stru - active_low ? 0 : QCA808X_LED_ACTIVE_HIGH); - } - -+static int qca8084_package_clock_init(struct qca808x_shared_priv *shared_priv) -+{ -+ int ret; -+ -+ /* Configure clock rate 312.5MHZ for the PHY package -+ * APB bridge clock tree. -+ */ -+ ret = clk_set_rate(shared_priv->clk[APB_BRIDGE_CLK], 312500000); -+ if (ret) -+ return ret; -+ -+ ret = clk_prepare_enable(shared_priv->clk[SWITCH_CORE_CLK]); -+ if (ret) -+ return ret; -+ -+ ret = clk_prepare_enable(shared_priv->clk[APB_BRIDGE_CLK]); -+ if (ret) -+ return ret; -+ -+ /* Configure clock rate 104.17MHZ for the PHY package -+ * AHB clock tree. -+ */ -+ ret = clk_set_rate(shared_priv->clk[AHB_CLK], 104170000); -+ if (ret) -+ return ret; -+ -+ ret = clk_prepare_enable(shared_priv->clk[AHB_CLK]); -+ if (ret) -+ return ret; -+ -+ ret = clk_prepare_enable(shared_priv->clk[SEC_CTRL_AHB_CLK]); -+ if (ret) -+ return ret; -+ -+ ret = clk_prepare_enable(shared_priv->clk[TLMM_CLK]); -+ if (ret) -+ return ret; -+ -+ ret = clk_prepare_enable(shared_priv->clk[TLMM_AHB_CLK]); -+ if (ret) -+ return ret; -+ -+ ret = clk_prepare_enable(shared_priv->clk[CNOC_AHB_CLK]); -+ if (ret) -+ return ret; -+ -+ ret = clk_prepare_enable(shared_priv->clk[MDIO_MASTER_AHB_CLK]); -+ if (ret) -+ return ret; -+ -+ return clk_prepare_enable(shared_priv->clk[MDIO_AHB_CLK]); -+} -+ -+static int qca8084_phy_package_config_init_once(struct phy_device *phydev) -+{ -+ struct qca808x_shared_priv *shared_priv; -+ int ret, mode; -+ -+ shared_priv = phy_package_get_priv(phydev); -+ switch (shared_priv->package_mode) { -+ case QCA808X_PCS1_10G_QXGMII_PCS0_UNUNSED: -+ mode = QCA8084_WORK_MODE_QXGMII; -+ break; -+ case QCA808X_PCS1_SGMII_MAC_PCS0_SGMII_MAC: -+ mode = QCA8084_WORK_MODE_SWITCH; -+ break; -+ case QCA808X_PCS1_SGMII_MAC_PCS0_SGMII_PHY: -+ mode = QCA8084_WORK_MODE_SWITCH_PORT4_SGMII; -+ break; -+ default: -+ phydev_err(phydev, "Invalid qcom,package-mode %d\n", -+ shared_priv->package_mode); -+ return -EINVAL; -+ } -+ -+ ret = qca8084_mii_modify(phydev, QCA8084_WORK_MODE_CFG, -+ QCA8084_WORK_MODE_MASK, -+ FIELD_PREP(QCA8084_WORK_MODE_MASK, mode)); -+ if (ret) -+ return ret; -+ -+ /* Enable efuse loading into analog circuit */ -+ ret = qca8084_mii_modify(phydev, QCA8084_EPHY_CFG, -+ QCA8084_EPHY_LDO_EN, 0); -+ if (ret) -+ return ret; -+ -+ usleep_range(10000, 11000); -+ -+ /* Initialize the PHY package clock and reset, which is the -+ * necessary config sequence after GPIO reset on the PHY package. -+ */ -+ return qca8084_package_clock_init(shared_priv); -+} -+ - static int qca8084_config_init(struct phy_device *phydev) - { - int ret; - -+ if (phy_package_init_once(phydev)) { -+ ret = qca8084_phy_package_config_init_once(phydev); -+ if (ret) -+ return ret; -+ } -+ - if (phydev->interface == PHY_INTERFACE_MODE_10G_QXGMII) - __set_bit(PHY_INTERFACE_MODE_10G_QXGMII, - phydev->possible_interfaces); -@@ -954,6 +1063,15 @@ static int qca8084_phy_package_probe_onc - shared_priv->clk[i] = clk; - } - -+ /* The package mode 10G-QXGMII of PCS1 is used for Quad PHY and -+ * PCS0 is unused by default. -+ */ -+ shared_priv->package_mode = QCA808X_PCS1_10G_QXGMII_PCS0_UNUNSED; -+ ret = of_property_read_u32(np, "qcom,package-mode", -+ &shared_priv->package_mode); -+ if (ret && ret != -EINVAL) -+ return ret; -+ - rstc = of_reset_control_get_exclusive(np, NULL); - if (IS_ERR(rstc)) - return dev_err_probe(&phydev->mdio.dev, PTR_ERR(rstc), diff --git a/target/linux/qualcommbe/patches-6.12/0314-dt-bindings-net-pcs-Add-Ethernet-PCS-for-Qualcomm-IP.patch b/target/linux/qualcommbe/patches-6.12/0314-dt-bindings-net-pcs-Add-Ethernet-PCS-for-Qualcomm-IP.patch deleted file mode 100644 index 1112d4e072..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0314-dt-bindings-net-pcs-Add-Ethernet-PCS-for-Qualcomm-IP.patch +++ /dev/null @@ -1,234 +0,0 @@ -From 5f650721c4b232a14a1a3e25b686f2234faee961 Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Fri, 7 Feb 2025 23:53:12 +0800 -Subject: [PATCH] dt-bindings: net: pcs: Add Ethernet PCS for Qualcomm IPQ9574 - SoC - -The 'UNIPHY' PCS block in the IPQ9574 SoC includes PCS and SerDes -functions. It supports different interface modes to enable Ethernet -MAC connections to different types of external PHYs/switch. It includes -PCS functions for 1Gbps and 2.5Gbps interface modes and XPCS functions -for 10Gbps interface modes. There are three UNIPHY (PCS) instances -in IPQ9574 SoC which provide PCS/XPCS functions to the six Ethernet -ports. - -Reviewed-by: Krzysztof Kozlowski -Signed-off-by: Lei Wei ---- - .../bindings/net/pcs/qcom,ipq9574-pcs.yaml | 190 ++++++++++++++++++ - include/dt-bindings/net/qcom,ipq9574-pcs.h | 15 ++ - 2 files changed, 205 insertions(+) - create mode 100644 Documentation/devicetree/bindings/net/pcs/qcom,ipq9574-pcs.yaml - create mode 100644 include/dt-bindings/net/qcom,ipq9574-pcs.h - ---- /dev/null -+++ b/Documentation/devicetree/bindings/net/pcs/qcom,ipq9574-pcs.yaml -@@ -0,0 +1,190 @@ -+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/net/pcs/qcom,ipq9574-pcs.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Ethernet PCS for Qualcomm IPQ9574 SoC -+ -+maintainers: -+ - Lei Wei -+ -+description: -+ The UNIPHY hardware blocks in the Qualcomm IPQ SoC include PCS and SerDes -+ functions. They enable connectivity between the Ethernet MAC inside the -+ PPE (packet processing engine) and external Ethernet PHY/switch. There are -+ three UNIPHY instances in IPQ9574 SoC which provide PCS functions to the -+ six Ethernet ports. -+ -+ For SGMII (1Gbps PHY) or 2500BASE-X (2.5Gbps PHY) interface modes, the PCS -+ function is enabled by using the PCS block inside UNIPHY. For USXGMII (10Gbps -+ PHY), the XPCS block in UNIPHY is used. -+ -+ The SerDes provides 125M (1Gbps mode) or 312.5M (2.5Gbps and 10Gbps modes) -+ RX and TX clocks to the NSSCC (Networking Sub System Clock Controller). The -+ NSSCC divides these clocks and generates the MII RX and TX clocks to each -+ of the MII interfaces between the PCS and MAC, as per the link speeds and -+ interface modes. -+ -+ Different IPQ SoC may support different number of UNIPHYs (PCSes) since the -+ number of ports and their capabilities can be different between these SoCs -+ -+ Below diagram depicts the UNIPHY (PCS) connections for an IPQ9574 SoC based -+ board. In this example, the PCS0 has four GMIIs/XGMIIs, which can connect -+ with four MACs to support QSGMII (4 x 1Gbps) or 10G_QXGMII (4 x 2.5Gbps) -+ interface modes. -+ -+ - +-------+ +---------+ +-------------------------+ -+ +---------+CMN PLL| | GCC | | NSSCC (Divider) | -+ | +----+--+ +----+----+ +--+-------+--------------+ -+ | | | ^ | -+ | 31.25M | SYS/AHB|clk RX/TX|clk +------------+ -+ | ref clk| | | | | -+ | | v | MII RX|TX clk MAC| RX/TX clk -+ |25/50M +--+---------+----------+-------+---+ +-+---------+ -+ |ref clk | | +----------------+ | | | | PPE | -+ v | | | UNIPHY0 V | | V | -+ +-------+ | v | +-----------+ (X)GMII| | | -+ | | | +---+---+ | |--------|------|-- MAC0 | -+ | | | | | | | (X)GMII| | | -+ | Quad | | |SerDes | | PCS/XPCS |--------|------|-- MAC1 | -+ | +<----+ | | | | (X)GMII| | | -+ |(X)GPHY| | | | | |--------|------|-- MAC2 | -+ | | | | | | | (X)GMII| | | -+ | | | +-------+ | |--------|------|-- MAC3 | -+ +-------+ | | | | | | -+ | +-----------+ | | | -+ +-----------------------------------+ | | -+ +--+---------+----------+-------+---+ | | -+ +-------+ | UNIPHY1 | | | -+ | | | +-----------+ | | | -+ |(X)GPHY| | +-------+ | | (X)GMII| | | -+ | +<----+ |SerDes | | PCS/XPCS |--------|------|- MAC4 | -+ | | | | | | | | | | -+ +-------+ | +-------+ | | | | | -+ | +-----------+ | | | -+ +-----------------------------------+ | | -+ +--+---------+----------+-------+---+ | | -+ +-------+ | UNIPHY2 | | | -+ | | | +-----------+ | | | -+ |(X)GPHY| | +-------+ | | (X)GMII| | | -+ | +<----+ |SerDes | | PCS/XPCS |--------|------|- MAC5 | -+ | | | | | | | | | | -+ +-------+ | +-------+ | | | | | -+ | +-----------+ | | | -+ +-----------------------------------+ +-----------+ -+ -+properties: -+ compatible: -+ enum: -+ - qcom,ipq9574-pcs -+ -+ reg: -+ maxItems: 1 -+ -+ '#address-cells': -+ const: 1 -+ -+ '#size-cells': -+ const: 0 -+ -+ clocks: -+ items: -+ - description: System clock -+ - description: AHB clock needed for register interface access -+ -+ clock-names: -+ items: -+ - const: sys -+ - const: ahb -+ -+ '#clock-cells': -+ const: 1 -+ description: See include/dt-bindings/net/qcom,ipq9574-pcs.h for constants -+ -+patternProperties: -+ '^pcs-mii@[0-4]$': -+ type: object -+ description: PCS MII interface. -+ -+ properties: -+ reg: -+ minimum: 0 -+ maximum: 4 -+ description: MII index -+ -+ clocks: -+ items: -+ - description: PCS MII RX clock -+ - description: PCS MII TX clock -+ -+ clock-names: -+ items: -+ - const: rx -+ - const: tx -+ -+ required: -+ - reg -+ - clocks -+ - clock-names -+ -+ additionalProperties: false -+ -+required: -+ - compatible -+ - reg -+ - '#address-cells' -+ - '#size-cells' -+ - clocks -+ - clock-names -+ - '#clock-cells' -+ -+additionalProperties: false -+ -+examples: -+ - | -+ #include -+ -+ ethernet-pcs@7a00000 { -+ compatible = "qcom,ipq9574-pcs"; -+ reg = <0x7a00000 0x10000>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ clocks = <&gcc GCC_UNIPHY0_SYS_CLK>, -+ <&gcc GCC_UNIPHY0_AHB_CLK>; -+ clock-names = "sys", -+ "ahb"; -+ #clock-cells = <1>; -+ -+ pcs-mii@0 { -+ reg = <0>; -+ clocks = <&nsscc 116>, -+ <&nsscc 117>; -+ clock-names = "rx", -+ "tx"; -+ }; -+ -+ pcs-mii@1 { -+ reg = <1>; -+ clocks = <&nsscc 118>, -+ <&nsscc 119>; -+ clock-names = "rx", -+ "tx"; -+ }; -+ -+ pcs-mii@2 { -+ reg = <2>; -+ clocks = <&nsscc 120>, -+ <&nsscc 121>; -+ clock-names = "rx", -+ "tx"; -+ }; -+ -+ pcs-mii@3 { -+ reg = <3>; -+ clocks = <&nsscc 122>, -+ <&nsscc 123>; -+ clock-names = "rx", -+ "tx"; -+ }; -+ }; ---- /dev/null -+++ b/include/dt-bindings/net/qcom,ipq9574-pcs.h -@@ -0,0 +1,15 @@ -+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ -+/* -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ * -+ * Device Tree constants for the Qualcomm IPQ9574 PCS -+ */ -+ -+#ifndef _DT_BINDINGS_PCS_QCOM_IPQ9574_H -+#define _DT_BINDINGS_PCS_QCOM_IPQ9574_H -+ -+/* The RX and TX clocks which are provided from the SerDes to NSSCC. */ -+#define PCS_RX_CLK 0 -+#define PCS_TX_CLK 1 -+ -+#endif /* _DT_BINDINGS_PCS_QCOM_IPQ9574_H */ diff --git a/target/linux/qualcommbe/patches-6.12/0315-net-pcs-Add-PCS-driver-for-Qualcomm-IPQ9574-SoC.patch b/target/linux/qualcommbe/patches-6.12/0315-net-pcs-Add-PCS-driver-for-Qualcomm-IPQ9574-SoC.patch deleted file mode 100644 index eb0750cf4e..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0315-net-pcs-Add-PCS-driver-for-Qualcomm-IPQ9574-SoC.patch +++ /dev/null @@ -1,301 +0,0 @@ -From e404519d9f3e5e7d661cb105d3766d87e37e4ef5 Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Fri, 7 Feb 2025 23:53:13 +0800 -Subject: [PATCH] net: pcs: Add PCS driver for Qualcomm IPQ9574 SoC - -The 'UNIPHY' PCS hardware block in Qualcomm's IPQ SoC supports -different interface modes to enable Ethernet MAC connections -for different types of external PHYs/switch. Each UNIPHY block -includes a SerDes and PCS/XPCS blocks, and can operate in either -PCS or XPCS modes. It supports 1Gbps and 2.5Gbps interface modes -(Ex: SGMII) using the PCS, and 10Gbps interface modes (Ex: USXGMII) -using the XPCS. There are three UNIPHY (PCS) instances in IPQ9574 -SoC which support the six Ethernet ports in the SoC. - -This patch adds support for the platform driver, probe and clock -registrations for the PCS driver. The platform driver creates an -'ipq_pcs' instance for each of the UNIPHY used on the given board. - -Signed-off-by: Lei Wei ---- - drivers/net/pcs/Kconfig | 9 ++ - drivers/net/pcs/Makefile | 1 + - drivers/net/pcs/pcs-qcom-ipq9574.c | 245 +++++++++++++++++++++++++++++ - 3 files changed, 255 insertions(+) - create mode 100644 drivers/net/pcs/pcs-qcom-ipq9574.c - ---- a/drivers/net/pcs/Kconfig -+++ b/drivers/net/pcs/Kconfig -@@ -43,6 +43,15 @@ config PCS_MTK_USXGMII - 1000Base-X, 2500Base-X and Cisco SGMII are supported on the same - differential pairs via an embedded LynxI PHY. - -+config PCS_QCOM_IPQ9574 -+ tristate "Qualcomm IPQ9574 PCS" -+ depends on OF && (ARCH_QCOM || COMPILE_TEST) -+ depends on HAS_IOMEM && COMMON_CLK -+ help -+ This module provides driver for UNIPHY PCS available on Qualcomm -+ IPQ9574 SoC. The UNIPHY PCS supports both PCS and XPCS functions -+ to support different interface modes for MAC to PHY connections. -+ - config PCS_RZN1_MIIC - tristate "Renesas RZ/N1 MII converter" - depends on OF && (ARCH_RZN1 || COMPILE_TEST) ---- a/drivers/net/pcs/Makefile -+++ b/drivers/net/pcs/Makefile -@@ -8,5 +8,6 @@ pcs_xpcs-$(CONFIG_PCS_XPCS) := pcs-xpcs. - obj-$(CONFIG_PCS_XPCS) += pcs_xpcs.o - obj-$(CONFIG_PCS_LYNX) += pcs-lynx.o - obj-$(CONFIG_PCS_MTK_LYNXI) += pcs-mtk-lynxi.o -+obj-$(CONFIG_PCS_QCOM_IPQ9574) += pcs-qcom-ipq9574.o - obj-$(CONFIG_PCS_RZN1_MIIC) += pcs-rzn1-miic.o - obj-$(CONFIG_PCS_MTK_USXGMII) += pcs-mtk-usxgmii.o ---- /dev/null -+++ b/drivers/net/pcs/pcs-qcom-ipq9574.c -@@ -0,0 +1,245 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#define XPCS_INDIRECT_ADDR 0x8000 -+#define XPCS_INDIRECT_AHB_ADDR 0x83fc -+#define XPCS_INDIRECT_ADDR_H GENMASK(20, 8) -+#define XPCS_INDIRECT_ADDR_L GENMASK(7, 0) -+#define XPCS_INDIRECT_DATA_ADDR(reg) (FIELD_PREP(GENMASK(15, 10), 0x20) | \ -+ FIELD_PREP(GENMASK(9, 2), \ -+ FIELD_GET(XPCS_INDIRECT_ADDR_L, reg))) -+ -+/* PCS private data */ -+struct ipq_pcs { -+ struct device *dev; -+ void __iomem *base; -+ struct regmap *regmap; -+ phy_interface_t interface; -+ -+ /* RX clock supplied to NSSCC */ -+ struct clk_hw rx_hw; -+ /* TX clock supplied to NSSCC */ -+ struct clk_hw tx_hw; -+}; -+ -+static unsigned long ipq_pcs_clk_rate_get(struct ipq_pcs *qpcs) -+{ -+ switch (qpcs->interface) { -+ case PHY_INTERFACE_MODE_USXGMII: -+ return 312500000; -+ default: -+ return 125000000; -+ } -+} -+ -+/* Return clock rate for the RX clock supplied to NSSCC -+ * as per the interface mode. -+ */ -+static unsigned long ipq_pcs_rx_clk_recalc_rate(struct clk_hw *hw, -+ unsigned long parent_rate) -+{ -+ struct ipq_pcs *qpcs = container_of(hw, struct ipq_pcs, rx_hw); -+ -+ return ipq_pcs_clk_rate_get(qpcs); -+} -+ -+/* Return clock rate for the TX clock supplied to NSSCC -+ * as per the interface mode. -+ */ -+static unsigned long ipq_pcs_tx_clk_recalc_rate(struct clk_hw *hw, -+ unsigned long parent_rate) -+{ -+ struct ipq_pcs *qpcs = container_of(hw, struct ipq_pcs, tx_hw); -+ -+ return ipq_pcs_clk_rate_get(qpcs); -+} -+ -+static int ipq_pcs_clk_determine_rate(struct clk_hw *hw, -+ struct clk_rate_request *req) -+{ -+ switch (req->rate) { -+ case 125000000: -+ case 312500000: -+ return 0; -+ default: -+ return -EINVAL; -+ } -+} -+ -+/* Clock ops for the RX clock supplied to NSSCC */ -+static const struct clk_ops ipq_pcs_rx_clk_ops = { -+ .determine_rate = ipq_pcs_clk_determine_rate, -+ .recalc_rate = ipq_pcs_rx_clk_recalc_rate, -+}; -+ -+/* Clock ops for the TX clock supplied to NSSCC */ -+static const struct clk_ops ipq_pcs_tx_clk_ops = { -+ .determine_rate = ipq_pcs_clk_determine_rate, -+ .recalc_rate = ipq_pcs_tx_clk_recalc_rate, -+}; -+ -+static struct clk_hw *ipq_pcs_clk_hw_get(struct of_phandle_args *clkspec, -+ void *data) -+{ -+ struct ipq_pcs *qpcs = data; -+ -+ switch (clkspec->args[0]) { -+ case PCS_RX_CLK: -+ return &qpcs->rx_hw; -+ case PCS_TX_CLK: -+ return &qpcs->tx_hw; -+ } -+ -+ return ERR_PTR(-EINVAL); -+} -+ -+/* Register the RX and TX clock which are output from SerDes to -+ * the NSSCC. The NSSCC driver assigns the RX and TX clock as -+ * parent, divides them to generate the MII RX and TX clock to -+ * each MII interface of the PCS as per the link speeds and -+ * interface modes. -+ */ -+static int ipq_pcs_clk_register(struct ipq_pcs *qpcs) -+{ -+ struct clk_init_data init = { }; -+ int ret; -+ -+ init.ops = &ipq_pcs_rx_clk_ops; -+ init.name = devm_kasprintf(qpcs->dev, GFP_KERNEL, "%s::rx_clk", -+ dev_name(qpcs->dev)); -+ if (!init.name) -+ return -ENOMEM; -+ -+ qpcs->rx_hw.init = &init; -+ ret = devm_clk_hw_register(qpcs->dev, &qpcs->rx_hw); -+ if (ret) -+ return ret; -+ -+ init.ops = &ipq_pcs_tx_clk_ops; -+ init.name = devm_kasprintf(qpcs->dev, GFP_KERNEL, "%s::tx_clk", -+ dev_name(qpcs->dev)); -+ if (!init.name) -+ return -ENOMEM; -+ -+ qpcs->tx_hw.init = &init; -+ ret = devm_clk_hw_register(qpcs->dev, &qpcs->tx_hw); -+ if (ret) -+ return ret; -+ -+ return devm_of_clk_add_hw_provider(qpcs->dev, ipq_pcs_clk_hw_get, qpcs); -+} -+ -+static int ipq_pcs_regmap_read(void *context, unsigned int reg, -+ unsigned int *val) -+{ -+ struct ipq_pcs *qpcs = context; -+ -+ /* PCS uses direct AHB access while XPCS uses indirect AHB access */ -+ if (reg >= XPCS_INDIRECT_ADDR) { -+ writel(FIELD_GET(XPCS_INDIRECT_ADDR_H, reg), -+ qpcs->base + XPCS_INDIRECT_AHB_ADDR); -+ *val = readl(qpcs->base + XPCS_INDIRECT_DATA_ADDR(reg)); -+ } else { -+ *val = readl(qpcs->base + reg); -+ } -+ -+ return 0; -+} -+ -+static int ipq_pcs_regmap_write(void *context, unsigned int reg, -+ unsigned int val) -+{ -+ struct ipq_pcs *qpcs = context; -+ -+ /* PCS uses direct AHB access while XPCS uses indirect AHB access */ -+ if (reg >= XPCS_INDIRECT_ADDR) { -+ writel(FIELD_GET(XPCS_INDIRECT_ADDR_H, reg), -+ qpcs->base + XPCS_INDIRECT_AHB_ADDR); -+ writel(val, qpcs->base + XPCS_INDIRECT_DATA_ADDR(reg)); -+ } else { -+ writel(val, qpcs->base + reg); -+ } -+ -+ return 0; -+} -+ -+static const struct regmap_config ipq_pcs_regmap_cfg = { -+ .reg_bits = 32, -+ .val_bits = 32, -+ .reg_read = ipq_pcs_regmap_read, -+ .reg_write = ipq_pcs_regmap_write, -+ .fast_io = true, -+}; -+ -+static int ipq9574_pcs_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct ipq_pcs *qpcs; -+ struct clk *clk; -+ int ret; -+ -+ qpcs = devm_kzalloc(dev, sizeof(*qpcs), GFP_KERNEL); -+ if (!qpcs) -+ return -ENOMEM; -+ -+ qpcs->dev = dev; -+ -+ qpcs->base = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(qpcs->base)) -+ return dev_err_probe(dev, PTR_ERR(qpcs->base), -+ "Failed to ioremap resource\n"); -+ -+ qpcs->regmap = devm_regmap_init(dev, NULL, qpcs, &ipq_pcs_regmap_cfg); -+ if (IS_ERR(qpcs->regmap)) -+ return dev_err_probe(dev, PTR_ERR(qpcs->regmap), -+ "Failed to allocate register map\n"); -+ -+ clk = devm_clk_get_enabled(dev, "sys"); -+ if (IS_ERR(clk)) -+ return dev_err_probe(dev, PTR_ERR(clk), -+ "Failed to enable SYS clock\n"); -+ -+ clk = devm_clk_get_enabled(dev, "ahb"); -+ if (IS_ERR(clk)) -+ return dev_err_probe(dev, PTR_ERR(clk), -+ "Failed to enable AHB clock\n"); -+ -+ ret = ipq_pcs_clk_register(qpcs); -+ if (ret) -+ return ret; -+ -+ platform_set_drvdata(pdev, qpcs); -+ -+ return 0; -+} -+ -+static const struct of_device_id ipq9574_pcs_of_mtable[] = { -+ { .compatible = "qcom,ipq9574-pcs" }, -+ { /* sentinel */ }, -+}; -+MODULE_DEVICE_TABLE(of, ipq9574_pcs_of_mtable); -+ -+static struct platform_driver ipq9574_pcs_driver = { -+ .driver = { -+ .name = "ipq9574_pcs", -+ .suppress_bind_attrs = true, -+ .of_match_table = ipq9574_pcs_of_mtable, -+ }, -+ .probe = ipq9574_pcs_probe, -+}; -+module_platform_driver(ipq9574_pcs_driver); -+ -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("Qualcomm IPQ9574 PCS driver"); -+MODULE_AUTHOR("Lei Wei "); diff --git a/target/linux/qualcommbe/patches-6.12/0316-net-pcs-qcom-ipq9574-Add-PCS-instantiation-and-phyli.patch b/target/linux/qualcommbe/patches-6.12/0316-net-pcs-qcom-ipq9574-Add-PCS-instantiation-and-phyli.patch deleted file mode 100644 index 7d071c2e25..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0316-net-pcs-qcom-ipq9574-Add-PCS-instantiation-and-phyli.patch +++ /dev/null @@ -1,555 +0,0 @@ -From 10b609ddbf4d369c80098efa39451ef3973759b5 Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Fri, 7 Feb 2025 23:53:14 +0800 -Subject: [PATCH] net: pcs: qcom-ipq9574: Add PCS instantiation and phylink - operations - -This patch adds the following PCS functionality for the PCS driver -for IPQ9574 SoC: - -a.) Parses PCS MII DT nodes and instantiate each MII PCS instance. -b.) Exports PCS instance get and put APIs. The network driver calls -the PCS get API to get and associate the PCS instance with the port -MAC. -c.) PCS phylink operations for SGMII/QSGMII interface modes. - -Signed-off-by: Lei Wei -Alex G: remove phylink_pcs .neg_mode boolean -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/pcs/pcs-qcom-ipq9574.c | 468 +++++++++++++++++++++++++++ - include/linux/pcs/pcs-qcom-ipq9574.h | 15 + - 2 files changed, 483 insertions(+) - create mode 100644 include/linux/pcs/pcs-qcom-ipq9574.h - ---- a/drivers/net/pcs/pcs-qcom-ipq9574.c -+++ b/drivers/net/pcs/pcs-qcom-ipq9574.c -@@ -6,12 +6,46 @@ - #include - #include - #include -+#include -+#include -+#include - #include -+#include - #include - #include - - #include - -+/* Maximum number of MIIs per PCS instance. There are 5 MIIs for PSGMII. */ -+#define PCS_MAX_MII_NRS 5 -+ -+#define PCS_CALIBRATION 0x1e0 -+#define PCS_CALIBRATION_DONE BIT(7) -+ -+#define PCS_MODE_CTRL 0x46c -+#define PCS_MODE_SEL_MASK GENMASK(12, 8) -+#define PCS_MODE_SGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x4) -+#define PCS_MODE_QSGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x1) -+ -+#define PCS_MII_CTRL(x) (0x480 + 0x18 * (x)) -+#define PCS_MII_ADPT_RESET BIT(11) -+#define PCS_MII_FORCE_MODE BIT(3) -+#define PCS_MII_SPEED_MASK GENMASK(2, 1) -+#define PCS_MII_SPEED_1000 FIELD_PREP(PCS_MII_SPEED_MASK, 0x2) -+#define PCS_MII_SPEED_100 FIELD_PREP(PCS_MII_SPEED_MASK, 0x1) -+#define PCS_MII_SPEED_10 FIELD_PREP(PCS_MII_SPEED_MASK, 0x0) -+ -+#define PCS_MII_STS(x) (0x488 + 0x18 * (x)) -+#define PCS_MII_LINK_STS BIT(7) -+#define PCS_MII_STS_DUPLEX_FULL BIT(6) -+#define PCS_MII_STS_SPEED_MASK GENMASK(5, 4) -+#define PCS_MII_STS_SPEED_10 0 -+#define PCS_MII_STS_SPEED_100 1 -+#define PCS_MII_STS_SPEED_1000 2 -+ -+#define PCS_PLL_RESET 0x780 -+#define PCS_ANA_SW_RESET BIT(6) -+ - #define XPCS_INDIRECT_ADDR 0x8000 - #define XPCS_INDIRECT_AHB_ADDR 0x83fc - #define XPCS_INDIRECT_ADDR_H GENMASK(20, 8) -@@ -20,6 +54,18 @@ - FIELD_PREP(GENMASK(9, 2), \ - FIELD_GET(XPCS_INDIRECT_ADDR_L, reg))) - -+/* Per PCS MII private data */ -+struct ipq_pcs_mii { -+ struct ipq_pcs *qpcs; -+ struct phylink_pcs pcs; -+ int index; -+ -+ /* RX clock from NSSCC to PCS MII */ -+ struct clk *rx_clk; -+ /* TX clock from NSSCC to PCS MII */ -+ struct clk *tx_clk; -+}; -+ - /* PCS private data */ - struct ipq_pcs { - struct device *dev; -@@ -31,8 +77,358 @@ struct ipq_pcs { - struct clk_hw rx_hw; - /* TX clock supplied to NSSCC */ - struct clk_hw tx_hw; -+ -+ struct ipq_pcs_mii *qpcs_mii[PCS_MAX_MII_NRS]; - }; - -+#define phylink_pcs_to_qpcs_mii(_pcs) \ -+ container_of(_pcs, struct ipq_pcs_mii, pcs) -+ -+static void ipq_pcs_get_state_sgmii(struct ipq_pcs *qpcs, -+ int index, -+ struct phylink_link_state *state) -+{ -+ unsigned int val; -+ int ret; -+ -+ ret = regmap_read(qpcs->regmap, PCS_MII_STS(index), &val); -+ if (ret) { -+ state->link = 0; -+ return; -+ } -+ -+ state->link = !!(val & PCS_MII_LINK_STS); -+ -+ if (!state->link) -+ return; -+ -+ switch (FIELD_GET(PCS_MII_STS_SPEED_MASK, val)) { -+ case PCS_MII_STS_SPEED_1000: -+ state->speed = SPEED_1000; -+ break; -+ case PCS_MII_STS_SPEED_100: -+ state->speed = SPEED_100; -+ break; -+ case PCS_MII_STS_SPEED_10: -+ state->speed = SPEED_10; -+ break; -+ default: -+ state->link = false; -+ return; -+ } -+ -+ if (val & PCS_MII_STS_DUPLEX_FULL) -+ state->duplex = DUPLEX_FULL; -+ else -+ state->duplex = DUPLEX_HALF; -+} -+ -+static int ipq_pcs_config_mode(struct ipq_pcs *qpcs, -+ phy_interface_t interface) -+{ -+ unsigned int val; -+ int ret; -+ -+ /* Configure PCS interface mode */ -+ switch (interface) { -+ case PHY_INTERFACE_MODE_SGMII: -+ val = PCS_MODE_SGMII; -+ break; -+ case PHY_INTERFACE_MODE_QSGMII: -+ val = PCS_MODE_QSGMII; -+ break; -+ default: -+ return -EOPNOTSUPP; -+ } -+ -+ ret = regmap_update_bits(qpcs->regmap, PCS_MODE_CTRL, -+ PCS_MODE_SEL_MASK, val); -+ if (ret) -+ return ret; -+ -+ /* PCS PLL reset */ -+ ret = regmap_clear_bits(qpcs->regmap, PCS_PLL_RESET, PCS_ANA_SW_RESET); -+ if (ret) -+ return ret; -+ -+ fsleep(1000); -+ ret = regmap_set_bits(qpcs->regmap, PCS_PLL_RESET, PCS_ANA_SW_RESET); -+ if (ret) -+ return ret; -+ -+ /* Wait for calibration completion */ -+ ret = regmap_read_poll_timeout(qpcs->regmap, PCS_CALIBRATION, -+ val, val & PCS_CALIBRATION_DONE, -+ 1000, 100000); -+ if (ret) { -+ dev_err(qpcs->dev, "PCS calibration timed-out\n"); -+ return ret; -+ } -+ -+ qpcs->interface = interface; -+ -+ return 0; -+} -+ -+static int ipq_pcs_config_sgmii(struct ipq_pcs *qpcs, -+ int index, -+ unsigned int neg_mode, -+ phy_interface_t interface) -+{ -+ int ret; -+ -+ /* Configure the PCS mode if required */ -+ if (qpcs->interface != interface) { -+ ret = ipq_pcs_config_mode(qpcs, interface); -+ if (ret) -+ return ret; -+ } -+ -+ /* Nothing to do here as in-band autoneg mode is enabled -+ * by default for each PCS MII port. -+ */ -+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) -+ return 0; -+ -+ /* Set force speed mode */ -+ return regmap_set_bits(qpcs->regmap, -+ PCS_MII_CTRL(index), PCS_MII_FORCE_MODE); -+} -+ -+static int ipq_pcs_link_up_config_sgmii(struct ipq_pcs *qpcs, -+ int index, -+ unsigned int neg_mode, -+ int speed) -+{ -+ unsigned int val; -+ int ret; -+ -+ /* PCS speed need not be configured if in-band autoneg is enabled */ -+ if (neg_mode != PHYLINK_PCS_NEG_INBAND_ENABLED) { -+ /* PCS speed set for force mode */ -+ switch (speed) { -+ case SPEED_1000: -+ val = PCS_MII_SPEED_1000; -+ break; -+ case SPEED_100: -+ val = PCS_MII_SPEED_100; -+ break; -+ case SPEED_10: -+ val = PCS_MII_SPEED_10; -+ break; -+ default: -+ dev_err(qpcs->dev, "Invalid SGMII speed %d\n", speed); -+ return -EINVAL; -+ } -+ -+ ret = regmap_update_bits(qpcs->regmap, PCS_MII_CTRL(index), -+ PCS_MII_SPEED_MASK, val); -+ if (ret) -+ return ret; -+ } -+ -+ /* PCS adapter reset */ -+ ret = regmap_clear_bits(qpcs->regmap, -+ PCS_MII_CTRL(index), PCS_MII_ADPT_RESET); -+ if (ret) -+ return ret; -+ -+ return regmap_set_bits(qpcs->regmap, -+ PCS_MII_CTRL(index), PCS_MII_ADPT_RESET); -+} -+ -+static int ipq_pcs_validate(struct phylink_pcs *pcs, unsigned long *supported, -+ const struct phylink_link_state *state) -+{ -+ switch (state->interface) { -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_QSGMII: -+ return 0; -+ default: -+ return -EINVAL; -+ } -+} -+ -+static unsigned int ipq_pcs_inband_caps(struct phylink_pcs *pcs, -+ phy_interface_t interface) -+{ -+ switch (interface) { -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_QSGMII: -+ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; -+ default: -+ return 0; -+ } -+} -+ -+static int ipq_pcs_enable(struct phylink_pcs *pcs) -+{ -+ struct ipq_pcs_mii *qpcs_mii = phylink_pcs_to_qpcs_mii(pcs); -+ struct ipq_pcs *qpcs = qpcs_mii->qpcs; -+ int index = qpcs_mii->index; -+ int ret; -+ -+ ret = clk_prepare_enable(qpcs_mii->rx_clk); -+ if (ret) { -+ dev_err(qpcs->dev, "Failed to enable MII %d RX clock\n", index); -+ return ret; -+ } -+ -+ ret = clk_prepare_enable(qpcs_mii->tx_clk); -+ if (ret) { -+ /* This is a fatal event since phylink does not support unwinding -+ * the state back for this error. So, we only report the error -+ * and do not disable the clocks. -+ */ -+ dev_err(qpcs->dev, "Failed to enable MII %d TX clock\n", index); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static void ipq_pcs_disable(struct phylink_pcs *pcs) -+{ -+ struct ipq_pcs_mii *qpcs_mii = phylink_pcs_to_qpcs_mii(pcs); -+ -+ clk_disable_unprepare(qpcs_mii->rx_clk); -+ clk_disable_unprepare(qpcs_mii->tx_clk); -+} -+ -+static void ipq_pcs_get_state(struct phylink_pcs *pcs, -+ struct phylink_link_state *state) -+{ -+ struct ipq_pcs_mii *qpcs_mii = phylink_pcs_to_qpcs_mii(pcs); -+ struct ipq_pcs *qpcs = qpcs_mii->qpcs; -+ int index = qpcs_mii->index; -+ -+ switch (state->interface) { -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_QSGMII: -+ ipq_pcs_get_state_sgmii(qpcs, index, state); -+ break; -+ default: -+ break; -+ } -+ -+ dev_dbg_ratelimited(qpcs->dev, -+ "mode=%s/%s/%s link=%u\n", -+ phy_modes(state->interface), -+ phy_speed_to_str(state->speed), -+ phy_duplex_to_str(state->duplex), -+ state->link); -+} -+ -+static int ipq_pcs_config(struct phylink_pcs *pcs, -+ unsigned int neg_mode, -+ phy_interface_t interface, -+ const unsigned long *advertising, -+ bool permit) -+{ -+ struct ipq_pcs_mii *qpcs_mii = phylink_pcs_to_qpcs_mii(pcs); -+ struct ipq_pcs *qpcs = qpcs_mii->qpcs; -+ int index = qpcs_mii->index; -+ -+ switch (interface) { -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_QSGMII: -+ return ipq_pcs_config_sgmii(qpcs, index, neg_mode, interface); -+ default: -+ return -EOPNOTSUPP; -+ }; -+} -+ -+static void ipq_pcs_link_up(struct phylink_pcs *pcs, -+ unsigned int neg_mode, -+ phy_interface_t interface, -+ int speed, int duplex) -+{ -+ struct ipq_pcs_mii *qpcs_mii = phylink_pcs_to_qpcs_mii(pcs); -+ struct ipq_pcs *qpcs = qpcs_mii->qpcs; -+ int index = qpcs_mii->index; -+ int ret; -+ -+ switch (interface) { -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_QSGMII: -+ ret = ipq_pcs_link_up_config_sgmii(qpcs, index, -+ neg_mode, speed); -+ break; -+ default: -+ return; -+ } -+ -+ if (ret) -+ dev_err(qpcs->dev, "PCS link up fail for interface %s\n", -+ phy_modes(interface)); -+} -+ -+static const struct phylink_pcs_ops ipq_pcs_phylink_ops = { -+ .pcs_validate = ipq_pcs_validate, -+ .pcs_inband_caps = ipq_pcs_inband_caps, -+ .pcs_enable = ipq_pcs_enable, -+ .pcs_disable = ipq_pcs_disable, -+ .pcs_get_state = ipq_pcs_get_state, -+ .pcs_config = ipq_pcs_config, -+ .pcs_link_up = ipq_pcs_link_up, -+}; -+ -+/* Parse the PCS MII DT nodes which are child nodes of the PCS node, -+ * and instantiate each MII PCS instance. -+ */ -+static int ipq_pcs_create_miis(struct ipq_pcs *qpcs) -+{ -+ struct device *dev = qpcs->dev; -+ struct ipq_pcs_mii *qpcs_mii; -+ struct device_node *mii_np; -+ u32 index; -+ int ret; -+ -+ for_each_available_child_of_node(dev->of_node, mii_np) { -+ ret = of_property_read_u32(mii_np, "reg", &index); -+ if (ret) { -+ dev_err(dev, "Failed to read MII index\n"); -+ of_node_put(mii_np); -+ return ret; -+ } -+ -+ if (index >= PCS_MAX_MII_NRS) { -+ dev_err(dev, "Invalid MII index\n"); -+ of_node_put(mii_np); -+ return -EINVAL; -+ } -+ -+ qpcs_mii = devm_kzalloc(dev, sizeof(*qpcs_mii), GFP_KERNEL); -+ if (!qpcs_mii) { -+ of_node_put(mii_np); -+ return -ENOMEM; -+ } -+ -+ qpcs_mii->qpcs = qpcs; -+ qpcs_mii->index = index; -+ qpcs_mii->pcs.ops = &ipq_pcs_phylink_ops; -+ qpcs_mii->pcs.poll = true; -+ -+ qpcs_mii->rx_clk = devm_get_clk_from_child(dev, mii_np, "rx"); -+ if (IS_ERR(qpcs_mii->rx_clk)) { -+ of_node_put(mii_np); -+ return dev_err_probe(dev, PTR_ERR(qpcs_mii->rx_clk), -+ "Failed to get MII %d RX clock\n", index); -+ } -+ -+ qpcs_mii->tx_clk = devm_get_clk_from_child(dev, mii_np, "tx"); -+ if (IS_ERR(qpcs_mii->tx_clk)) { -+ of_node_put(mii_np); -+ return dev_err_probe(dev, PTR_ERR(qpcs_mii->tx_clk), -+ "Failed to get MII %d TX clock\n", index); -+ } -+ -+ qpcs->qpcs_mii[index] = qpcs_mii; -+ } -+ -+ return 0; -+} -+ - static unsigned long ipq_pcs_clk_rate_get(struct ipq_pcs *qpcs) - { - switch (qpcs->interface) { -@@ -219,6 +615,10 @@ static int ipq9574_pcs_probe(struct plat - if (ret) - return ret; - -+ ret = ipq_pcs_create_miis(qpcs); -+ if (ret) -+ return ret; -+ - platform_set_drvdata(pdev, qpcs); - - return 0; -@@ -230,6 +630,74 @@ static const struct of_device_id ipq9574 - }; - MODULE_DEVICE_TABLE(of, ipq9574_pcs_of_mtable); - -+/** -+ * ipq_pcs_get() - Get the IPQ PCS MII instance -+ * @np: Device tree node to the PCS MII -+ * -+ * Description: Get the phylink PCS instance for the given PCS MII node @np. -+ * This instance is associated with the specific MII of the PCS and the -+ * corresponding Ethernet netdevice. -+ * -+ * Return: A pointer to the phylink PCS instance or an error-pointer value. -+ */ -+struct phylink_pcs *ipq_pcs_get(struct device_node *np) -+{ -+ struct platform_device *pdev; -+ struct ipq_pcs_mii *qpcs_mii; -+ struct ipq_pcs *qpcs; -+ u32 index; -+ -+ if (of_property_read_u32(np, "reg", &index)) -+ return ERR_PTR(-EINVAL); -+ -+ if (index >= PCS_MAX_MII_NRS) -+ return ERR_PTR(-EINVAL); -+ -+ if (!of_match_node(ipq9574_pcs_of_mtable, np->parent)) -+ return ERR_PTR(-EINVAL); -+ -+ /* Get the parent device */ -+ pdev = of_find_device_by_node(np->parent); -+ if (!pdev) -+ return ERR_PTR(-ENODEV); -+ -+ qpcs = platform_get_drvdata(pdev); -+ if (!qpcs) { -+ put_device(&pdev->dev); -+ -+ /* If probe is not yet completed, return DEFER to -+ * the dependent driver. -+ */ -+ return ERR_PTR(-EPROBE_DEFER); -+ } -+ -+ qpcs_mii = qpcs->qpcs_mii[index]; -+ if (!qpcs_mii) { -+ put_device(&pdev->dev); -+ return ERR_PTR(-ENOENT); -+ } -+ -+ return &qpcs_mii->pcs; -+} -+EXPORT_SYMBOL(ipq_pcs_get); -+ -+/** -+ * ipq_pcs_put() - Release the IPQ PCS MII instance -+ * @pcs: PCS instance -+ * -+ * Description: Release a phylink PCS instance. -+ */ -+void ipq_pcs_put(struct phylink_pcs *pcs) -+{ -+ struct ipq_pcs_mii *qpcs_mii = phylink_pcs_to_qpcs_mii(pcs); -+ -+ /* Put reference taken by of_find_device_by_node() in -+ * ipq_pcs_get(). -+ */ -+ put_device(qpcs_mii->qpcs->dev); -+} -+EXPORT_SYMBOL(ipq_pcs_put); -+ - static struct platform_driver ipq9574_pcs_driver = { - .driver = { - .name = "ipq9574_pcs", ---- /dev/null -+++ b/include/linux/pcs/pcs-qcom-ipq9574.h -@@ -0,0 +1,15 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+/* -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#ifndef __LINUX_PCS_QCOM_IPQ9574_H -+#define __LINUX_PCS_QCOM_IPQ9574_H -+ -+struct device_node; -+struct phylink_pcs; -+ -+struct phylink_pcs *ipq_pcs_get(struct device_node *np); -+void ipq_pcs_put(struct phylink_pcs *pcs); -+ -+#endif /* __LINUX_PCS_QCOM_IPQ9574_H */ diff --git a/target/linux/qualcommbe/patches-6.12/0317-net-pcs-qcom-ipq9574-Add-USXGMII-interface-mode-supp.patch b/target/linux/qualcommbe/patches-6.12/0317-net-pcs-qcom-ipq9574-Add-USXGMII-interface-mode-supp.patch deleted file mode 100644 index b1cddffc6a..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0317-net-pcs-qcom-ipq9574-Add-USXGMII-interface-mode-supp.patch +++ /dev/null @@ -1,272 +0,0 @@ -From 4923ca63214a4e6bbee1b3f8f6b9b79f0fd3a3be Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Fri, 7 Feb 2025 23:53:15 +0800 -Subject: [PATCH] net: pcs: qcom-ipq9574: Add USXGMII interface mode support - -USXGMII mode is enabled by PCS when 10Gbps PHYs are connected, such as -Aquantia 10Gbps PHY. - -Signed-off-by: Lei Wei ---- - drivers/net/pcs/pcs-qcom-ipq9574.c | 170 +++++++++++++++++++++++++++++ - 1 file changed, 170 insertions(+) - ---- a/drivers/net/pcs/pcs-qcom-ipq9574.c -+++ b/drivers/net/pcs/pcs-qcom-ipq9574.c -@@ -26,6 +26,7 @@ - #define PCS_MODE_SEL_MASK GENMASK(12, 8) - #define PCS_MODE_SGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x4) - #define PCS_MODE_QSGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x1) -+#define PCS_MODE_XPCS FIELD_PREP(PCS_MODE_SEL_MASK, 0x10) - - #define PCS_MII_CTRL(x) (0x480 + 0x18 * (x)) - #define PCS_MII_ADPT_RESET BIT(11) -@@ -54,6 +55,34 @@ - FIELD_PREP(GENMASK(9, 2), \ - FIELD_GET(XPCS_INDIRECT_ADDR_L, reg))) - -+#define XPCS_DIG_CTRL 0x38000 -+#define XPCS_USXG_ADPT_RESET BIT(10) -+#define XPCS_USXG_EN BIT(9) -+ -+#define XPCS_MII_CTRL 0x1f0000 -+#define XPCS_MII_AN_EN BIT(12) -+#define XPCS_DUPLEX_FULL BIT(8) -+#define XPCS_SPEED_MASK (BIT(13) | BIT(6) | BIT(5)) -+#define XPCS_SPEED_10000 (BIT(13) | BIT(6)) -+#define XPCS_SPEED_5000 (BIT(13) | BIT(5)) -+#define XPCS_SPEED_2500 BIT(5) -+#define XPCS_SPEED_1000 BIT(6) -+#define XPCS_SPEED_100 BIT(13) -+#define XPCS_SPEED_10 0 -+ -+#define XPCS_MII_AN_CTRL 0x1f8001 -+#define XPCS_MII_AN_8BIT BIT(8) -+ -+#define XPCS_MII_AN_INTR_STS 0x1f8002 -+#define XPCS_USXG_AN_LINK_STS BIT(14) -+#define XPCS_USXG_AN_SPEED_MASK GENMASK(12, 10) -+#define XPCS_USXG_AN_SPEED_10 0 -+#define XPCS_USXG_AN_SPEED_100 1 -+#define XPCS_USXG_AN_SPEED_1000 2 -+#define XPCS_USXG_AN_SPEED_2500 4 -+#define XPCS_USXG_AN_SPEED_5000 5 -+#define XPCS_USXG_AN_SPEED_10000 3 -+ - /* Per PCS MII private data */ - struct ipq_pcs_mii { - struct ipq_pcs *qpcs; -@@ -123,9 +152,54 @@ static void ipq_pcs_get_state_sgmii(stru - state->duplex = DUPLEX_HALF; - } - -+static void ipq_pcs_get_state_usxgmii(struct ipq_pcs *qpcs, -+ struct phylink_link_state *state) -+{ -+ unsigned int val; -+ int ret; -+ -+ ret = regmap_read(qpcs->regmap, XPCS_MII_AN_INTR_STS, &val); -+ if (ret) { -+ state->link = 0; -+ return; -+ } -+ -+ state->link = !!(val & XPCS_USXG_AN_LINK_STS); -+ -+ if (!state->link) -+ return; -+ -+ switch (FIELD_GET(XPCS_USXG_AN_SPEED_MASK, val)) { -+ case XPCS_USXG_AN_SPEED_10000: -+ state->speed = SPEED_10000; -+ break; -+ case XPCS_USXG_AN_SPEED_5000: -+ state->speed = SPEED_5000; -+ break; -+ case XPCS_USXG_AN_SPEED_2500: -+ state->speed = SPEED_2500; -+ break; -+ case XPCS_USXG_AN_SPEED_1000: -+ state->speed = SPEED_1000; -+ break; -+ case XPCS_USXG_AN_SPEED_100: -+ state->speed = SPEED_100; -+ break; -+ case XPCS_USXG_AN_SPEED_10: -+ state->speed = SPEED_10; -+ break; -+ default: -+ state->link = false; -+ return; -+ } -+ -+ state->duplex = DUPLEX_FULL; -+} -+ - static int ipq_pcs_config_mode(struct ipq_pcs *qpcs, - phy_interface_t interface) - { -+ unsigned long rate = 125000000; - unsigned int val; - int ret; - -@@ -137,6 +211,10 @@ static int ipq_pcs_config_mode(struct ip - case PHY_INTERFACE_MODE_QSGMII: - val = PCS_MODE_QSGMII; - break; -+ case PHY_INTERFACE_MODE_USXGMII: -+ val = PCS_MODE_XPCS; -+ rate = 312500000; -+ break; - default: - return -EOPNOTSUPP; - } -@@ -167,6 +245,21 @@ static int ipq_pcs_config_mode(struct ip - - qpcs->interface = interface; - -+ /* Configure the RX and TX clock to NSSCC as 125M or 312.5M based -+ * on current interface mode. -+ */ -+ ret = clk_set_rate(qpcs->rx_hw.clk, rate); -+ if (ret) { -+ dev_err(qpcs->dev, "Failed to set RX clock rate\n"); -+ return ret; -+ } -+ -+ ret = clk_set_rate(qpcs->tx_hw.clk, rate); -+ if (ret) { -+ dev_err(qpcs->dev, "Failed to set TX clock rate\n"); -+ return ret; -+ } -+ - return 0; - } - -@@ -195,6 +288,29 @@ static int ipq_pcs_config_sgmii(struct i - PCS_MII_CTRL(index), PCS_MII_FORCE_MODE); - } - -+static int ipq_pcs_config_usxgmii(struct ipq_pcs *qpcs) -+{ -+ int ret; -+ -+ /* Configure the XPCS for USXGMII mode if required */ -+ if (qpcs->interface == PHY_INTERFACE_MODE_USXGMII) -+ return 0; -+ -+ ret = ipq_pcs_config_mode(qpcs, PHY_INTERFACE_MODE_USXGMII); -+ if (ret) -+ return ret; -+ -+ ret = regmap_set_bits(qpcs->regmap, XPCS_DIG_CTRL, XPCS_USXG_EN); -+ if (ret) -+ return ret; -+ -+ ret = regmap_set_bits(qpcs->regmap, XPCS_MII_AN_CTRL, XPCS_MII_AN_8BIT); -+ if (ret) -+ return ret; -+ -+ return regmap_set_bits(qpcs->regmap, XPCS_MII_CTRL, XPCS_MII_AN_EN); -+} -+ - static int ipq_pcs_link_up_config_sgmii(struct ipq_pcs *qpcs, - int index, - unsigned int neg_mode, -@@ -237,6 +353,46 @@ static int ipq_pcs_link_up_config_sgmii( - PCS_MII_CTRL(index), PCS_MII_ADPT_RESET); - } - -+static int ipq_pcs_link_up_config_usxgmii(struct ipq_pcs *qpcs, int speed) -+{ -+ unsigned int val; -+ int ret; -+ -+ switch (speed) { -+ case SPEED_10000: -+ val = XPCS_SPEED_10000; -+ break; -+ case SPEED_5000: -+ val = XPCS_SPEED_5000; -+ break; -+ case SPEED_2500: -+ val = XPCS_SPEED_2500; -+ break; -+ case SPEED_1000: -+ val = XPCS_SPEED_1000; -+ break; -+ case SPEED_100: -+ val = XPCS_SPEED_100; -+ break; -+ case SPEED_10: -+ val = XPCS_SPEED_10; -+ break; -+ default: -+ dev_err(qpcs->dev, "Invalid USXGMII speed %d\n", speed); -+ return -EINVAL; -+ } -+ -+ /* Configure XPCS speed */ -+ ret = regmap_update_bits(qpcs->regmap, XPCS_MII_CTRL, -+ XPCS_SPEED_MASK, val | XPCS_DUPLEX_FULL); -+ if (ret) -+ return ret; -+ -+ /* XPCS adapter reset */ -+ return regmap_set_bits(qpcs->regmap, -+ XPCS_DIG_CTRL, XPCS_USXG_ADPT_RESET); -+} -+ - static int ipq_pcs_validate(struct phylink_pcs *pcs, unsigned long *supported, - const struct phylink_link_state *state) - { -@@ -244,6 +400,11 @@ static int ipq_pcs_validate(struct phyli - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: - return 0; -+ case PHY_INTERFACE_MODE_USXGMII: -+ /* USXGMII only supports full duplex mode */ -+ phylink_clear(supported, 100baseT_Half); -+ phylink_clear(supported, 10baseT_Half); -+ return 0; - default: - return -EINVAL; - } -@@ -255,6 +416,7 @@ static unsigned int ipq_pcs_inband_caps( - switch (interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_USXGMII: - return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; - default: - return 0; -@@ -307,6 +469,9 @@ static void ipq_pcs_get_state(struct phy - case PHY_INTERFACE_MODE_QSGMII: - ipq_pcs_get_state_sgmii(qpcs, index, state); - break; -+ case PHY_INTERFACE_MODE_USXGMII: -+ ipq_pcs_get_state_usxgmii(qpcs, state); -+ break; - default: - break; - } -@@ -333,6 +498,8 @@ static int ipq_pcs_config(struct phylink - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: - return ipq_pcs_config_sgmii(qpcs, index, neg_mode, interface); -+ case PHY_INTERFACE_MODE_USXGMII: -+ return ipq_pcs_config_usxgmii(qpcs); - default: - return -EOPNOTSUPP; - }; -@@ -354,6 +521,9 @@ static void ipq_pcs_link_up(struct phyli - ret = ipq_pcs_link_up_config_sgmii(qpcs, index, - neg_mode, speed); - break; -+ case PHY_INTERFACE_MODE_USXGMII: -+ ret = ipq_pcs_link_up_config_usxgmii(qpcs, speed); -+ break; - default: - return; - } diff --git a/target/linux/qualcommbe/patches-6.12/0318-MAINTAINERS-Add-maintainer-for-Qualcomm-IPQ9574-PCS-.patch b/target/linux/qualcommbe/patches-6.12/0318-MAINTAINERS-Add-maintainer-for-Qualcomm-IPQ9574-PCS-.patch deleted file mode 100644 index adaf5575fc..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0318-MAINTAINERS-Add-maintainer-for-Qualcomm-IPQ9574-PCS-.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 34d10a4eb8fea32bb79e3012dc9d8bd2dffb0df3 Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Fri, 7 Feb 2025 23:53:16 +0800 -Subject: [PATCH] MAINTAINERS: Add maintainer for Qualcomm IPQ9574 PCS driver - -Add maintainer for the Ethernet PCS driver supported for Qualcomm -IPQ9574 SoC. - -Signed-off-by: Lei Wei ---- - MAINTAINERS | 9 +++++++++ - 1 file changed, 9 insertions(+) - ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -19129,6 +19129,15 @@ S: Maintained - F: Documentation/devicetree/bindings/regulator/vqmmc-ipq4019-regulator.yaml - F: drivers/regulator/vqmmc-ipq4019-regulator.c - -+QUALCOMM IPQ9574 Ethernet PCS DRIVER -+M: Lei Wei -+L: netdev@vger.kernel.org -+S: Supported -+F: Documentation/devicetree/bindings/net/pcs/qcom,ipq9574-pcs.yaml -+F: drivers/net/pcs/pcs-qcom-ipq9574.c -+F: include/dt-bindings/net/qcom,ipq9574-pcs.h -+F: include/linux/pcs/pcs-qcom-ipq9574.h -+ - QUALCOMM NAND CONTROLLER DRIVER - M: Manivannan Sadhasivam - L: linux-mtd@lists.infradead.org diff --git a/target/linux/qualcommbe/patches-6.12/0322-arm64-dts-qcom-ipq9574-add-PCS-uniphy-nodes.patch b/target/linux/qualcommbe/patches-6.12/0322-arm64-dts-qcom-ipq9574-add-PCS-uniphy-nodes.patch deleted file mode 100644 index 8196ff601c..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0322-arm64-dts-qcom-ipq9574-add-PCS-uniphy-nodes.patch +++ /dev/null @@ -1,139 +0,0 @@ -From d6f184181b076cbb54f152994f5bc73ce524a67e Mon Sep 17 00:00:00 2001 -From: Alexandru Gagniuc -Date: Sun, 11 May 2025 18:21:00 -0500 -Subject: [PATCH] arm64: dts: qcom: ipq9574: add PCS uniphy nodes - -IPQ9574 has three uniphy blocks. IPQ9554 lacks uniphy1. They take -their system and AHB clocks from NSSCC, and also feed NSSCC with -the clocks that are intended for the PHYs. This is not a cirular -dependency. Add nodes for these uniphy blocks, and the clocks they -feed back to the NSSCC node. - -Signed-off-by: Alexandru Gagniuc ---- - arch/arm64/boot/dts/qcom/ipq9574.dtsi | 100 ++++++++++++++++++++++++-- - 1 file changed, 94 insertions(+), 6 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi -@@ -9,6 +9,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -1247,12 +1248,12 @@ - <&cmn_pll NSS_1200MHZ_CLK>, - <&cmn_pll PPE_353MHZ_CLK>, - <&gcc GPLL0_OUT_AUX>, -- <0>, -- <0>, -- <0>, -- <0>, -- <0>, -- <0>, -+ <&pcs0 0>, -+ <&pcs0 1>, -+ <&pcs1 0>, -+ <&pcs1 1>, -+ <&pcs2 0>, -+ <&pcs2 1>, - <&gcc GCC_NSSCC_CLK>; - clock-names = "xo", - "nss_1200", -@@ -1269,6 +1270,93 @@ - #reset-cells = <1>; - #interconnect-cells = <1>; - }; -+ -+ pcs0: ethernet-pcs@7a00000 { -+ compatible = "qcom,ipq9574-pcs"; -+ reg = <0x7a00000 0x10000>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ clocks = <&gcc GCC_UNIPHY0_SYS_CLK>, -+ <&gcc GCC_UNIPHY0_AHB_CLK>; -+ clock-names = "sys", -+ "ahb"; -+ resets = <&gcc GCC_UNIPHY0_XPCS_RESET>; -+ #clock-cells = <1>; -+ -+ pcs0_ch0: pcs-mii@0 { -+ reg = <0>; -+ clocks = <&nsscc NSS_CC_UNIPHY_PORT1_RX_CLK>, -+ <&nsscc NSS_CC_UNIPHY_PORT1_TX_CLK>; -+ clock-names = "rx", -+ "tx"; -+ }; -+ -+ pcs0_ch1: pcs-mii@1 { -+ reg = <1>; -+ clocks = <&nsscc NSS_CC_UNIPHY_PORT2_RX_CLK>, -+ <&nsscc NSS_CC_UNIPHY_PORT2_TX_CLK>; -+ clock-names = "rx", -+ "tx"; -+ }; -+ -+ pcs0_ch2: pcs-mii@2 { -+ reg = <2>; -+ clocks = <&nsscc NSS_CC_UNIPHY_PORT3_RX_CLK>, -+ <&nsscc NSS_CC_UNIPHY_PORT3_TX_CLK>; -+ clock-names = "rx", -+ "tx"; -+ }; -+ -+ pcs0_ch3: pcs-mii@3 { -+ reg = <3>; -+ clocks = <&nsscc NSS_CC_UNIPHY_PORT4_RX_CLK>, -+ <&nsscc NSS_CC_UNIPHY_PORT4_TX_CLK>; -+ clock-names = "rx", -+ "tx"; -+ }; -+ }; -+ -+ pcs1: ethernet-pcs@7a10000 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "qcom,ipq9574-pcs"; -+ reg = <0x7a10000 0x10000>; -+ clocks = <&gcc GCC_UNIPHY1_SYS_CLK>, -+ <&gcc GCC_UNIPHY1_AHB_CLK>; -+ clock-names = "sys", -+ "ahb"; -+ resets = <&gcc GCC_UNIPHY1_XPCS_RESET>; -+ #clock-cells = <1>; -+ -+ pcs1_ch0: pcs-mii@0 { -+ reg = <0>; -+ clocks = <&nsscc NSS_CC_UNIPHY_PORT5_RX_CLK>, -+ <&nsscc NSS_CC_UNIPHY_PORT5_TX_CLK>; -+ clock-names = "rx", -+ "tx"; -+ }; -+ }; -+ -+ pcs2: ethernet-pcs@7a20000 { -+ compatible = "qcom,ipq9574-pcs"; -+ reg = <0x7a20000 0x10000>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ clocks = <&gcc GCC_UNIPHY2_SYS_CLK>, -+ <&gcc GCC_UNIPHY2_AHB_CLK>; -+ clock-names = "sys", -+ "ahb"; -+ resets = <&gcc GCC_UNIPHY2_XPCS_RESET>; -+ #clock-cells = <1>; -+ -+ pcs2_ch0: pcs-mii@0 { -+ reg = <0>; -+ clocks = <&nsscc NSS_CC_UNIPHY_PORT6_RX_CLK>, -+ <&nsscc NSS_CC_UNIPHY_PORT6_TX_CLK>; -+ clock-names = "rx", -+ "tx"; -+ }; -+ }; - }; - - thermal-zones { diff --git a/target/linux/qualcommbe/patches-6.12/0323-dt-bindings-net-Add-PPE-for-Qualcomm-IPQ9574-SoC.patch b/target/linux/qualcommbe/patches-6.12/0323-dt-bindings-net-Add-PPE-for-Qualcomm-IPQ9574-SoC.patch deleted file mode 100644 index 89c09ff9ea..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0323-dt-bindings-net-Add-PPE-for-Qualcomm-IPQ9574-SoC.patch +++ /dev/null @@ -1,432 +0,0 @@ -From 48dc6d2fe28865a5c3d271aeb966b984a8085e7c Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 9 Feb 2025 22:29:35 +0800 -Subject: [PATCH] dt-bindings: net: Add PPE for Qualcomm IPQ9574 SoC - -The PPE (packet process engine) hardware block is available in Qualcomm -IPQ chipsets that support PPE architecture, such as IPQ9574. The PPE in -the IPQ9574 SoC includes six ethernet ports (6 GMAC and 6 XGMAC), which -are used to connect with external PHY devices by PCS. It includes an L2 -switch function for bridging packets among the 6 ethernet ports and the -CPU port. The CPU port enables packet transfer between the ethernet -ports and the ARM cores in the SoC, using the ethernet DMA. - -The PPE also includes packet processing offload capabilities for various -networking functions such as route and bridge flows, VLANs, different -tunnel protocols and VPN. - -Signed-off-by: Luo Jie ---- - .../bindings/net/qcom,ipq9574-ppe.yaml | 406 ++++++++++++++++++ - 1 file changed, 406 insertions(+) - create mode 100644 Documentation/devicetree/bindings/net/qcom,ipq9574-ppe.yaml - ---- /dev/null -+++ b/Documentation/devicetree/bindings/net/qcom,ipq9574-ppe.yaml -@@ -0,0 +1,406 @@ -+# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/net/qcom,ipq9574-ppe.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Qualcomm IPQ packet process engine (PPE) -+ -+maintainers: -+ - Luo Jie -+ - Lei Wei -+ - Suruchi Agarwal -+ - Pavithra R > -+ -+description: -+ The Ethernet functionality in the PPE (Packet Process Engine) is comprised -+ of three components, the switch core, port wrapper and Ethernet DMA. -+ -+ The Switch core in the IPQ9574 PPE has maximum of 6 front panel ports and -+ two FIFO interfaces. One of the two FIFO interfaces is used for Ethernet -+ port to host CPU communication using Ethernet DMA. The other is used -+ communicating to the EIP engine which is used for IPsec offload. On the -+ IPQ9574, the PPE includes 6 GMAC/XGMACs that can be connected with external -+ Ethernet PHY. Switch core also includes BM (Buffer Management), QM (Queue -+ Management) and SCH (Scheduler) modules for supporting the packet processing. -+ -+ The port wrapper provides connections from the 6 GMAC/XGMACS to UNIPHY (PCS) -+ supporting various modes such as SGMII/QSGMII/PSGMII/USXGMII/10G-BASER. There -+ are 3 UNIPHY (PCS) instances supported on the IPQ9574. -+ -+ Ethernet DMA is used to transmit and receive packets between the six Ethernet -+ ports and ARM host CPU. -+ -+ The follow diagram shows the PPE hardware block along with its connectivity -+ to the external hardware blocks such clock hardware blocks (CMNPLL, GCC, -+ NSS clock controller) and ethernet PCS/PHY blocks. For depicting the PHY -+ connectivity, one 4x1 Gbps PHY (QCA8075) and two 10 GBps PHYs are used as an -+ example. -+ - | -+ +---------+ -+ | 48 MHZ | -+ +----+----+ -+ |(clock) -+ v -+ +----+----+ -+ +------| CMN PLL | -+ | +----+----+ -+ | |(clock) -+ | v -+ | +----+----+ +----+----+ (clock) +----+----+ -+ | +---| NSSCC | | GCC |--------->| MDIO | -+ | | +----+----+ +----+----+ +----+----+ -+ | | |(clock & reset) |(clock) -+ | | v v -+ | | +-----------------------------+----------+----------+---------+ -+ | | | +-----+ |EDMA FIFO | | EIP FIFO| -+ | | | | SCH | +----------+ +---------+ -+ | | | +-----+ | | | -+ | | | +------+ +------+ +-------------------+ | -+ | | | | BM | | QM | IPQ9574-PPE | L2/L3 Process | | -+ | | | +------+ +------+ +-------------------+ | -+ | | | | | -+ | | | +-------+ +-------+ +-------+ +-------+ +-------+ +-------+ | -+ | | | | MAC0 | | MAC1 | | MAC2 | | MAC3 | | XGMAC4| |XGMAC5 | | -+ | | | +---+---+ +---+---+ +---+---+ +---+---+ +---+---+ +---+---+ | -+ | | | | | | | | | | -+ | | +-----+---------+---------+---------+---------+---------+-----+ -+ | | | | | | | | -+ | | +---+---------+---------+---------+---+ +---+---+ +---+---+ -+ +--+---->| PCS0 | | PCS1 | | PCS2 | -+ |(clock) +---+---------+---------+---------+---+ +---+---+ +---+---+ -+ | | | | | | | -+ | +---+---------+---------+---------+---+ +---+---+ +---+---+ -+ +------->| QCA8075 PHY | | PHY4 | | PHY5 | -+ (clock) +-------------------------------------+ +-------+ +-------+ -+ -+properties: -+ compatible: -+ enum: -+ - qcom,ipq9574-ppe -+ -+ reg: -+ maxItems: 1 -+ -+ clocks: -+ items: -+ - description: PPE core clock from NSS clock controller -+ - description: PPE APB (Advanced Peripheral Bus) clock from NSS clock controller -+ - description: PPE ingress process engine clock from NSS clock controller -+ - description: PPE BM, QM and scheduler clock from NSS clock controller -+ -+ clock-names: -+ items: -+ - const: ppe -+ - const: apb -+ - const: ipe -+ - const: btq -+ -+ resets: -+ maxItems: 1 -+ description: PPE reset, which is necessary before configuring PPE hardware -+ -+ interconnects: -+ items: -+ - description: Clock path leading to PPE switch core function -+ - description: Clock path leading to PPE register access -+ - description: Clock path leading to QoS generation -+ - description: Clock path leading to timeout reference -+ - description: Clock path leading to NSS NOC from memory NOC -+ - description: Clock path leading to memory NOC from NSS NOC -+ - description: Clock path leading to enhanced memory NOC from NSS NOC -+ -+ interconnect-names: -+ items: -+ - const: ppe -+ - const: ppe_cfg -+ - const: qos_gen -+ - const: timeout_ref -+ - const: nssnoc_memnoc -+ - const: memnoc_nssnoc -+ - const: memnoc_nssnoc_1 -+ -+ ethernet-dma: -+ type: object -+ additionalProperties: false -+ description: -+ EDMA (Ethernet DMA) is used to transmit packets between PPE and ARM -+ host CPU. There are 32 TX descriptor rings, 32 TX completion rings, -+ 24 RX descriptor rings and 8 RX fill rings supported. -+ -+ properties: -+ clocks: -+ items: -+ - description: EDMA system clock from NSS Clock Controller -+ - description: EDMA APB (Advanced Peripheral Bus) clock from -+ NSS Clock Controller -+ -+ clock-names: -+ items: -+ - const: sys -+ - const: apb -+ -+ resets: -+ maxItems: 1 -+ description: EDMA reset from NSS clock controller -+ -+ interrupts: -+ minItems: 29 -+ maxItems: 57 -+ -+ interrupt-names: -+ minItems: 29 -+ maxItems: 57 -+ items: -+ pattern: '^(txcmpl_([0-9]|[1-2][0-9]|3[0-1])|rxdesc_([0-9]|1[0-9]|2[0-3])|misc)$' -+ description: -+ Interrupts "txcmpl_[0-31]" are the Ethernet DMA Tx completion ring interrupts. -+ Interrupts "rxdesc_[0-23]" are the Ethernet DMA Rx Descriptor ring interrupts. -+ Interrupt "misc" is the Ethernet DMA miscellaneous error interrupt. -+ -+ required: -+ - clocks -+ - clock-names -+ - resets -+ - interrupts -+ - interrupt-names -+ -+required: -+ - compatible -+ - reg -+ - clocks -+ - clock-names -+ - resets -+ - interconnects -+ - interconnect-names -+ - ethernet-dma -+ -+allOf: -+ - $ref: ethernet-switch.yaml -+ -+unevaluatedProperties: false -+ -+examples: -+ - | -+ #include -+ #include -+ #include -+ -+ ethernet-switch@3a000000 { -+ compatible = "qcom,ipq9574-ppe"; -+ reg = <0x3a000000 0xbef800>; -+ clocks = <&nsscc 80>, -+ <&nsscc 79>, -+ <&nsscc 81>, -+ <&nsscc 78>; -+ clock-names = "ppe", -+ "apb", -+ "ipe", -+ "btq"; -+ resets = <&nsscc 108>; -+ interconnects = <&nsscc MASTER_NSSNOC_PPE &nsscc SLAVE_NSSNOC_PPE>, -+ <&nsscc MASTER_NSSNOC_PPE_CFG &nsscc SLAVE_NSSNOC_PPE_CFG>, -+ <&gcc MASTER_NSSNOC_QOSGEN_REF &gcc SLAVE_NSSNOC_QOSGEN_REF>, -+ <&gcc MASTER_NSSNOC_TIMEOUT_REF &gcc SLAVE_NSSNOC_TIMEOUT_REF>, -+ <&gcc MASTER_MEM_NOC_NSSNOC &gcc SLAVE_MEM_NOC_NSSNOC>, -+ <&gcc MASTER_NSSNOC_MEMNOC &gcc SLAVE_NSSNOC_MEMNOC>, -+ <&gcc MASTER_NSSNOC_MEM_NOC_1 &gcc SLAVE_NSSNOC_MEM_NOC_1>; -+ interconnect-names = "ppe", -+ "ppe_cfg", -+ "qos_gen", -+ "timeout_ref", -+ "nssnoc_memnoc", -+ "memnoc_nssnoc", -+ "memnoc_nssnoc_1"; -+ -+ ethernet-dma { -+ clocks = <&nsscc 77>, -+ <&nsscc 76>; -+ clock-names = "sys", -+ "apb"; -+ resets = <&nsscc 0>; -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ ; -+ interrupt-names = "txcmpl_8", -+ "txcmpl_9", -+ "txcmpl_10", -+ "txcmpl_11", -+ "txcmpl_12", -+ "txcmpl_13", -+ "txcmpl_14", -+ "txcmpl_15", -+ "txcmpl_16", -+ "txcmpl_17", -+ "txcmpl_18", -+ "txcmpl_19", -+ "txcmpl_20", -+ "txcmpl_21", -+ "txcmpl_22", -+ "txcmpl_23", -+ "txcmpl_24", -+ "txcmpl_25", -+ "txcmpl_26", -+ "txcmpl_27", -+ "txcmpl_28", -+ "txcmpl_29", -+ "txcmpl_30", -+ "txcmpl_31", -+ "rxdesc_20", -+ "rxdesc_21", -+ "rxdesc_22", -+ "rxdesc_23", -+ "misc"; -+ }; -+ -+ ethernet-ports { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ port@1 { -+ reg = <1>; -+ phy-mode = "qsgmii"; -+ managed = "in-band-status"; -+ phy-handle = <&phy0>; -+ pcs-handle = <&pcs0_mii0>; -+ clocks = <&nsscc 33>, -+ <&nsscc 34>, -+ <&nsscc 37>; -+ clock-names = "mac", -+ "rx", -+ "tx"; -+ resets = <&nsscc 29>, -+ <&nsscc 96>, -+ <&nsscc 97>; -+ reset-names = "mac", -+ "rx", -+ "tx"; -+ }; -+ -+ port@2 { -+ reg = <2>; -+ phy-mode = "qsgmii"; -+ managed = "in-band-status"; -+ phy-handle = <&phy1>; -+ pcs-handle = <&pcs0_mii1>; -+ clocks = <&nsscc 40>, -+ <&nsscc 41>, -+ <&nsscc 44>; -+ clock-names = "mac", -+ "rx", -+ "tx"; -+ resets = <&nsscc 30>, -+ <&nsscc 98>, -+ <&nsscc 99>; -+ reset-names = "mac", -+ "rx", -+ "tx"; -+ }; -+ -+ port@3 { -+ reg = <3>; -+ phy-mode = "qsgmii"; -+ managed = "in-band-status"; -+ phy-handle = <&phy2>; -+ pcs-handle = <&pcs0_mii2>; -+ clocks = <&nsscc 47>, -+ <&nsscc 48>, -+ <&nsscc 51>; -+ clock-names = "mac", -+ "rx", -+ "tx"; -+ resets = <&nsscc 31>, -+ <&nsscc 100>, -+ <&nsscc 101>; -+ reset-names = "mac", -+ "rx", -+ "tx"; -+ }; -+ -+ port@4 { -+ reg = <4>; -+ phy-mode = "qsgmii"; -+ managed = "in-band-status"; -+ phy-handle = <&phy3>; -+ pcs-handle = <&pcs0_mii3>; -+ clocks = <&nsscc 54>, -+ <&nsscc 55>, -+ <&nsscc 58>; -+ clock-names = "mac", -+ "rx", -+ "tx"; -+ resets = <&nsscc 32>, -+ <&nsscc 102>, -+ <&nsscc 103>; -+ reset-names = "mac", -+ "rx", -+ "tx"; -+ }; -+ -+ port@5 { -+ reg = <5>; -+ phy-mode = "usxgmii"; -+ managed = "in-band-status"; -+ phy-handle = <&phy4>; -+ pcs-handle = <&pcs1_mii0>; -+ clocks = <&nsscc 61>, -+ <&nsscc 62>, -+ <&nsscc 65>; -+ clock-names = "mac", -+ "rx", -+ "tx"; -+ resets = <&nsscc 33>, -+ <&nsscc 104>, -+ <&nsscc 105>; -+ reset-names = "mac", -+ "rx", -+ "tx"; -+ }; -+ -+ port@6 { -+ reg = <6>; -+ phy-mode = "usxgmii"; -+ managed = "in-band-status"; -+ phy-handle = <&phy5>; -+ pcs-handle = <&pcs2_mii0>; -+ clocks = <&nsscc 68>, -+ <&nsscc 69>, -+ <&nsscc 72>; -+ clock-names = "mac", -+ "rx", -+ "tx"; -+ resets = <&nsscc 34>, -+ <&nsscc 106>, -+ <&nsscc 107>; -+ reset-names = "mac", -+ "rx", -+ "tx"; -+ }; -+ }; -+ }; diff --git a/target/linux/qualcommbe/patches-6.12/0324-docs-networking-Add-PPE-driver-documentation-for-Qua.patch b/target/linux/qualcommbe/patches-6.12/0324-docs-networking-Add-PPE-driver-documentation-for-Qua.patch deleted file mode 100644 index 429006c7bc..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0324-docs-networking-Add-PPE-driver-documentation-for-Qua.patch +++ /dev/null @@ -1,227 +0,0 @@ -From 9973b6610830146af1a12fe02d2d6440eb80b0f9 Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Sun, 9 Feb 2025 22:29:36 +0800 -Subject: [PATCH] docs: networking: Add PPE driver documentation for Qualcomm - IPQ9574 SoC - -Add description and high-level diagram for PPE, driver overview and -module enable/debug information. - -Signed-off-by: Lei Wei -Signed-off-by: Luo Jie ---- - .../device_drivers/ethernet/index.rst | 1 + - .../ethernet/qualcomm/ppe/ppe.rst | 197 ++++++++++++++++++ - 2 files changed, 198 insertions(+) - create mode 100644 Documentation/networking/device_drivers/ethernet/qualcomm/ppe/ppe.rst - ---- a/Documentation/networking/device_drivers/ethernet/index.rst -+++ b/Documentation/networking/device_drivers/ethernet/index.rst -@@ -49,6 +49,7 @@ Contents: - neterion/s2io - netronome/nfp - pensando/ionic -+ qualcomm/ppe/ppe - smsc/smc9 - stmicro/stmmac - ti/cpsw ---- /dev/null -+++ b/Documentation/networking/device_drivers/ethernet/qualcomm/ppe/ppe.rst -@@ -0,0 +1,197 @@ -+.. SPDX-License-Identifier: GPL-2.0 -+ -+=============================================== -+PPE Ethernet Driver for Qualcomm IPQ SoC Family -+=============================================== -+ -+Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. -+ -+Author: Lei Wei -+ -+ -+Contents -+======== -+ -+- `PPE Overview`_ -+- `PPE Driver Overview`_ -+- `PPE Driver Supported SoCs`_ -+- `Enabling the Driver`_ -+- `Debugging`_ -+ -+ -+PPE Overview -+============ -+ -+IPQ (Qualcomm Internet Processor) SoC (System-on-Chip) series is Qualcomm's series of -+networking SoC for Wi-Fi access points. The PPE (Packet Process Engine) is the Ethernet -+packet process engine in the IPQ SoC. -+ -+Below is a simplified hardware diagram of IPQ9574 SoC which includes the PPE engine and -+other blocks which are in the SoC but outside the PPE engine. These blocks work together -+to enable the Ethernet for the IPQ SoC:: -+ -+ +------+ +------+ +------+ +------+ +------+ +------+ start +-------+ -+ |netdev| |netdev| |netdev| |netdev| |netdev| |netdev|<------|PHYLINK| -+ +------+ +------+ +------+ +------+ +------+ +------+ stop +-+-+-+-+ -+ | | | ^ -+ +-------+ +-------------------------+--------+----------------------+ | | | -+ | GCC | | | EDMA | | | | | -+ +---+---+ | PPE +---+----+ | | | | -+ | clk | | | | | | -+ +------>| +-----------------------+------+-----+---------------+ | | | | -+ | | Switch Core |Port0 | |Port7(EIP FIFO)| | | | | -+ | | +---+--+ +------+--------+ | | | | -+ | | | | | | | | | -+ +-------+ | | +------+---------------+----+ | | | | | -+ |CMN PLL| | | +---+ +---+ +----+ | +--------+ | | | | | | -+ +---+---+ | | |BM | |QM | |SCH | | | L2/L3 | ....... | | | | | | -+ | | | | +---+ +---+ +----+ | +--------+ | | | | | | -+ | | | | +------+--------------------+ | | | | | -+ | | | | | | | | | | -+ | v | | +-----+-+-----+-+-----+-+-+---+--+-----+-+-----+ | | | | | -+ | +------+ | | |Port1| |Port2| |Port3| |Port4| |Port5| |Port6| | | | | | -+ | |NSSCC | | | +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ | | mac| | | -+ | +-+-+--+ | | |MAC0 | |MAC1 | |MAC2 | |MAC3 | |MAC4 | |MAC5 | | |<---+ | | -+ | ^ | |clk | | +-----+-+-----+-+-----+-+-----+--+-----+-+-----+ | | ops | | -+ | | | +---->| +----|------|-------|-------|---------|--------|-----+ | | | -+ | | | +---------------------------------------------------------+ | | -+ | | | | | | | | | | | -+ | | | MII clk | QSGMII USXGMII USXGMII | | -+ | | +------------->| | | | | | | | -+ | | +-------------------------+ +---------+ +---------+ | | -+ | |125/312.5M clk| (PCS0) | | (PCS1) | | (PCS2) | pcs ops | | -+ | +--------------+ UNIPHY0 | | UNIPHY1 | | UNIPHY2 |<--------+ | -+ +--------------->| | | | | | | -+ | 31.25M ref clk +-------------------------+ +---------+ +---------+ | -+ | | | | | | | | -+ | +-----------------------------------------------------+ | -+ |25/50M ref clk| +-------------------------+ +------+ +------+ | link | -+ +------------->| | QUAD PHY | | PHY4 | | PHY5 | |---------+ -+ | +-------------------------+ +------+ +------+ | change -+ | | -+ | MDIO bus | -+ +-----------------------------------------------------+ -+ -+The CMN (Common) PLL, NSSCC (Networking Sub System Clock Controller) and GCC (Global -+Clock Controller) blocks are in the SoC and act as clock providers. -+ -+The UNIPHY block is in the SoC and provides the PCS (Physical Coding Sublayer) and -+XPCS (10-Gigabit Physical Coding Sublayer) functions to support different interface -+modes between the PPE MAC and the external PHY. -+ -+This documentation focuses on the descriptions of PPE engine and the PPE driver. -+ -+The Ethernet functionality in the PPE (Packet Process Engine) is comprised of three -+components: the switch core, port wrapper and Ethernet DMA. -+ -+The Switch core in the IPQ9574 PPE has maximum of 6 front panel ports and two FIFO -+interfaces. One of the two FIFO interfaces is used for Ethernet port to host CPU -+communication using Ethernet DMA. The other is used communicating to the EIP engine -+which is used for IPsec offload. On the IPQ9574, the PPE includes 6 GMAC/XGMACs that -+can be connected with external Ethernet PHY. Switch core also includes BM (Buffer -+Management), QM (Queue Management) and SCH (Scheduler) modules for supporting the -+packet processing. -+ -+The port wrapper provides connections from the 6 GMAC/XGMACS to UNIPHY (PCS) supporting -+various modes such as SGMII/QSGMII/PSGMII/USXGMII/10G-BASER. There are 3 UNIPHY (PCS) -+instances supported on the IPQ9574. -+ -+Ethernet DMA is used to transmit and receive packets between the Ethernet subsystem -+and ARM host CPU. -+ -+The following lists the main blocks in the PPE engine which will be driven by this -+PPE driver: -+ -+- BM -+ BM is the hardware buffer manager for the PPE switch ports. -+- QM -+ Queue Manager for managing the egress hardware queues of the PPE switch ports. -+- SCH -+ The scheduler which manages the hardware traffic scheduling for the PPE switch ports. -+- L2 -+ The L2 block performs the packet bridging in the switch core. The bridge domain is -+ represented by the VSI (Virtual Switch Instance) domain in PPE. FDB learning can be -+ enabled based on the VSI domain and bridge forwarding occurs within the VSI domain. -+- MAC -+ The PPE in the IPQ9574 supports up to six MACs (MAC0 to MAC5) which are corresponding -+ to six switch ports (port1 to port6). The MAC block is connected with external PHY -+ through the UNIPHY PCS block. Each MAC block includes the GMAC and XGMAC blocks and -+ the switch port can select to use GMAC or XMAC through a MUX selection according to -+ the external PHY's capability. -+- EDMA (Ethernet DMA) -+ The Ethernet DMA is used to transmit and receive Ethernet packets between the PPE -+ ports and the ARM cores. -+ -+The received packet on a PPE MAC port can be forwarded to another PPE MAC port. It can -+be also forwarded to internal switch port0 so that the packet can be delivered to the -+ARM cores using the Ethernet DMA (EDMA) engine. The Ethernet DMA driver will deliver the -+packet to the corresponding 'netdevice' interface. -+ -+The software instantiations of the PPE MAC (netdevice), PCS and external PHYs interact -+with the Linux PHYLINK framework to manage the connectivity between the PPE ports and -+the connected PHYs, and the port link states. This is also illustrated in above diagram. -+ -+ -+PPE Driver Overview -+=================== -+PPE driver is Ethernet driver for the Qualcomm IPQ SoC. It is a single platform driver -+which includes the PPE part and Ethernet DMA part. The PPE part initializes and drives the -+various blocks in PPE switch core such as BM/QM/L2 blocks and the PPE MACs. The EDMA part -+drives the Ethernet DMA for packet transfer between PPE ports and ARM cores, and enables -+the netdevice driver for the PPE ports. -+ -+The PPE driver files in drivers/net/ethernet/qualcomm/ppe/ are listed as below: -+ -+- Makefile -+- ppe.c -+- ppe.h -+- ppe_config.c -+- ppe_config.h -+- ppe_debugfs.c -+- ppe_debugfs.h -+- ppe_regs.h -+ -+The ppe.c file contains the main PPE platform driver and undertakes the initialization of -+PPE switch core blocks such as QM, BM and L2. The configuration APIs for these hardware -+blocks are provided in the ppe_config.c file. -+ -+The ppe.h defines the PPE device data structure which will be used by PPE driver functions. -+ -+The ppe_debugfs.c enables the PPE statistics counters such as PPE port Rx and Tx counters, -+CPU code counters and queue counters. -+ -+ -+PPE Driver Supported SoCs -+========================= -+ -+The PPE driver supports the following IPQ SoC: -+ -+- IPQ9574 -+ -+ -+Enabling the Driver -+=================== -+ -+The driver is located in the menu structure at: -+ -+ -> Device Drivers -+ -> Network device support (NETDEVICES [=y]) -+ -> Ethernet driver support -+ -> Qualcomm devices -+ -> Qualcomm Technologies, Inc. PPE Ethernet support -+ -+If this driver is built as a module, we can use below commands to install and remove it: -+ -+- insmod qcom-ppe.ko -+- rmmod qcom-ppe.ko -+ -+The PPE driver functionally depends on the CMN PLL and NSSCC clock controller drivers. -+Please make sure the dependent modules are installed before installing the PPE driver -+module. -+ -+ -+Debugging -+========= -+ -+The PPE hardware counters are available in the debugfs and can be checked by the command -+``cat /sys/kernel/debug/ppe/packet_counters``. diff --git a/target/linux/qualcommbe/patches-6.12/0325-net-ethernet-qualcomm-Add-PPE-driver-for-IPQ9574-SoC.patch b/target/linux/qualcommbe/patches-6.12/0325-net-ethernet-qualcomm-Add-PPE-driver-for-IPQ9574-SoC.patch deleted file mode 100644 index f55879ae48..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0325-net-ethernet-qualcomm-Add-PPE-driver-for-IPQ9574-SoC.patch +++ /dev/null @@ -1,339 +0,0 @@ -From d1158f0282304c89217894aa346fc45364b95542 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 9 Feb 2025 22:29:37 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Add PPE driver for IPQ9574 SoC - -The PPE (Packet Process Engine) hardware block is available -on Qualcomm IPQ SoC that support PPE architecture, such as -IPQ9574. - -The PPE in IPQ9574 includes six integrated ethernet MAC -(for 6 PPE ports), buffer management, queue management and -scheduler functions. The MACs can connect with the external -PHY or switch devices using the UNIPHY PCS block available -in the SoC. - -The PPE also includes various packet processing offload -capabilities such as L3 routing and L2 bridging, VLAN and -tunnel processing offload. It also includes Ethernet DMA -function for transferring packets between ARM cores and -PPE ethernet ports. - -This patch adds the base source files and Makefiles for -the PPE driver such as platform driver registration, -clock initialization, and PPE reset routines. - -Signed-off-by: Luo Jie ---- - drivers/net/ethernet/qualcomm/Kconfig | 15 ++ - drivers/net/ethernet/qualcomm/Makefile | 1 + - drivers/net/ethernet/qualcomm/ppe/Makefile | 7 + - drivers/net/ethernet/qualcomm/ppe/ppe.c | 218 +++++++++++++++++++++ - drivers/net/ethernet/qualcomm/ppe/ppe.h | 36 ++++ - 5 files changed, 277 insertions(+) - create mode 100644 drivers/net/ethernet/qualcomm/ppe/Makefile - create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe.c - create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe.h - ---- a/drivers/net/ethernet/qualcomm/Kconfig -+++ b/drivers/net/ethernet/qualcomm/Kconfig -@@ -61,6 +61,21 @@ config QCOM_EMAC - low power, Receive-Side Scaling (RSS), and IEEE 1588-2008 - Precision Clock Synchronization Protocol. - -+config QCOM_PPE -+ tristate "Qualcomm Technologies, Inc. PPE Ethernet support" -+ depends on HAS_IOMEM && OF -+ depends on COMMON_CLK -+ select REGMAP_MMIO -+ help -+ This driver supports the Qualcomm Technologies, Inc. packet -+ process engine (PPE) available with IPQ SoC. The PPE includes -+ the ethernet MACs, Ethernet DMA (EDMA) and switch core that -+ supports L3 flow offload, L2 switch function, RSS and tunnel -+ offload. -+ -+ To compile this driver as a module, choose M here. The module -+ will be called qcom-ppe. -+ - source "drivers/net/ethernet/qualcomm/rmnet/Kconfig" - - endif # NET_VENDOR_QUALCOMM ---- a/drivers/net/ethernet/qualcomm/Makefile -+++ b/drivers/net/ethernet/qualcomm/Makefile -@@ -11,4 +11,5 @@ qcauart-objs := qca_uart.o - - obj-y += emac/ - -+obj-$(CONFIG_QCOM_PPE) += ppe/ - obj-$(CONFIG_RMNET) += rmnet/ ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/Makefile -@@ -0,0 +1,7 @@ -+# SPDX-License-Identifier: GPL-2.0-only -+# -+# Makefile for the device driver of PPE (Packet Process Engine) in IPQ SoC -+# -+ -+obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o -+qcom-ppe-objs := ppe.o ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.c -@@ -0,0 +1,218 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+/* PPE platform device probe, DTSI parser and PPE clock initializations. */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "ppe.h" -+ -+#define PPE_PORT_MAX 8 -+#define PPE_CLK_RATE 353000000 -+ -+/* ICC clocks for enabling PPE device. The avg_bw and peak_bw with value 0 -+ * will be updated by the clock rate of PPE. -+ */ -+static const struct icc_bulk_data ppe_icc_data[] = { -+ { -+ .name = "ppe", -+ .avg_bw = 0, -+ .peak_bw = 0, -+ }, -+ { -+ .name = "ppe_cfg", -+ .avg_bw = 0, -+ .peak_bw = 0, -+ }, -+ { -+ .name = "qos_gen", -+ .avg_bw = 6000, -+ .peak_bw = 6000, -+ }, -+ { -+ .name = "timeout_ref", -+ .avg_bw = 6000, -+ .peak_bw = 6000, -+ }, -+ { -+ .name = "nssnoc_memnoc", -+ .avg_bw = 533333, -+ .peak_bw = 533333, -+ }, -+ { -+ .name = "memnoc_nssnoc", -+ .avg_bw = 533333, -+ .peak_bw = 533333, -+ }, -+ { -+ .name = "memnoc_nssnoc_1", -+ .avg_bw = 533333, -+ .peak_bw = 533333, -+ }, -+}; -+ -+static const struct regmap_range ppe_readable_ranges[] = { -+ regmap_reg_range(0x0, 0x1ff), /* Global */ -+ regmap_reg_range(0x400, 0x5ff), /* LPI CSR */ -+ regmap_reg_range(0x1000, 0x11ff), /* GMAC0 */ -+ regmap_reg_range(0x1200, 0x13ff), /* GMAC1 */ -+ regmap_reg_range(0x1400, 0x15ff), /* GMAC2 */ -+ regmap_reg_range(0x1600, 0x17ff), /* GMAC3 */ -+ regmap_reg_range(0x1800, 0x19ff), /* GMAC4 */ -+ regmap_reg_range(0x1a00, 0x1bff), /* GMAC5 */ -+ regmap_reg_range(0xb000, 0xefff), /* PRX CSR */ -+ regmap_reg_range(0xf000, 0x1efff), /* IPE */ -+ regmap_reg_range(0x20000, 0x5ffff), /* PTX CSR */ -+ regmap_reg_range(0x60000, 0x9ffff), /* IPE L2 CSR */ -+ regmap_reg_range(0xb0000, 0xeffff), /* IPO CSR */ -+ regmap_reg_range(0x100000, 0x17ffff), /* IPE PC */ -+ regmap_reg_range(0x180000, 0x1bffff), /* PRE IPO CSR */ -+ regmap_reg_range(0x1d0000, 0x1dffff), /* Tunnel parser */ -+ regmap_reg_range(0x1e0000, 0x1effff), /* Ingress parse */ -+ regmap_reg_range(0x200000, 0x2fffff), /* IPE L3 */ -+ regmap_reg_range(0x300000, 0x3fffff), /* IPE tunnel */ -+ regmap_reg_range(0x400000, 0x4fffff), /* Scheduler */ -+ regmap_reg_range(0x500000, 0x503fff), /* XGMAC0 */ -+ regmap_reg_range(0x504000, 0x507fff), /* XGMAC1 */ -+ regmap_reg_range(0x508000, 0x50bfff), /* XGMAC2 */ -+ regmap_reg_range(0x50c000, 0x50ffff), /* XGMAC3 */ -+ regmap_reg_range(0x510000, 0x513fff), /* XGMAC4 */ -+ regmap_reg_range(0x514000, 0x517fff), /* XGMAC5 */ -+ regmap_reg_range(0x600000, 0x6fffff), /* BM */ -+ regmap_reg_range(0x800000, 0x9fffff), /* QM */ -+ regmap_reg_range(0xb00000, 0xbef800), /* EDMA */ -+}; -+ -+static const struct regmap_access_table ppe_reg_table = { -+ .yes_ranges = ppe_readable_ranges, -+ .n_yes_ranges = ARRAY_SIZE(ppe_readable_ranges), -+}; -+ -+static const struct regmap_config regmap_config_ipq9574 = { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .rd_table = &ppe_reg_table, -+ .wr_table = &ppe_reg_table, -+ .max_register = 0xbef800, -+ .fast_io = true, -+}; -+ -+static int ppe_clock_init_and_reset(struct ppe_device *ppe_dev) -+{ -+ unsigned long ppe_rate = ppe_dev->clk_rate; -+ struct device *dev = ppe_dev->dev; -+ struct reset_control *rstc; -+ struct clk_bulk_data *clks; -+ struct clk *clk; -+ int ret, i; -+ -+ for (i = 0; i < ppe_dev->num_icc_paths; i++) { -+ ppe_dev->icc_paths[i].name = ppe_icc_data[i].name; -+ ppe_dev->icc_paths[i].avg_bw = ppe_icc_data[i].avg_bw ? : -+ Bps_to_icc(ppe_rate); -+ ppe_dev->icc_paths[i].peak_bw = ppe_icc_data[i].peak_bw ? : -+ Bps_to_icc(ppe_rate); -+ } -+ -+ ret = devm_of_icc_bulk_get(dev, ppe_dev->num_icc_paths, -+ ppe_dev->icc_paths); -+ if (ret) -+ return ret; -+ -+ ret = icc_bulk_set_bw(ppe_dev->num_icc_paths, ppe_dev->icc_paths); -+ if (ret) -+ return ret; -+ -+ /* The PPE clocks have a common parent clock. Setting the clock -+ * rate of "ppe" ensures the clock rate of all PPE clocks is -+ * configured to the same rate. -+ */ -+ clk = devm_clk_get(dev, "ppe"); -+ if (IS_ERR(clk)) -+ return PTR_ERR(clk); -+ -+ ret = clk_set_rate(clk, ppe_rate); -+ if (ret) -+ return ret; -+ -+ ret = devm_clk_bulk_get_all_enable(dev, &clks); -+ if (ret < 0) -+ return ret; -+ -+ /* Reset the PPE. */ -+ rstc = devm_reset_control_get_exclusive(dev, NULL); -+ if (IS_ERR(rstc)) -+ return PTR_ERR(rstc); -+ -+ ret = reset_control_assert(rstc); -+ if (ret) -+ return ret; -+ -+ /* The delay 10 ms of assert is necessary for resetting PPE. */ -+ usleep_range(10000, 11000); -+ -+ return reset_control_deassert(rstc); -+} -+ -+static int qcom_ppe_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct ppe_device *ppe_dev; -+ void __iomem *base; -+ int ret, num_icc; -+ -+ num_icc = ARRAY_SIZE(ppe_icc_data); -+ ppe_dev = devm_kzalloc(dev, struct_size(ppe_dev, icc_paths, num_icc), -+ GFP_KERNEL); -+ if (!ppe_dev) -+ return -ENOMEM; -+ -+ base = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(base)) -+ return dev_err_probe(dev, PTR_ERR(base), "PPE ioremap failed\n"); -+ -+ ppe_dev->regmap = devm_regmap_init_mmio(dev, base, ®map_config_ipq9574); -+ if (IS_ERR(ppe_dev->regmap)) -+ return dev_err_probe(dev, PTR_ERR(ppe_dev->regmap), -+ "PPE initialize regmap failed\n"); -+ ppe_dev->dev = dev; -+ ppe_dev->clk_rate = PPE_CLK_RATE; -+ ppe_dev->num_ports = PPE_PORT_MAX; -+ ppe_dev->num_icc_paths = num_icc; -+ -+ ret = ppe_clock_init_and_reset(ppe_dev); -+ if (ret) -+ return dev_err_probe(dev, ret, "PPE clock config failed\n"); -+ -+ platform_set_drvdata(pdev, ppe_dev); -+ -+ return 0; -+} -+ -+static const struct of_device_id qcom_ppe_of_match[] = { -+ { .compatible = "qcom,ipq9574-ppe" }, -+ {} -+}; -+MODULE_DEVICE_TABLE(of, qcom_ppe_of_match); -+ -+static struct platform_driver qcom_ppe_driver = { -+ .driver = { -+ .name = "qcom_ppe", -+ .of_match_table = qcom_ppe_of_match, -+ }, -+ .probe = qcom_ppe_probe, -+}; -+module_platform_driver(qcom_ppe_driver); -+ -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("Qualcomm Technologies, Inc. IPQ PPE driver"); ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.h -@@ -0,0 +1,36 @@ -+/* SPDX-License-Identifier: GPL-2.0-only -+ * -+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#ifndef __PPE_H__ -+#define __PPE_H__ -+ -+#include -+#include -+ -+struct device; -+struct regmap; -+ -+/** -+ * struct ppe_device - PPE device private data. -+ * @dev: PPE device structure. -+ * @regmap: PPE register map. -+ * @clk_rate: PPE clock rate. -+ * @num_ports: Number of PPE ports. -+ * @num_icc_paths: Number of interconnect paths. -+ * @icc_paths: Interconnect path array. -+ * -+ * PPE device is the instance of PPE hardware, which is used to -+ * configure PPE packet process modules such as BM (buffer management), -+ * QM (queue management), and scheduler. -+ */ -+struct ppe_device { -+ struct device *dev; -+ struct regmap *regmap; -+ unsigned long clk_rate; -+ unsigned int num_ports; -+ unsigned int num_icc_paths; -+ struct icc_bulk_data icc_paths[] __counted_by(num_icc_paths); -+}; -+#endif diff --git a/target/linux/qualcommbe/patches-6.12/0326-net-ethernet-qualcomm-Initialize-PPE-buffer-manageme.patch b/target/linux/qualcommbe/patches-6.12/0326-net-ethernet-qualcomm-Initialize-PPE-buffer-manageme.patch deleted file mode 100644 index 5f38e25b37..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0326-net-ethernet-qualcomm-Initialize-PPE-buffer-manageme.patch +++ /dev/null @@ -1,328 +0,0 @@ -From 6e639ab45348ee7a697db8b481fa6f8555280f58 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 9 Feb 2025 22:29:38 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Initialize PPE buffer management for - IPQ9574 - -The BM (Buffer Management) config controls the pause frame generated -on the PPE port. There are maximum 15 BM ports and 4 groups supported, -all BM ports are assigned to group 0 by default. The number of hardware -buffers configured for the port influence the threshold of the flow -control for that port. - -Signed-off-by: Luo Jie ---- - drivers/net/ethernet/qualcomm/ppe/Makefile | 2 +- - drivers/net/ethernet/qualcomm/ppe/ppe.c | 5 + - .../net/ethernet/qualcomm/ppe/ppe_config.c | 195 ++++++++++++++++++ - .../net/ethernet/qualcomm/ppe/ppe_config.h | 12 ++ - drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 59 ++++++ - 5 files changed, 272 insertions(+), 1 deletion(-) - create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe_config.c - create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe_config.h - create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe_regs.h - ---- a/drivers/net/ethernet/qualcomm/ppe/Makefile -+++ b/drivers/net/ethernet/qualcomm/ppe/Makefile -@@ -4,4 +4,4 @@ - # - - obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o --qcom-ppe-objs := ppe.o -+qcom-ppe-objs := ppe.o ppe_config.o ---- a/drivers/net/ethernet/qualcomm/ppe/ppe.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.c -@@ -15,6 +15,7 @@ - #include - - #include "ppe.h" -+#include "ppe_config.h" - - #define PPE_PORT_MAX 8 - #define PPE_CLK_RATE 353000000 -@@ -194,6 +195,10 @@ static int qcom_ppe_probe(struct platfor - if (ret) - return dev_err_probe(dev, ret, "PPE clock config failed\n"); - -+ ret = ppe_hw_config(ppe_dev); -+ if (ret) -+ return dev_err_probe(dev, ret, "PPE HW config failed\n"); -+ - platform_set_drvdata(pdev, ppe_dev); - - return 0; ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -@@ -0,0 +1,195 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+/* PPE HW initialization configs such as BM(buffer management), -+ * QM(queue management) and scheduler configs. -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include "ppe.h" -+#include "ppe_config.h" -+#include "ppe_regs.h" -+ -+/** -+ * struct ppe_bm_port_config - PPE BM port configuration. -+ * @port_id_start: The fist BM port ID to configure. -+ * @port_id_end: The last BM port ID to configure. -+ * @pre_alloc: BM port dedicated buffer number. -+ * @in_fly_buf: Buffer number for receiving the packet after pause frame sent. -+ * @ceil: Ceil to generate the back pressure. -+ * @weight: Weight value. -+ * @resume_offset: Resume offset from the threshold value. -+ * @resume_ceil: Ceil to resume from the back pressure state. -+ * @dynamic: Dynamic threshold used or not. -+ * -+ * The is for configuring the threshold that impacts the port -+ * flow control. -+ */ -+struct ppe_bm_port_config { -+ unsigned int port_id_start; -+ unsigned int port_id_end; -+ unsigned int pre_alloc; -+ unsigned int in_fly_buf; -+ unsigned int ceil; -+ unsigned int weight; -+ unsigned int resume_offset; -+ unsigned int resume_ceil; -+ bool dynamic; -+}; -+ -+/* Assign the share buffer number 1550 to group 0 by default. */ -+static const int ipq9574_ppe_bm_group_config = 1550; -+ -+/* The buffer configurations per PPE port. There are 15 BM ports and -+ * 4 BM groups supported by PPE. BM port (0-7) is for EDMA port 0, -+ * BM port (8-13) is for PPE physical port 1-6 and BM port 14 is for -+ * EIP port. -+ */ -+static const struct ppe_bm_port_config ipq9574_ppe_bm_port_config[] = { -+ { -+ /* Buffer configuration for the BM port ID 0 of EDMA. */ -+ .port_id_start = 0, -+ .port_id_end = 0, -+ .pre_alloc = 0, -+ .in_fly_buf = 100, -+ .ceil = 1146, -+ .weight = 7, -+ .resume_offset = 8, -+ .resume_ceil = 0, -+ .dynamic = true, -+ }, -+ { -+ /* Buffer configuration for the BM port ID 1-7 of EDMA. */ -+ .port_id_start = 1, -+ .port_id_end = 7, -+ .pre_alloc = 0, -+ .in_fly_buf = 100, -+ .ceil = 250, -+ .weight = 4, -+ .resume_offset = 36, -+ .resume_ceil = 0, -+ .dynamic = true, -+ }, -+ { -+ /* Buffer configuration for the BM port ID 8-13 of PPE ports. */ -+ .port_id_start = 8, -+ .port_id_end = 13, -+ .pre_alloc = 0, -+ .in_fly_buf = 128, -+ .ceil = 250, -+ .weight = 4, -+ .resume_offset = 36, -+ .resume_ceil = 0, -+ .dynamic = true, -+ }, -+ { -+ /* Buffer configuration for the BM port ID 14 of EIP. */ -+ .port_id_start = 14, -+ .port_id_end = 14, -+ .pre_alloc = 0, -+ .in_fly_buf = 40, -+ .ceil = 250, -+ .weight = 4, -+ .resume_offset = 36, -+ .resume_ceil = 0, -+ .dynamic = true, -+ }, -+}; -+ -+static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id, -+ const struct ppe_bm_port_config port_cfg) -+{ -+ u32 reg, val, bm_fc_val[2]; -+ int ret; -+ -+ reg = PPE_BM_PORT_FC_CFG_TBL_ADDR + PPE_BM_PORT_FC_CFG_TBL_INC * bm_port_id; -+ ret = regmap_bulk_read(ppe_dev->regmap, reg, -+ bm_fc_val, ARRAY_SIZE(bm_fc_val)); -+ if (ret) -+ return ret; -+ -+ /* Configure BM flow control related threshold. */ -+ PPE_BM_PORT_FC_SET_WEIGHT(bm_fc_val, port_cfg.weight); -+ PPE_BM_PORT_FC_SET_RESUME_OFFSET(bm_fc_val, port_cfg.resume_offset); -+ PPE_BM_PORT_FC_SET_RESUME_THRESHOLD(bm_fc_val, port_cfg.resume_ceil); -+ PPE_BM_PORT_FC_SET_DYNAMIC(bm_fc_val, port_cfg.dynamic); -+ PPE_BM_PORT_FC_SET_REACT_LIMIT(bm_fc_val, port_cfg.in_fly_buf); -+ PPE_BM_PORT_FC_SET_PRE_ALLOC(bm_fc_val, port_cfg.pre_alloc); -+ -+ /* Configure low/high bits of the ceiling for the BM port. */ -+ val = FIELD_GET(GENMASK(2, 0), port_cfg.ceil); -+ PPE_BM_PORT_FC_SET_CEILING_LOW(bm_fc_val, val); -+ val = FIELD_GET(GENMASK(10, 3), port_cfg.ceil); -+ PPE_BM_PORT_FC_SET_CEILING_HIGH(bm_fc_val, val); -+ -+ ret = regmap_bulk_write(ppe_dev->regmap, reg, -+ bm_fc_val, ARRAY_SIZE(bm_fc_val)); -+ if (ret) -+ return ret; -+ -+ /* Assign the default group ID 0 to the BM port. */ -+ val = FIELD_PREP(PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID, 0); -+ reg = PPE_BM_PORT_GROUP_ID_ADDR + PPE_BM_PORT_GROUP_ID_INC * bm_port_id; -+ ret = regmap_update_bits(ppe_dev->regmap, reg, -+ PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID, -+ val); -+ if (ret) -+ return ret; -+ -+ /* Enable BM port flow control. */ -+ reg = PPE_BM_PORT_FC_MODE_ADDR + PPE_BM_PORT_FC_MODE_INC * bm_port_id; -+ -+ return regmap_set_bits(ppe_dev->regmap, reg, PPE_BM_PORT_FC_MODE_EN); -+} -+ -+/* Configure the buffer threshold for the port flow control function. */ -+static int ppe_config_bm(struct ppe_device *ppe_dev) -+{ -+ const struct ppe_bm_port_config *port_cfg; -+ unsigned int i, bm_port_id, port_cfg_cnt; -+ u32 reg, val; -+ int ret; -+ -+ /* Configure the allocated buffer number only for group 0. -+ * The buffer number of group 1-3 is already cleared to 0 -+ * after PPE reset during the probe of PPE driver. -+ */ -+ reg = PPE_BM_SHARED_GROUP_CFG_ADDR; -+ val = FIELD_PREP(PPE_BM_SHARED_GROUP_CFG_SHARED_LIMIT, -+ ipq9574_ppe_bm_group_config); -+ ret = regmap_update_bits(ppe_dev->regmap, reg, -+ PPE_BM_SHARED_GROUP_CFG_SHARED_LIMIT, -+ val); -+ if (ret) -+ goto bm_config_fail; -+ -+ /* Configure buffer thresholds for the BM ports. */ -+ port_cfg = ipq9574_ppe_bm_port_config; -+ port_cfg_cnt = ARRAY_SIZE(ipq9574_ppe_bm_port_config); -+ for (i = 0; i < port_cfg_cnt; i++) { -+ for (bm_port_id = port_cfg[i].port_id_start; -+ bm_port_id <= port_cfg[i].port_id_end; bm_port_id++) { -+ ret = ppe_config_bm_threshold(ppe_dev, bm_port_id, -+ port_cfg[i]); -+ if (ret) -+ goto bm_config_fail; -+ } -+ } -+ -+ return 0; -+ -+bm_config_fail: -+ dev_err(ppe_dev->dev, "PPE BM config error %d\n", ret); -+ return ret; -+} -+ -+int ppe_hw_config(struct ppe_device *ppe_dev) -+{ -+ return ppe_config_bm(ppe_dev); -+} ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h -@@ -0,0 +1,12 @@ -+/* SPDX-License-Identifier: GPL-2.0-only -+ * -+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#ifndef __PPE_CONFIG_H__ -+#define __PPE_CONFIG_H__ -+ -+#include "ppe.h" -+ -+int ppe_hw_config(struct ppe_device *ppe_dev); -+#endif ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -@@ -0,0 +1,59 @@ -+/* SPDX-License-Identifier: GPL-2.0-only -+ * -+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+/* PPE hardware register and table declarations. */ -+#ifndef __PPE_REGS_H__ -+#define __PPE_REGS_H__ -+ -+#include -+ -+/* There are 15 BM ports and 4 BM groups supported by PPE. -+ * BM port (0-7) is for EDMA port 0, BM port (8-13) is for -+ * PPE physical port 1-6 and BM port 14 is for EIP port. -+ */ -+#define PPE_BM_PORT_FC_MODE_ADDR 0x600100 -+#define PPE_BM_PORT_FC_MODE_ENTRIES 15 -+#define PPE_BM_PORT_FC_MODE_INC 0x4 -+#define PPE_BM_PORT_FC_MODE_EN BIT(0) -+ -+#define PPE_BM_PORT_GROUP_ID_ADDR 0x600180 -+#define PPE_BM_PORT_GROUP_ID_ENTRIES 15 -+#define PPE_BM_PORT_GROUP_ID_INC 0x4 -+#define PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID GENMASK(1, 0) -+ -+#define PPE_BM_SHARED_GROUP_CFG_ADDR 0x600290 -+#define PPE_BM_SHARED_GROUP_CFG_ENTRIES 4 -+#define PPE_BM_SHARED_GROUP_CFG_INC 0x4 -+#define PPE_BM_SHARED_GROUP_CFG_SHARED_LIMIT GENMASK(10, 0) -+ -+#define PPE_BM_PORT_FC_CFG_TBL_ADDR 0x601000 -+#define PPE_BM_PORT_FC_CFG_TBL_ENTRIES 15 -+#define PPE_BM_PORT_FC_CFG_TBL_INC 0x10 -+#define PPE_BM_PORT_FC_W0_REACT_LIMIT GENMASK(8, 0) -+#define PPE_BM_PORT_FC_W0_RESUME_THRESHOLD GENMASK(17, 9) -+#define PPE_BM_PORT_FC_W0_RESUME_OFFSET GENMASK(28, 18) -+#define PPE_BM_PORT_FC_W0_CEILING_LOW GENMASK(31, 29) -+#define PPE_BM_PORT_FC_W1_CEILING_HIGH GENMASK(7, 0) -+#define PPE_BM_PORT_FC_W1_WEIGHT GENMASK(10, 8) -+#define PPE_BM_PORT_FC_W1_DYNAMIC BIT(11) -+#define PPE_BM_PORT_FC_W1_PRE_ALLOC GENMASK(22, 12) -+ -+#define PPE_BM_PORT_FC_SET_REACT_LIMIT(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_BM_PORT_FC_W0_REACT_LIMIT) -+#define PPE_BM_PORT_FC_SET_RESUME_THRESHOLD(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_BM_PORT_FC_W0_RESUME_THRESHOLD) -+#define PPE_BM_PORT_FC_SET_RESUME_OFFSET(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_BM_PORT_FC_W0_RESUME_OFFSET) -+#define PPE_BM_PORT_FC_SET_CEILING_LOW(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_BM_PORT_FC_W0_CEILING_LOW) -+#define PPE_BM_PORT_FC_SET_CEILING_HIGH(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_BM_PORT_FC_W1_CEILING_HIGH) -+#define PPE_BM_PORT_FC_SET_WEIGHT(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_BM_PORT_FC_W1_WEIGHT) -+#define PPE_BM_PORT_FC_SET_DYNAMIC(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_BM_PORT_FC_W1_DYNAMIC) -+#define PPE_BM_PORT_FC_SET_PRE_ALLOC(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_BM_PORT_FC_W1_PRE_ALLOC) -+#endif diff --git a/target/linux/qualcommbe/patches-6.12/0327-net-ethernet-qualcomm-Initialize-PPE-queue-managemen.patch b/target/linux/qualcommbe/patches-6.12/0327-net-ethernet-qualcomm-Initialize-PPE-queue-managemen.patch deleted file mode 100644 index be16222b96..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0327-net-ethernet-qualcomm-Initialize-PPE-queue-managemen.patch +++ /dev/null @@ -1,320 +0,0 @@ -From 9be6c3590ef3c241e6a3cfd05291304a1f973bcf Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 9 Feb 2025 22:29:39 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Initialize PPE queue management for - IPQ9574 - -QM (queue management) configurations decide the length of PPE -queues and the queue depth for these queues which are used to -drop packets in events of congestion. - -There are two types of PPE queues - unicast queues (0-255) and -multicast queues (256-299). These queue types are used to forward -different types of traffic, and are configured with different -lengths. - -Signed-off-by: Luo Jie ---- - .../net/ethernet/qualcomm/ppe/ppe_config.c | 177 +++++++++++++++++- - drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 85 +++++++++ - 2 files changed, 261 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -@@ -43,6 +43,29 @@ struct ppe_bm_port_config { - bool dynamic; - }; - -+/** -+ * struct ppe_qm_queue_config - PPE queue config. -+ * @queue_start: PPE start of queue ID. -+ * @queue_end: PPE end of queue ID. -+ * @prealloc_buf: Queue dedicated buffer number. -+ * @ceil: Ceil to start drop packet from queue. -+ * @weight: Weight value. -+ * @resume_offset: Resume offset from the threshold. -+ * @dynamic: Threshold value is decided dynamically or statically. -+ * -+ * Queue configuration decides the threshold to drop packet from PPE -+ * hardware queue. -+ */ -+struct ppe_qm_queue_config { -+ unsigned int queue_start; -+ unsigned int queue_end; -+ unsigned int prealloc_buf; -+ unsigned int ceil; -+ unsigned int weight; -+ unsigned int resume_offset; -+ bool dynamic; -+}; -+ - /* Assign the share buffer number 1550 to group 0 by default. */ - static const int ipq9574_ppe_bm_group_config = 1550; - -@@ -102,6 +125,33 @@ static const struct ppe_bm_port_config i - }, - }; - -+/* Default QM group settings for IPQ9754. */ -+static const int ipq9574_ppe_qm_group_config = 2000; -+ -+/* Default QM settings for unicast and multicast queues for IPQ9754. */ -+static const struct ppe_qm_queue_config ipq9574_ppe_qm_queue_config[] = { -+ { -+ /* QM settings for unicast queues 0 to 255. */ -+ .queue_start = 0, -+ .queue_end = 255, -+ .prealloc_buf = 0, -+ .ceil = 1200, -+ .weight = 7, -+ .resume_offset = 36, -+ .dynamic = true, -+ }, -+ { -+ /* QM settings for multicast queues 256 to 299. */ -+ .queue_start = 256, -+ .queue_end = 299, -+ .prealloc_buf = 0, -+ .ceil = 250, -+ .weight = 0, -+ .resume_offset = 36, -+ .dynamic = false, -+ }, -+}; -+ - static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id, - const struct ppe_bm_port_config port_cfg) - { -@@ -189,7 +239,132 @@ bm_config_fail: - return ret; - } - -+/* Configure PPE hardware queue depth, which is decided by the threshold -+ * of queue. -+ */ -+static int ppe_config_qm(struct ppe_device *ppe_dev) -+{ -+ const struct ppe_qm_queue_config *queue_cfg; -+ int ret, i, queue_id, queue_cfg_count; -+ u32 reg, multicast_queue_cfg[5]; -+ u32 unicast_queue_cfg[4]; -+ u32 group_cfg[3]; -+ -+ /* Assign the buffer number to the group 0 by default. */ -+ reg = PPE_AC_GRP_CFG_TBL_ADDR; -+ ret = regmap_bulk_read(ppe_dev->regmap, reg, -+ group_cfg, ARRAY_SIZE(group_cfg)); -+ if (ret) -+ goto qm_config_fail; -+ -+ PPE_AC_GRP_SET_BUF_LIMIT(group_cfg, ipq9574_ppe_qm_group_config); -+ -+ ret = regmap_bulk_write(ppe_dev->regmap, reg, -+ group_cfg, ARRAY_SIZE(group_cfg)); -+ if (ret) -+ goto qm_config_fail; -+ -+ queue_cfg = ipq9574_ppe_qm_queue_config; -+ queue_cfg_count = ARRAY_SIZE(ipq9574_ppe_qm_queue_config); -+ for (i = 0; i < queue_cfg_count; i++) { -+ queue_id = queue_cfg[i].queue_start; -+ -+ /* Configure threshold for dropping packets separately for -+ * unicast and multicast PPE queues. -+ */ -+ while (queue_id <= queue_cfg[i].queue_end) { -+ if (queue_id < PPE_AC_UNICAST_QUEUE_CFG_TBL_ENTRIES) { -+ reg = PPE_AC_UNICAST_QUEUE_CFG_TBL_ADDR + -+ PPE_AC_UNICAST_QUEUE_CFG_TBL_INC * queue_id; -+ -+ ret = regmap_bulk_read(ppe_dev->regmap, reg, -+ unicast_queue_cfg, -+ ARRAY_SIZE(unicast_queue_cfg)); -+ if (ret) -+ goto qm_config_fail; -+ -+ PPE_AC_UNICAST_QUEUE_SET_EN(unicast_queue_cfg, true); -+ PPE_AC_UNICAST_QUEUE_SET_GRP_ID(unicast_queue_cfg, 0); -+ PPE_AC_UNICAST_QUEUE_SET_PRE_LIMIT(unicast_queue_cfg, -+ queue_cfg[i].prealloc_buf); -+ PPE_AC_UNICAST_QUEUE_SET_DYNAMIC(unicast_queue_cfg, -+ queue_cfg[i].dynamic); -+ PPE_AC_UNICAST_QUEUE_SET_WEIGHT(unicast_queue_cfg, -+ queue_cfg[i].weight); -+ PPE_AC_UNICAST_QUEUE_SET_THRESHOLD(unicast_queue_cfg, -+ queue_cfg[i].ceil); -+ PPE_AC_UNICAST_QUEUE_SET_GRN_RESUME(unicast_queue_cfg, -+ queue_cfg[i].resume_offset); -+ -+ ret = regmap_bulk_write(ppe_dev->regmap, reg, -+ unicast_queue_cfg, -+ ARRAY_SIZE(unicast_queue_cfg)); -+ if (ret) -+ goto qm_config_fail; -+ } else { -+ reg = PPE_AC_MULTICAST_QUEUE_CFG_TBL_ADDR + -+ PPE_AC_MULTICAST_QUEUE_CFG_TBL_INC * queue_id; -+ -+ ret = regmap_bulk_read(ppe_dev->regmap, reg, -+ multicast_queue_cfg, -+ ARRAY_SIZE(multicast_queue_cfg)); -+ if (ret) -+ goto qm_config_fail; -+ -+ PPE_AC_MULTICAST_QUEUE_SET_EN(multicast_queue_cfg, true); -+ PPE_AC_MULTICAST_QUEUE_SET_GRN_GRP_ID(multicast_queue_cfg, 0); -+ PPE_AC_MULTICAST_QUEUE_SET_GRN_PRE_LIMIT(multicast_queue_cfg, -+ queue_cfg[i].prealloc_buf); -+ PPE_AC_MULTICAST_QUEUE_SET_GRN_THRESHOLD(multicast_queue_cfg, -+ queue_cfg[i].ceil); -+ PPE_AC_MULTICAST_QUEUE_SET_GRN_RESUME(multicast_queue_cfg, -+ queue_cfg[i].resume_offset); -+ -+ ret = regmap_bulk_write(ppe_dev->regmap, reg, -+ multicast_queue_cfg, -+ ARRAY_SIZE(multicast_queue_cfg)); -+ if (ret) -+ goto qm_config_fail; -+ } -+ -+ /* Enable enqueue. */ -+ reg = PPE_ENQ_OPR_TBL_ADDR + PPE_ENQ_OPR_TBL_INC * queue_id; -+ ret = regmap_clear_bits(ppe_dev->regmap, reg, -+ PPE_ENQ_OPR_TBL_ENQ_DISABLE); -+ if (ret) -+ goto qm_config_fail; -+ -+ /* Enable dequeue. */ -+ reg = PPE_DEQ_OPR_TBL_ADDR + PPE_DEQ_OPR_TBL_INC * queue_id; -+ ret = regmap_clear_bits(ppe_dev->regmap, reg, -+ PPE_DEQ_OPR_TBL_DEQ_DISABLE); -+ if (ret) -+ goto qm_config_fail; -+ -+ queue_id++; -+ } -+ } -+ -+ /* Enable queue counter for all PPE hardware queues. */ -+ ret = regmap_set_bits(ppe_dev->regmap, PPE_EG_BRIDGE_CONFIG_ADDR, -+ PPE_EG_BRIDGE_CONFIG_QUEUE_CNT_EN); -+ if (ret) -+ goto qm_config_fail; -+ -+ return 0; -+ -+qm_config_fail: -+ dev_err(ppe_dev->dev, "PPE QM config error %d\n", ret); -+ return ret; -+} -+ - int ppe_hw_config(struct ppe_device *ppe_dev) - { -- return ppe_config_bm(ppe_dev); -+ int ret; -+ -+ ret = ppe_config_bm(ppe_dev); -+ if (ret) -+ return ret; -+ -+ return ppe_config_qm(ppe_dev); - } ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -@@ -9,6 +9,16 @@ - - #include - -+/* PPE queue counters enable/disable control. */ -+#define PPE_EG_BRIDGE_CONFIG_ADDR 0x20044 -+#define PPE_EG_BRIDGE_CONFIG_QUEUE_CNT_EN BIT(2) -+ -+/* Table addresses for per-queue dequeue setting. */ -+#define PPE_DEQ_OPR_TBL_ADDR 0x430000 -+#define PPE_DEQ_OPR_TBL_ENTRIES 300 -+#define PPE_DEQ_OPR_TBL_INC 0x10 -+#define PPE_DEQ_OPR_TBL_DEQ_DISABLE BIT(0) -+ - /* There are 15 BM ports and 4 BM groups supported by PPE. - * BM port (0-7) is for EDMA port 0, BM port (8-13) is for - * PPE physical port 1-6 and BM port 14 is for EIP port. -@@ -56,4 +66,79 @@ - u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_BM_PORT_FC_W1_DYNAMIC) - #define PPE_BM_PORT_FC_SET_PRE_ALLOC(tbl_cfg, value) \ - u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_BM_PORT_FC_W1_PRE_ALLOC) -+ -+/* PPE unicast queue (0-255) configurations. */ -+#define PPE_AC_UNICAST_QUEUE_CFG_TBL_ADDR 0x848000 -+#define PPE_AC_UNICAST_QUEUE_CFG_TBL_ENTRIES 256 -+#define PPE_AC_UNICAST_QUEUE_CFG_TBL_INC 0x10 -+#define PPE_AC_UNICAST_QUEUE_CFG_W0_EN BIT(0) -+#define PPE_AC_UNICAST_QUEUE_CFG_W0_WRED_EN BIT(1) -+#define PPE_AC_UNICAST_QUEUE_CFG_W0_FC_EN BIT(2) -+#define PPE_AC_UNICAST_QUEUE_CFG_W0_CLR_AWARE BIT(3) -+#define PPE_AC_UNICAST_QUEUE_CFG_W0_GRP_ID GENMASK(5, 4) -+#define PPE_AC_UNICAST_QUEUE_CFG_W0_PRE_LIMIT GENMASK(16, 6) -+#define PPE_AC_UNICAST_QUEUE_CFG_W0_DYNAMIC BIT(17) -+#define PPE_AC_UNICAST_QUEUE_CFG_W0_WEIGHT GENMASK(20, 18) -+#define PPE_AC_UNICAST_QUEUE_CFG_W0_THRESHOLD GENMASK(31, 21) -+#define PPE_AC_UNICAST_QUEUE_CFG_W3_GRN_RESUME GENMASK(23, 13) -+ -+#define PPE_AC_UNICAST_QUEUE_SET_EN(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_AC_UNICAST_QUEUE_CFG_W0_EN) -+#define PPE_AC_UNICAST_QUEUE_SET_GRP_ID(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_AC_UNICAST_QUEUE_CFG_W0_GRP_ID) -+#define PPE_AC_UNICAST_QUEUE_SET_PRE_LIMIT(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_AC_UNICAST_QUEUE_CFG_W0_PRE_LIMIT) -+#define PPE_AC_UNICAST_QUEUE_SET_DYNAMIC(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_AC_UNICAST_QUEUE_CFG_W0_DYNAMIC) -+#define PPE_AC_UNICAST_QUEUE_SET_WEIGHT(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_AC_UNICAST_QUEUE_CFG_W0_WEIGHT) -+#define PPE_AC_UNICAST_QUEUE_SET_THRESHOLD(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_AC_UNICAST_QUEUE_CFG_W0_THRESHOLD) -+#define PPE_AC_UNICAST_QUEUE_SET_GRN_RESUME(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x3, value, PPE_AC_UNICAST_QUEUE_CFG_W3_GRN_RESUME) -+ -+/* PPE multicast queue (256-299) configurations. */ -+#define PPE_AC_MULTICAST_QUEUE_CFG_TBL_ADDR 0x84a000 -+#define PPE_AC_MULTICAST_QUEUE_CFG_TBL_ENTRIES 44 -+#define PPE_AC_MULTICAST_QUEUE_CFG_TBL_INC 0x10 -+#define PPE_AC_MULTICAST_QUEUE_CFG_W0_EN BIT(0) -+#define PPE_AC_MULTICAST_QUEUE_CFG_W0_FC_EN BIT(1) -+#define PPE_AC_MULTICAST_QUEUE_CFG_W0_CLR_AWARE BIT(2) -+#define PPE_AC_MULTICAST_QUEUE_CFG_W0_GRP_ID GENMASK(4, 3) -+#define PPE_AC_MULTICAST_QUEUE_CFG_W0_PRE_LIMIT GENMASK(15, 5) -+#define PPE_AC_MULTICAST_QUEUE_CFG_W0_THRESHOLD GENMASK(26, 16) -+#define PPE_AC_MULTICAST_QUEUE_CFG_W2_RESUME GENMASK(17, 7) -+ -+#define PPE_AC_MULTICAST_QUEUE_SET_EN(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_AC_MULTICAST_QUEUE_CFG_W0_EN) -+#define PPE_AC_MULTICAST_QUEUE_SET_GRN_GRP_ID(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_AC_MULTICAST_QUEUE_CFG_W0_GRP_ID) -+#define PPE_AC_MULTICAST_QUEUE_SET_GRN_PRE_LIMIT(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_AC_MULTICAST_QUEUE_CFG_W0_PRE_LIMIT) -+#define PPE_AC_MULTICAST_QUEUE_SET_GRN_THRESHOLD(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_AC_MULTICAST_QUEUE_CFG_W0_THRESHOLD) -+#define PPE_AC_MULTICAST_QUEUE_SET_GRN_RESUME(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x2, value, PPE_AC_MULTICAST_QUEUE_CFG_W2_RESUME) -+ -+/* PPE admission control group (0-3) configurations */ -+#define PPE_AC_GRP_CFG_TBL_ADDR 0x84c000 -+#define PPE_AC_GRP_CFG_TBL_ENTRIES 0x4 -+#define PPE_AC_GRP_CFG_TBL_INC 0x10 -+#define PPE_AC_GRP_W0_AC_EN BIT(0) -+#define PPE_AC_GRP_W0_AC_FC_EN BIT(1) -+#define PPE_AC_GRP_W0_CLR_AWARE BIT(2) -+#define PPE_AC_GRP_W0_THRESHOLD_LOW GENMASK(31, 25) -+#define PPE_AC_GRP_W1_THRESHOLD_HIGH GENMASK(3, 0) -+#define PPE_AC_GRP_W1_BUF_LIMIT GENMASK(14, 4) -+#define PPE_AC_GRP_W2_RESUME_GRN GENMASK(15, 5) -+#define PPE_AC_GRP_W2_PRE_ALLOC GENMASK(26, 16) -+ -+#define PPE_AC_GRP_SET_BUF_LIMIT(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_AC_GRP_W1_BUF_LIMIT) -+ -+/* Table addresses for per-queue enqueue setting. */ -+#define PPE_ENQ_OPR_TBL_ADDR 0x85c000 -+#define PPE_ENQ_OPR_TBL_ENTRIES 300 -+#define PPE_ENQ_OPR_TBL_INC 0x10 -+#define PPE_ENQ_OPR_TBL_ENQ_DISABLE BIT(0) - #endif diff --git a/target/linux/qualcommbe/patches-6.12/0328-net-ethernet-qualcomm-Initialize-the-PPE-scheduler-s.patch b/target/linux/qualcommbe/patches-6.12/0328-net-ethernet-qualcomm-Initialize-the-PPE-scheduler-s.patch deleted file mode 100644 index 86949a2f3b..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0328-net-ethernet-qualcomm-Initialize-the-PPE-scheduler-s.patch +++ /dev/null @@ -1,1000 +0,0 @@ -From 333edaf474cd707b0a04c57f255b56bc3c015789 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 9 Feb 2025 22:29:40 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Initialize the PPE scheduler - settings - -The PPE scheduler settings determine the priority of scheduling the -packet across the different hardware queues per PPE port. - -Signed-off-by: Luo Jie ---- - .../net/ethernet/qualcomm/ppe/ppe_config.c | 788 +++++++++++++++++- - .../net/ethernet/qualcomm/ppe/ppe_config.h | 37 + - drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 97 +++ - 3 files changed, 921 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -@@ -16,6 +16,8 @@ - #include "ppe_config.h" - #include "ppe_regs.h" - -+#define PPE_QUEUE_SCH_PRI_NUM 8 -+ - /** - * struct ppe_bm_port_config - PPE BM port configuration. - * @port_id_start: The fist BM port ID to configure. -@@ -66,6 +68,66 @@ struct ppe_qm_queue_config { - bool dynamic; - }; - -+/** -+ * struct ppe_scheduler_bm_config - PPE arbitration for buffer config. -+ * @valid: Arbitration entry valid or not. -+ * @is_egress: Arbitration entry for egress or not. -+ * @port: Port ID to use arbitration entry. -+ * @second_valid: Second port valid or not. -+ * @second_port: Second port to use. -+ * -+ * Configure the scheduler settings for accessing and releasing the PPE buffers. -+ */ -+struct ppe_scheduler_bm_config { -+ bool valid; -+ bool is_egress; -+ unsigned int port; -+ bool second_valid; -+ unsigned int second_port; -+}; -+ -+/** -+ * struct ppe_scheduler_qm_config - PPE arbitration for scheduler config. -+ * @ensch_port_bmp: Port bit map for enqueue scheduler. -+ * @ensch_port: Port ID to enqueue scheduler. -+ * @desch_port: Port ID to dequeue scheduler. -+ * @desch_second_valid: Dequeue for the second port valid or not. -+ * @desch_second_port: Second port ID to dequeue scheduler. -+ * -+ * Configure the scheduler settings for enqueuing and dequeuing packets on -+ * the PPE port. -+ */ -+struct ppe_scheduler_qm_config { -+ unsigned int ensch_port_bmp; -+ unsigned int ensch_port; -+ unsigned int desch_port; -+ bool desch_second_valid; -+ unsigned int desch_second_port; -+}; -+ -+/** -+ * struct ppe_scheduler_port_config - PPE port scheduler config. -+ * @port: Port ID to be scheduled. -+ * @flow_level: Scheduler flow level or not. -+ * @node_id: Node ID, for level 0, queue ID is used. -+ * @loop_num: Loop number of scheduler config. -+ * @pri_max: Max priority configured. -+ * @flow_id: Strict priority ID. -+ * @drr_node_id: Node ID for scheduler. -+ * -+ * PPE port scheduler configuration which decides the priority in the -+ * packet scheduler for the egress port. -+ */ -+struct ppe_scheduler_port_config { -+ unsigned int port; -+ bool flow_level; -+ unsigned int node_id; -+ unsigned int loop_num; -+ unsigned int pri_max; -+ unsigned int flow_id; -+ unsigned int drr_node_id; -+}; -+ - /* Assign the share buffer number 1550 to group 0 by default. */ - static const int ipq9574_ppe_bm_group_config = 1550; - -@@ -152,6 +214,599 @@ static const struct ppe_qm_queue_config - }, - }; - -+/* Scheduler configuration for the assigning and releasing buffers for the -+ * packet passing through PPE, which is different per SoC. -+ */ -+static const struct ppe_scheduler_bm_config ipq9574_ppe_sch_bm_config[] = { -+ {1, 0, 0, 0, 0}, -+ {1, 1, 0, 0, 0}, -+ {1, 0, 5, 0, 0}, -+ {1, 1, 5, 0, 0}, -+ {1, 0, 6, 0, 0}, -+ {1, 1, 6, 0, 0}, -+ {1, 0, 1, 0, 0}, -+ {1, 1, 1, 0, 0}, -+ {1, 0, 0, 0, 0}, -+ {1, 1, 0, 0, 0}, -+ {1, 0, 5, 0, 0}, -+ {1, 1, 5, 0, 0}, -+ {1, 0, 6, 0, 0}, -+ {1, 1, 6, 0, 0}, -+ {1, 0, 7, 0, 0}, -+ {1, 1, 7, 0, 0}, -+ {1, 0, 0, 0, 0}, -+ {1, 1, 0, 0, 0}, -+ {1, 0, 1, 0, 0}, -+ {1, 1, 1, 0, 0}, -+ {1, 0, 5, 0, 0}, -+ {1, 1, 5, 0, 0}, -+ {1, 0, 6, 0, 0}, -+ {1, 1, 6, 0, 0}, -+ {1, 0, 2, 0, 0}, -+ {1, 1, 2, 0, 0}, -+ {1, 0, 0, 0, 0}, -+ {1, 1, 0, 0, 0}, -+ {1, 0, 5, 0, 0}, -+ {1, 1, 5, 0, 0}, -+ {1, 0, 6, 0, 0}, -+ {1, 1, 6, 0, 0}, -+ {1, 0, 1, 0, 0}, -+ {1, 1, 1, 0, 0}, -+ {1, 0, 3, 0, 0}, -+ {1, 1, 3, 0, 0}, -+ {1, 0, 0, 0, 0}, -+ {1, 1, 0, 0, 0}, -+ {1, 0, 5, 0, 0}, -+ {1, 1, 5, 0, 0}, -+ {1, 0, 6, 0, 0}, -+ {1, 1, 6, 0, 0}, -+ {1, 0, 7, 0, 0}, -+ {1, 1, 7, 0, 0}, -+ {1, 0, 0, 0, 0}, -+ {1, 1, 0, 0, 0}, -+ {1, 0, 1, 0, 0}, -+ {1, 1, 1, 0, 0}, -+ {1, 0, 5, 0, 0}, -+ {1, 1, 5, 0, 0}, -+ {1, 0, 6, 0, 0}, -+ {1, 1, 6, 0, 0}, -+ {1, 0, 4, 0, 0}, -+ {1, 1, 4, 0, 0}, -+ {1, 0, 0, 0, 0}, -+ {1, 1, 0, 0, 0}, -+ {1, 0, 5, 0, 0}, -+ {1, 1, 5, 0, 0}, -+ {1, 0, 6, 0, 0}, -+ {1, 1, 6, 0, 0}, -+ {1, 0, 1, 0, 0}, -+ {1, 1, 1, 0, 0}, -+ {1, 0, 0, 0, 0}, -+ {1, 1, 0, 0, 0}, -+ {1, 0, 5, 0, 0}, -+ {1, 1, 5, 0, 0}, -+ {1, 0, 6, 0, 0}, -+ {1, 1, 6, 0, 0}, -+ {1, 0, 2, 0, 0}, -+ {1, 1, 2, 0, 0}, -+ {1, 0, 0, 0, 0}, -+ {1, 1, 0, 0, 0}, -+ {1, 0, 7, 0, 0}, -+ {1, 1, 7, 0, 0}, -+ {1, 0, 5, 0, 0}, -+ {1, 1, 5, 0, 0}, -+ {1, 0, 6, 0, 0}, -+ {1, 1, 6, 0, 0}, -+ {1, 0, 1, 0, 0}, -+ {1, 1, 1, 0, 0}, -+ {1, 0, 0, 0, 0}, -+ {1, 1, 0, 0, 0}, -+ {1, 0, 5, 0, 0}, -+ {1, 1, 5, 0, 0}, -+ {1, 0, 6, 0, 0}, -+ {1, 1, 6, 0, 0}, -+ {1, 0, 3, 0, 0}, -+ {1, 1, 3, 0, 0}, -+ {1, 0, 1, 0, 0}, -+ {1, 1, 1, 0, 0}, -+ {1, 0, 0, 0, 0}, -+ {1, 1, 0, 0, 0}, -+ {1, 0, 5, 0, 0}, -+ {1, 1, 5, 0, 0}, -+ {1, 0, 6, 0, 0}, -+ {1, 1, 6, 0, 0}, -+ {1, 0, 4, 0, 0}, -+ {1, 1, 4, 0, 0}, -+ {1, 0, 7, 0, 0}, -+ {1, 1, 7, 0, 0}, -+}; -+ -+/* Scheduler configuration for dispatching packet on PPE queues, which -+ * is different per SoC. -+ */ -+static const struct ppe_scheduler_qm_config ipq9574_ppe_sch_qm_config[] = { -+ {0x98, 6, 0, 1, 1}, -+ {0x94, 5, 6, 1, 3}, -+ {0x86, 0, 5, 1, 4}, -+ {0x8C, 1, 6, 1, 0}, -+ {0x1C, 7, 5, 1, 1}, -+ {0x98, 2, 6, 1, 0}, -+ {0x1C, 5, 7, 1, 1}, -+ {0x34, 3, 6, 1, 0}, -+ {0x8C, 4, 5, 1, 1}, -+ {0x98, 2, 6, 1, 0}, -+ {0x8C, 5, 4, 1, 1}, -+ {0xA8, 0, 6, 1, 2}, -+ {0x98, 5, 1, 1, 0}, -+ {0x98, 6, 5, 1, 2}, -+ {0x89, 1, 6, 1, 4}, -+ {0xA4, 3, 0, 1, 1}, -+ {0x8C, 5, 6, 1, 4}, -+ {0xA8, 0, 2, 1, 1}, -+ {0x98, 6, 5, 1, 0}, -+ {0xC4, 4, 3, 1, 1}, -+ {0x94, 6, 5, 1, 0}, -+ {0x1C, 7, 6, 1, 1}, -+ {0x98, 2, 5, 1, 0}, -+ {0x1C, 6, 7, 1, 1}, -+ {0x1C, 5, 6, 1, 0}, -+ {0x94, 3, 5, 1, 1}, -+ {0x8C, 4, 6, 1, 0}, -+ {0x94, 1, 5, 1, 3}, -+ {0x94, 6, 1, 1, 0}, -+ {0xD0, 3, 5, 1, 2}, -+ {0x98, 6, 0, 1, 1}, -+ {0x94, 5, 6, 1, 3}, -+ {0x94, 1, 5, 1, 0}, -+ {0x98, 2, 6, 1, 1}, -+ {0x8C, 4, 5, 1, 0}, -+ {0x1C, 7, 6, 1, 1}, -+ {0x8C, 0, 5, 1, 4}, -+ {0x89, 1, 6, 1, 2}, -+ {0x98, 5, 0, 1, 1}, -+ {0x94, 6, 5, 1, 3}, -+ {0x92, 0, 6, 1, 2}, -+ {0x98, 1, 5, 1, 0}, -+ {0x98, 6, 2, 1, 1}, -+ {0xD0, 0, 5, 1, 3}, -+ {0x94, 6, 0, 1, 1}, -+ {0x8C, 5, 6, 1, 4}, -+ {0x8C, 1, 5, 1, 0}, -+ {0x1C, 6, 7, 1, 1}, -+ {0x1C, 5, 6, 1, 0}, -+ {0xB0, 2, 3, 1, 1}, -+ {0xC4, 4, 5, 1, 0}, -+ {0x8C, 6, 4, 1, 1}, -+ {0xA4, 3, 6, 1, 0}, -+ {0x1C, 5, 7, 1, 1}, -+ {0x4C, 0, 5, 1, 4}, -+ {0x8C, 6, 0, 1, 1}, -+ {0x34, 7, 6, 1, 3}, -+ {0x94, 5, 0, 1, 1}, -+ {0x98, 6, 5, 1, 2}, -+}; -+ -+static const struct ppe_scheduler_port_config ppe_port_sch_config[] = { -+ { -+ .port = 0, -+ .flow_level = true, -+ .node_id = 0, -+ .loop_num = 1, -+ .pri_max = 1, -+ .flow_id = 0, -+ .drr_node_id = 0, -+ }, -+ { -+ .port = 0, -+ .flow_level = false, -+ .node_id = 0, -+ .loop_num = 8, -+ .pri_max = 8, -+ .flow_id = 0, -+ .drr_node_id = 0, -+ }, -+ { -+ .port = 0, -+ .flow_level = false, -+ .node_id = 8, -+ .loop_num = 8, -+ .pri_max = 8, -+ .flow_id = 0, -+ .drr_node_id = 0, -+ }, -+ { -+ .port = 0, -+ .flow_level = false, -+ .node_id = 16, -+ .loop_num = 8, -+ .pri_max = 8, -+ .flow_id = 0, -+ .drr_node_id = 0, -+ }, -+ { -+ .port = 0, -+ .flow_level = false, -+ .node_id = 24, -+ .loop_num = 8, -+ .pri_max = 8, -+ .flow_id = 0, -+ .drr_node_id = 0, -+ }, -+ { -+ .port = 0, -+ .flow_level = false, -+ .node_id = 32, -+ .loop_num = 8, -+ .pri_max = 8, -+ .flow_id = 0, -+ .drr_node_id = 0, -+ }, -+ { -+ .port = 0, -+ .flow_level = false, -+ .node_id = 40, -+ .loop_num = 8, -+ .pri_max = 8, -+ .flow_id = 0, -+ .drr_node_id = 0, -+ }, -+ { -+ .port = 0, -+ .flow_level = false, -+ .node_id = 48, -+ .loop_num = 8, -+ .pri_max = 8, -+ .flow_id = 0, -+ .drr_node_id = 0, -+ }, -+ { -+ .port = 0, -+ .flow_level = false, -+ .node_id = 56, -+ .loop_num = 8, -+ .pri_max = 8, -+ .flow_id = 0, -+ .drr_node_id = 0, -+ }, -+ { -+ .port = 0, -+ .flow_level = false, -+ .node_id = 256, -+ .loop_num = 8, -+ .pri_max = 8, -+ .flow_id = 0, -+ .drr_node_id = 0, -+ }, -+ { -+ .port = 0, -+ .flow_level = false, -+ .node_id = 264, -+ .loop_num = 8, -+ .pri_max = 8, -+ .flow_id = 0, -+ .drr_node_id = 0, -+ }, -+ { -+ .port = 1, -+ .flow_level = true, -+ .node_id = 36, -+ .loop_num = 2, -+ .pri_max = 0, -+ .flow_id = 1, -+ .drr_node_id = 8, -+ }, -+ { -+ .port = 1, -+ .flow_level = false, -+ .node_id = 144, -+ .loop_num = 16, -+ .pri_max = 8, -+ .flow_id = 36, -+ .drr_node_id = 48, -+ }, -+ { -+ .port = 1, -+ .flow_level = false, -+ .node_id = 272, -+ .loop_num = 4, -+ .pri_max = 4, -+ .flow_id = 36, -+ .drr_node_id = 48, -+ }, -+ { -+ .port = 2, -+ .flow_level = true, -+ .node_id = 40, -+ .loop_num = 2, -+ .pri_max = 0, -+ .flow_id = 2, -+ .drr_node_id = 12, -+ }, -+ { -+ .port = 2, -+ .flow_level = false, -+ .node_id = 160, -+ .loop_num = 16, -+ .pri_max = 8, -+ .flow_id = 40, -+ .drr_node_id = 64, -+ }, -+ { -+ .port = 2, -+ .flow_level = false, -+ .node_id = 276, -+ .loop_num = 4, -+ .pri_max = 4, -+ .flow_id = 40, -+ .drr_node_id = 64, -+ }, -+ { -+ .port = 3, -+ .flow_level = true, -+ .node_id = 44, -+ .loop_num = 2, -+ .pri_max = 0, -+ .flow_id = 3, -+ .drr_node_id = 16, -+ }, -+ { -+ .port = 3, -+ .flow_level = false, -+ .node_id = 176, -+ .loop_num = 16, -+ .pri_max = 8, -+ .flow_id = 44, -+ .drr_node_id = 80, -+ }, -+ { -+ .port = 3, -+ .flow_level = false, -+ .node_id = 280, -+ .loop_num = 4, -+ .pri_max = 4, -+ .flow_id = 44, -+ .drr_node_id = 80, -+ }, -+ { -+ .port = 4, -+ .flow_level = true, -+ .node_id = 48, -+ .loop_num = 2, -+ .pri_max = 0, -+ .flow_id = 4, -+ .drr_node_id = 20, -+ }, -+ { -+ .port = 4, -+ .flow_level = false, -+ .node_id = 192, -+ .loop_num = 16, -+ .pri_max = 8, -+ .flow_id = 48, -+ .drr_node_id = 96, -+ }, -+ { -+ .port = 4, -+ .flow_level = false, -+ .node_id = 284, -+ .loop_num = 4, -+ .pri_max = 4, -+ .flow_id = 48, -+ .drr_node_id = 96, -+ }, -+ { -+ .port = 5, -+ .flow_level = true, -+ .node_id = 52, -+ .loop_num = 2, -+ .pri_max = 0, -+ .flow_id = 5, -+ .drr_node_id = 24, -+ }, -+ { -+ .port = 5, -+ .flow_level = false, -+ .node_id = 208, -+ .loop_num = 16, -+ .pri_max = 8, -+ .flow_id = 52, -+ .drr_node_id = 112, -+ }, -+ { -+ .port = 5, -+ .flow_level = false, -+ .node_id = 288, -+ .loop_num = 4, -+ .pri_max = 4, -+ .flow_id = 52, -+ .drr_node_id = 112, -+ }, -+ { -+ .port = 6, -+ .flow_level = true, -+ .node_id = 56, -+ .loop_num = 2, -+ .pri_max = 0, -+ .flow_id = 6, -+ .drr_node_id = 28, -+ }, -+ { -+ .port = 6, -+ .flow_level = false, -+ .node_id = 224, -+ .loop_num = 16, -+ .pri_max = 8, -+ .flow_id = 56, -+ .drr_node_id = 128, -+ }, -+ { -+ .port = 6, -+ .flow_level = false, -+ .node_id = 292, -+ .loop_num = 4, -+ .pri_max = 4, -+ .flow_id = 56, -+ .drr_node_id = 128, -+ }, -+ { -+ .port = 7, -+ .flow_level = true, -+ .node_id = 60, -+ .loop_num = 2, -+ .pri_max = 0, -+ .flow_id = 7, -+ .drr_node_id = 32, -+ }, -+ { -+ .port = 7, -+ .flow_level = false, -+ .node_id = 240, -+ .loop_num = 16, -+ .pri_max = 8, -+ .flow_id = 60, -+ .drr_node_id = 144, -+ }, -+ { -+ .port = 7, -+ .flow_level = false, -+ .node_id = 296, -+ .loop_num = 4, -+ .pri_max = 4, -+ .flow_id = 60, -+ .drr_node_id = 144, -+ }, -+}; -+ -+/* Set the PPE queue level scheduler configuration. */ -+static int ppe_scheduler_l0_queue_map_set(struct ppe_device *ppe_dev, -+ int node_id, int port, -+ struct ppe_scheduler_cfg scheduler_cfg) -+{ -+ u32 val, reg; -+ int ret; -+ -+ reg = PPE_L0_FLOW_MAP_TBL_ADDR + node_id * PPE_L0_FLOW_MAP_TBL_INC; -+ val = FIELD_PREP(PPE_L0_FLOW_MAP_TBL_FLOW_ID, scheduler_cfg.flow_id); -+ val |= FIELD_PREP(PPE_L0_FLOW_MAP_TBL_C_PRI, scheduler_cfg.pri); -+ val |= FIELD_PREP(PPE_L0_FLOW_MAP_TBL_E_PRI, scheduler_cfg.pri); -+ val |= FIELD_PREP(PPE_L0_FLOW_MAP_TBL_C_NODE_WT, scheduler_cfg.drr_node_wt); -+ val |= FIELD_PREP(PPE_L0_FLOW_MAP_TBL_E_NODE_WT, scheduler_cfg.drr_node_wt); -+ -+ ret = regmap_write(ppe_dev->regmap, reg, val); -+ if (ret) -+ return ret; -+ -+ reg = PPE_L0_C_FLOW_CFG_TBL_ADDR + -+ (scheduler_cfg.flow_id * PPE_QUEUE_SCH_PRI_NUM + scheduler_cfg.pri) * -+ PPE_L0_C_FLOW_CFG_TBL_INC; -+ val = FIELD_PREP(PPE_L0_C_FLOW_CFG_TBL_NODE_ID, scheduler_cfg.drr_node_id); -+ val |= FIELD_PREP(PPE_L0_C_FLOW_CFG_TBL_NODE_CREDIT_UNIT, scheduler_cfg.unit_is_packet); -+ -+ ret = regmap_write(ppe_dev->regmap, reg, val); -+ if (ret) -+ return ret; -+ -+ reg = PPE_L0_E_FLOW_CFG_TBL_ADDR + -+ (scheduler_cfg.flow_id * PPE_QUEUE_SCH_PRI_NUM + scheduler_cfg.pri) * -+ PPE_L0_E_FLOW_CFG_TBL_INC; -+ val = FIELD_PREP(PPE_L0_E_FLOW_CFG_TBL_NODE_ID, scheduler_cfg.drr_node_id); -+ val |= FIELD_PREP(PPE_L0_E_FLOW_CFG_TBL_NODE_CREDIT_UNIT, scheduler_cfg.unit_is_packet); -+ -+ ret = regmap_write(ppe_dev->regmap, reg, val); -+ if (ret) -+ return ret; -+ -+ reg = PPE_L0_FLOW_PORT_MAP_TBL_ADDR + node_id * PPE_L0_FLOW_PORT_MAP_TBL_INC; -+ val = FIELD_PREP(PPE_L0_FLOW_PORT_MAP_TBL_PORT_NUM, port); -+ -+ ret = regmap_write(ppe_dev->regmap, reg, val); -+ if (ret) -+ return ret; -+ -+ reg = PPE_L0_COMP_CFG_TBL_ADDR + node_id * PPE_L0_COMP_CFG_TBL_INC; -+ val = FIELD_PREP(PPE_L0_COMP_CFG_TBL_NODE_METER_LEN, scheduler_cfg.frame_mode); -+ -+ return regmap_update_bits(ppe_dev->regmap, reg, -+ PPE_L0_COMP_CFG_TBL_NODE_METER_LEN, -+ val); -+} -+ -+/* Set the PPE flow level scheduler configuration. */ -+static int ppe_scheduler_l1_queue_map_set(struct ppe_device *ppe_dev, -+ int node_id, int port, -+ struct ppe_scheduler_cfg scheduler_cfg) -+{ -+ u32 val, reg; -+ int ret; -+ -+ val = FIELD_PREP(PPE_L1_FLOW_MAP_TBL_FLOW_ID, scheduler_cfg.flow_id); -+ val |= FIELD_PREP(PPE_L1_FLOW_MAP_TBL_C_PRI, scheduler_cfg.pri); -+ val |= FIELD_PREP(PPE_L1_FLOW_MAP_TBL_E_PRI, scheduler_cfg.pri); -+ val |= FIELD_PREP(PPE_L1_FLOW_MAP_TBL_C_NODE_WT, scheduler_cfg.drr_node_wt); -+ val |= FIELD_PREP(PPE_L1_FLOW_MAP_TBL_E_NODE_WT, scheduler_cfg.drr_node_wt); -+ reg = PPE_L1_FLOW_MAP_TBL_ADDR + node_id * PPE_L1_FLOW_MAP_TBL_INC; -+ -+ ret = regmap_write(ppe_dev->regmap, reg, val); -+ if (ret) -+ return ret; -+ -+ val = FIELD_PREP(PPE_L1_C_FLOW_CFG_TBL_NODE_ID, scheduler_cfg.drr_node_id); -+ val |= FIELD_PREP(PPE_L1_C_FLOW_CFG_TBL_NODE_CREDIT_UNIT, scheduler_cfg.unit_is_packet); -+ reg = PPE_L1_C_FLOW_CFG_TBL_ADDR + -+ (scheduler_cfg.flow_id * PPE_QUEUE_SCH_PRI_NUM + scheduler_cfg.pri) * -+ PPE_L1_C_FLOW_CFG_TBL_INC; -+ -+ ret = regmap_write(ppe_dev->regmap, reg, val); -+ if (ret) -+ return ret; -+ -+ val = FIELD_PREP(PPE_L1_E_FLOW_CFG_TBL_NODE_ID, scheduler_cfg.drr_node_id); -+ val |= FIELD_PREP(PPE_L1_E_FLOW_CFG_TBL_NODE_CREDIT_UNIT, scheduler_cfg.unit_is_packet); -+ reg = PPE_L1_E_FLOW_CFG_TBL_ADDR + -+ (scheduler_cfg.flow_id * PPE_QUEUE_SCH_PRI_NUM + scheduler_cfg.pri) * -+ PPE_L1_E_FLOW_CFG_TBL_INC; -+ -+ ret = regmap_write(ppe_dev->regmap, reg, val); -+ if (ret) -+ return ret; -+ -+ val = FIELD_PREP(PPE_L1_FLOW_PORT_MAP_TBL_PORT_NUM, port); -+ reg = PPE_L1_FLOW_PORT_MAP_TBL_ADDR + node_id * PPE_L1_FLOW_PORT_MAP_TBL_INC; -+ -+ ret = regmap_write(ppe_dev->regmap, reg, val); -+ if (ret) -+ return ret; -+ -+ reg = PPE_L1_COMP_CFG_TBL_ADDR + node_id * PPE_L1_COMP_CFG_TBL_INC; -+ val = FIELD_PREP(PPE_L1_COMP_CFG_TBL_NODE_METER_LEN, scheduler_cfg.frame_mode); -+ -+ return regmap_update_bits(ppe_dev->regmap, reg, PPE_L1_COMP_CFG_TBL_NODE_METER_LEN, val); -+} -+ -+/** -+ * ppe_queue_scheduler_set - Configure scheduler for PPE hardware queue -+ * @ppe_dev: PPE device -+ * @node_id: PPE queue ID or flow ID -+ * @flow_level: Flow level scheduler or queue level scheduler -+ * @port: PPE port ID set scheduler configuration -+ * @scheduler_cfg: PPE scheduler configuration -+ * -+ * PPE scheduler configuration supports queue level and flow level on -+ * the PPE egress port. -+ * -+ * Return: 0 on success, negative error code on failure. -+ */ -+int ppe_queue_scheduler_set(struct ppe_device *ppe_dev, -+ int node_id, bool flow_level, int port, -+ struct ppe_scheduler_cfg scheduler_cfg) -+{ -+ if (flow_level) -+ return ppe_scheduler_l1_queue_map_set(ppe_dev, node_id, -+ port, scheduler_cfg); -+ -+ return ppe_scheduler_l0_queue_map_set(ppe_dev, node_id, -+ port, scheduler_cfg); -+} -+ - static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id, - const struct ppe_bm_port_config port_cfg) - { -@@ -358,6 +1013,133 @@ qm_config_fail: - return ret; - } - -+static int ppe_node_scheduler_config(struct ppe_device *ppe_dev, -+ const struct ppe_scheduler_port_config config) -+{ -+ struct ppe_scheduler_cfg sch_cfg; -+ int ret, i; -+ -+ for (i = 0; i < config.loop_num; i++) { -+ if (!config.pri_max) { -+ /* Round robin scheduler without priority. */ -+ sch_cfg.flow_id = config.flow_id; -+ sch_cfg.pri = 0; -+ sch_cfg.drr_node_id = config.drr_node_id; -+ } else { -+ sch_cfg.flow_id = config.flow_id + (i / config.pri_max); -+ sch_cfg.pri = i % config.pri_max; -+ sch_cfg.drr_node_id = config.drr_node_id + i; -+ } -+ -+ /* Scheduler weight, must be more than 0. */ -+ sch_cfg.drr_node_wt = 1; -+ /* Byte based to be scheduled. */ -+ sch_cfg.unit_is_packet = false; -+ /* Frame + CRC calculated. */ -+ sch_cfg.frame_mode = PPE_SCH_WITH_FRAME_CRC; -+ -+ ret = ppe_queue_scheduler_set(ppe_dev, config.node_id + i, -+ config.flow_level, -+ config.port, -+ sch_cfg); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+/* Initialize scheduler settings for PPE buffer utilization and dispatching -+ * packet on PPE queue. -+ */ -+static int ppe_config_scheduler(struct ppe_device *ppe_dev) -+{ -+ const struct ppe_scheduler_port_config *port_cfg; -+ const struct ppe_scheduler_qm_config *qm_cfg; -+ const struct ppe_scheduler_bm_config *bm_cfg; -+ int ret, i, count; -+ u32 val, reg; -+ -+ count = ARRAY_SIZE(ipq9574_ppe_sch_bm_config); -+ bm_cfg = ipq9574_ppe_sch_bm_config; -+ -+ /* Configure the depth of BM scheduler entries. */ -+ val = FIELD_PREP(PPE_BM_SCH_CTRL_SCH_DEPTH, count); -+ val |= FIELD_PREP(PPE_BM_SCH_CTRL_SCH_OFFSET, 0); -+ val |= FIELD_PREP(PPE_BM_SCH_CTRL_SCH_EN, 1); -+ -+ ret = regmap_write(ppe_dev->regmap, PPE_BM_SCH_CTRL_ADDR, val); -+ if (ret) -+ goto sch_config_fail; -+ -+ /* Configure each BM scheduler entry with the valid ingress port and -+ * egress port, the second port takes effect when the specified port -+ * is in the inactive state. -+ */ -+ for (i = 0; i < count; i++) { -+ val = FIELD_PREP(PPE_BM_SCH_CFG_TBL_VALID, bm_cfg[i].valid); -+ val |= FIELD_PREP(PPE_BM_SCH_CFG_TBL_DIR, bm_cfg[i].is_egress); -+ val |= FIELD_PREP(PPE_BM_SCH_CFG_TBL_PORT_NUM, bm_cfg[i].port); -+ val |= FIELD_PREP(PPE_BM_SCH_CFG_TBL_SECOND_PORT_VALID, bm_cfg[i].second_valid); -+ val |= FIELD_PREP(PPE_BM_SCH_CFG_TBL_SECOND_PORT, bm_cfg[i].second_port); -+ -+ reg = PPE_BM_SCH_CFG_TBL_ADDR + i * PPE_BM_SCH_CFG_TBL_INC; -+ ret = regmap_write(ppe_dev->regmap, reg, val); -+ if (ret) -+ goto sch_config_fail; -+ } -+ -+ count = ARRAY_SIZE(ipq9574_ppe_sch_qm_config); -+ qm_cfg = ipq9574_ppe_sch_qm_config; -+ -+ /* Configure the depth of QM scheduler entries. */ -+ val = FIELD_PREP(PPE_PSCH_SCH_DEPTH_CFG_SCH_DEPTH, count); -+ ret = regmap_write(ppe_dev->regmap, PPE_PSCH_SCH_DEPTH_CFG_ADDR, val); -+ if (ret) -+ goto sch_config_fail; -+ -+ /* Configure each QM scheduler entry with enqueue port and dequeue -+ * port, the second port takes effect when the specified dequeue -+ * port is in the inactive port. -+ */ -+ for (i = 0; i < count; i++) { -+ val = FIELD_PREP(PPE_PSCH_SCH_CFG_TBL_ENS_PORT_BITMAP, -+ qm_cfg[i].ensch_port_bmp); -+ val |= FIELD_PREP(PPE_PSCH_SCH_CFG_TBL_ENS_PORT, -+ qm_cfg[i].ensch_port); -+ val |= FIELD_PREP(PPE_PSCH_SCH_CFG_TBL_DES_PORT, -+ qm_cfg[i].desch_port); -+ val |= FIELD_PREP(PPE_PSCH_SCH_CFG_TBL_DES_SECOND_PORT_EN, -+ qm_cfg[i].desch_second_valid); -+ val |= FIELD_PREP(PPE_PSCH_SCH_CFG_TBL_DES_SECOND_PORT, -+ qm_cfg[i].desch_second_port); -+ -+ reg = PPE_PSCH_SCH_CFG_TBL_ADDR + i * PPE_PSCH_SCH_CFG_TBL_INC; -+ ret = regmap_write(ppe_dev->regmap, reg, val); -+ if (ret) -+ goto sch_config_fail; -+ } -+ -+ count = ARRAY_SIZE(ppe_port_sch_config); -+ port_cfg = ppe_port_sch_config; -+ -+ /* Configure scheduler per PPE queue or flow. */ -+ for (i = 0; i < count; i++) { -+ if (port_cfg[i].port >= ppe_dev->num_ports) -+ break; -+ -+ ret = ppe_node_scheduler_config(ppe_dev, port_cfg[i]); -+ if (ret) -+ goto sch_config_fail; -+ } -+ -+ return 0; -+ -+sch_config_fail: -+ dev_err(ppe_dev->dev, "PPE scheduler arbitration config error %d\n", ret); -+ return ret; -+}; -+ - int ppe_hw_config(struct ppe_device *ppe_dev) - { - int ret; -@@ -366,5 +1148,9 @@ int ppe_hw_config(struct ppe_device *ppe - if (ret) - return ret; - -- return ppe_config_qm(ppe_dev); -+ ret = ppe_config_qm(ppe_dev); -+ if (ret) -+ return ret; -+ -+ return ppe_config_scheduler(ppe_dev); - } ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h -@@ -8,5 +8,42 @@ - - #include "ppe.h" - -+/** -+ * enum ppe_scheduler_frame_mode - PPE scheduler frame mode. -+ * @PPE_SCH_WITH_IPG_PREAMBLE_FRAME_CRC: The scheduled frame includes IPG, -+ * preamble, Ethernet packet and CRC. -+ * @PPE_SCH_WITH_FRAME_CRC: The scheduled frame includes Ethernet frame and CRC -+ * excluding IPG and preamble. -+ * @PPE_SCH_WITH_L3_PAYLOAD: The scheduled frame includes layer 3 packet data. -+ */ -+enum ppe_scheduler_frame_mode { -+ PPE_SCH_WITH_IPG_PREAMBLE_FRAME_CRC = 0, -+ PPE_SCH_WITH_FRAME_CRC = 1, -+ PPE_SCH_WITH_L3_PAYLOAD = 2, -+}; -+ -+/** -+ * struct ppe_scheduler_cfg - PPE scheduler configuration. -+ * @flow_id: PPE flow ID. -+ * @pri: Scheduler priority. -+ * @drr_node_id: Node ID for scheduled traffic. -+ * @drr_node_wt: Weight for scheduled traffic. -+ * @unit_is_packet: Packet based or byte based unit for scheduled traffic. -+ * @frame_mode: Packet mode to be scheduled. -+ * -+ * PPE scheduler supports commit rate and exceed rate configurations. -+ */ -+struct ppe_scheduler_cfg { -+ int flow_id; -+ int pri; -+ int drr_node_id; -+ int drr_node_wt; -+ bool unit_is_packet; -+ enum ppe_scheduler_frame_mode frame_mode; -+}; -+ - int ppe_hw_config(struct ppe_device *ppe_dev); -+int ppe_queue_scheduler_set(struct ppe_device *ppe_dev, -+ int node_id, bool flow_level, int port, -+ struct ppe_scheduler_cfg scheduler_cfg); - #endif ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -@@ -9,16 +9,113 @@ - - #include - -+/* PPE scheduler configurations for buffer manager block. */ -+#define PPE_BM_SCH_CTRL_ADDR 0xb000 -+#define PPE_BM_SCH_CTRL_INC 4 -+#define PPE_BM_SCH_CTRL_SCH_DEPTH GENMASK(7, 0) -+#define PPE_BM_SCH_CTRL_SCH_OFFSET GENMASK(14, 8) -+#define PPE_BM_SCH_CTRL_SCH_EN BIT(31) -+ -+#define PPE_BM_SCH_CFG_TBL_ADDR 0xc000 -+#define PPE_BM_SCH_CFG_TBL_ENTRIES 128 -+#define PPE_BM_SCH_CFG_TBL_INC 0x10 -+#define PPE_BM_SCH_CFG_TBL_PORT_NUM GENMASK(3, 0) -+#define PPE_BM_SCH_CFG_TBL_DIR BIT(4) -+#define PPE_BM_SCH_CFG_TBL_VALID BIT(5) -+#define PPE_BM_SCH_CFG_TBL_SECOND_PORT_VALID BIT(6) -+#define PPE_BM_SCH_CFG_TBL_SECOND_PORT GENMASK(11, 8) -+ - /* PPE queue counters enable/disable control. */ - #define PPE_EG_BRIDGE_CONFIG_ADDR 0x20044 - #define PPE_EG_BRIDGE_CONFIG_QUEUE_CNT_EN BIT(2) - -+/* Port scheduler global config. */ -+#define PPE_PSCH_SCH_DEPTH_CFG_ADDR 0x400000 -+#define PPE_PSCH_SCH_DEPTH_CFG_INC 4 -+#define PPE_PSCH_SCH_DEPTH_CFG_SCH_DEPTH GENMASK(7, 0) -+ -+/* PPE queue level scheduler configurations. */ -+#define PPE_L0_FLOW_MAP_TBL_ADDR 0x402000 -+#define PPE_L0_FLOW_MAP_TBL_ENTRIES 300 -+#define PPE_L0_FLOW_MAP_TBL_INC 0x10 -+#define PPE_L0_FLOW_MAP_TBL_FLOW_ID GENMASK(5, 0) -+#define PPE_L0_FLOW_MAP_TBL_C_PRI GENMASK(8, 6) -+#define PPE_L0_FLOW_MAP_TBL_E_PRI GENMASK(11, 9) -+#define PPE_L0_FLOW_MAP_TBL_C_NODE_WT GENMASK(21, 12) -+#define PPE_L0_FLOW_MAP_TBL_E_NODE_WT GENMASK(31, 22) -+ -+#define PPE_L0_C_FLOW_CFG_TBL_ADDR 0x404000 -+#define PPE_L0_C_FLOW_CFG_TBL_ENTRIES 512 -+#define PPE_L0_C_FLOW_CFG_TBL_INC 0x10 -+#define PPE_L0_C_FLOW_CFG_TBL_NODE_ID GENMASK(7, 0) -+#define PPE_L0_C_FLOW_CFG_TBL_NODE_CREDIT_UNIT BIT(8) -+ -+#define PPE_L0_E_FLOW_CFG_TBL_ADDR 0x406000 -+#define PPE_L0_E_FLOW_CFG_TBL_ENTRIES 512 -+#define PPE_L0_E_FLOW_CFG_TBL_INC 0x10 -+#define PPE_L0_E_FLOW_CFG_TBL_NODE_ID GENMASK(7, 0) -+#define PPE_L0_E_FLOW_CFG_TBL_NODE_CREDIT_UNIT BIT(8) -+ -+#define PPE_L0_FLOW_PORT_MAP_TBL_ADDR 0x408000 -+#define PPE_L0_FLOW_PORT_MAP_TBL_ENTRIES 300 -+#define PPE_L0_FLOW_PORT_MAP_TBL_INC 0x10 -+#define PPE_L0_FLOW_PORT_MAP_TBL_PORT_NUM GENMASK(3, 0) -+ -+#define PPE_L0_COMP_CFG_TBL_ADDR 0x428000 -+#define PPE_L0_COMP_CFG_TBL_ENTRIES 300 -+#define PPE_L0_COMP_CFG_TBL_INC 0x10 -+#define PPE_L0_COMP_CFG_TBL_SHAPER_METER_LEN GENMASK(1, 0) -+#define PPE_L0_COMP_CFG_TBL_NODE_METER_LEN GENMASK(3, 2) -+ - /* Table addresses for per-queue dequeue setting. */ - #define PPE_DEQ_OPR_TBL_ADDR 0x430000 - #define PPE_DEQ_OPR_TBL_ENTRIES 300 - #define PPE_DEQ_OPR_TBL_INC 0x10 - #define PPE_DEQ_OPR_TBL_DEQ_DISABLE BIT(0) - -+/* PPE flow level scheduler configurations. */ -+#define PPE_L1_FLOW_MAP_TBL_ADDR 0x440000 -+#define PPE_L1_FLOW_MAP_TBL_ENTRIES 64 -+#define PPE_L1_FLOW_MAP_TBL_INC 0x10 -+#define PPE_L1_FLOW_MAP_TBL_FLOW_ID GENMASK(3, 0) -+#define PPE_L1_FLOW_MAP_TBL_C_PRI GENMASK(6, 4) -+#define PPE_L1_FLOW_MAP_TBL_E_PRI GENMASK(9, 7) -+#define PPE_L1_FLOW_MAP_TBL_C_NODE_WT GENMASK(19, 10) -+#define PPE_L1_FLOW_MAP_TBL_E_NODE_WT GENMASK(29, 20) -+ -+#define PPE_L1_C_FLOW_CFG_TBL_ADDR 0x442000 -+#define PPE_L1_C_FLOW_CFG_TBL_ENTRIES 64 -+#define PPE_L1_C_FLOW_CFG_TBL_INC 0x10 -+#define PPE_L1_C_FLOW_CFG_TBL_NODE_ID GENMASK(5, 0) -+#define PPE_L1_C_FLOW_CFG_TBL_NODE_CREDIT_UNIT BIT(6) -+ -+#define PPE_L1_E_FLOW_CFG_TBL_ADDR 0x444000 -+#define PPE_L1_E_FLOW_CFG_TBL_ENTRIES 64 -+#define PPE_L1_E_FLOW_CFG_TBL_INC 0x10 -+#define PPE_L1_E_FLOW_CFG_TBL_NODE_ID GENMASK(5, 0) -+#define PPE_L1_E_FLOW_CFG_TBL_NODE_CREDIT_UNIT BIT(6) -+ -+#define PPE_L1_FLOW_PORT_MAP_TBL_ADDR 0x446000 -+#define PPE_L1_FLOW_PORT_MAP_TBL_ENTRIES 64 -+#define PPE_L1_FLOW_PORT_MAP_TBL_INC 0x10 -+#define PPE_L1_FLOW_PORT_MAP_TBL_PORT_NUM GENMASK(3, 0) -+ -+#define PPE_L1_COMP_CFG_TBL_ADDR 0x46a000 -+#define PPE_L1_COMP_CFG_TBL_ENTRIES 64 -+#define PPE_L1_COMP_CFG_TBL_INC 0x10 -+#define PPE_L1_COMP_CFG_TBL_SHAPER_METER_LEN GENMASK(1, 0) -+#define PPE_L1_COMP_CFG_TBL_NODE_METER_LEN GENMASK(3, 2) -+ -+/* PPE port scheduler configurations for egress. */ -+#define PPE_PSCH_SCH_CFG_TBL_ADDR 0x47a000 -+#define PPE_PSCH_SCH_CFG_TBL_ENTRIES 128 -+#define PPE_PSCH_SCH_CFG_TBL_INC 0x10 -+#define PPE_PSCH_SCH_CFG_TBL_DES_PORT GENMASK(3, 0) -+#define PPE_PSCH_SCH_CFG_TBL_ENS_PORT GENMASK(7, 4) -+#define PPE_PSCH_SCH_CFG_TBL_ENS_PORT_BITMAP GENMASK(15, 8) -+#define PPE_PSCH_SCH_CFG_TBL_DES_SECOND_PORT_EN BIT(16) -+#define PPE_PSCH_SCH_CFG_TBL_DES_SECOND_PORT GENMASK(20, 17) -+ - /* There are 15 BM ports and 4 BM groups supported by PPE. - * BM port (0-7) is for EDMA port 0, BM port (8-13) is for - * PPE physical port 1-6 and BM port 14 is for EIP port. diff --git a/target/linux/qualcommbe/patches-6.12/0329-net-ethernet-qualcomm-Initialize-PPE-queue-settings.patch b/target/linux/qualcommbe/patches-6.12/0329-net-ethernet-qualcomm-Initialize-PPE-queue-settings.patch deleted file mode 100644 index fe29d76e36..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0329-net-ethernet-qualcomm-Initialize-PPE-queue-settings.patch +++ /dev/null @@ -1,522 +0,0 @@ -From 63874f7c2e46f192e43e6214d66236372e36396c Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 9 Feb 2025 22:29:41 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Initialize PPE queue settings - -Configure unicast and multicast hardware queues for the PPE -ports to enable packet forwarding between the ports. - -Each PPE port is assigned with a range of queues. The queue ID -selection for a packet is decided by the queue base and queue -offset that is configured based on the internal priority and -the RSS hash value of the packet. - -Signed-off-by: Luo Jie ---- - .../net/ethernet/qualcomm/ppe/ppe_config.c | 356 +++++++++++++++++- - .../net/ethernet/qualcomm/ppe/ppe_config.h | 63 ++++ - drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 21 ++ - 3 files changed, 439 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -@@ -128,6 +128,34 @@ struct ppe_scheduler_port_config { - unsigned int drr_node_id; - }; - -+/** -+ * struct ppe_port_schedule_resource - PPE port scheduler resource. -+ * @ucastq_start: Unicast queue start ID. -+ * @ucastq_end: Unicast queue end ID. -+ * @mcastq_start: Multicast queue start ID. -+ * @mcastq_end: Multicast queue end ID. -+ * @flow_id_start: Flow start ID. -+ * @flow_id_end: Flow end ID. -+ * @l0node_start: Scheduler node start ID for queue level. -+ * @l0node_end: Scheduler node end ID for queue level. -+ * @l1node_start: Scheduler node start ID for flow level. -+ * @l1node_end: Scheduler node end ID for flow level. -+ * -+ * PPE scheduler resource allocated among the PPE ports. -+ */ -+struct ppe_port_schedule_resource { -+ unsigned int ucastq_start; -+ unsigned int ucastq_end; -+ unsigned int mcastq_start; -+ unsigned int mcastq_end; -+ unsigned int flow_id_start; -+ unsigned int flow_id_end; -+ unsigned int l0node_start; -+ unsigned int l0node_end; -+ unsigned int l1node_start; -+ unsigned int l1node_end; -+}; -+ - /* Assign the share buffer number 1550 to group 0 by default. */ - static const int ipq9574_ppe_bm_group_config = 1550; - -@@ -676,6 +704,111 @@ static const struct ppe_scheduler_port_c - }, - }; - -+/* The scheduler resource is applied to each PPE port, The resource -+ * includes the unicast & multicast queues, flow nodes and DRR nodes. -+ */ -+static const struct ppe_port_schedule_resource ppe_scheduler_res[] = { -+ { .ucastq_start = 0, -+ .ucastq_end = 63, -+ .mcastq_start = 256, -+ .mcastq_end = 271, -+ .flow_id_start = 0, -+ .flow_id_end = 0, -+ .l0node_start = 0, -+ .l0node_end = 7, -+ .l1node_start = 0, -+ .l1node_end = 0, -+ }, -+ { .ucastq_start = 144, -+ .ucastq_end = 159, -+ .mcastq_start = 272, -+ .mcastq_end = 275, -+ .flow_id_start = 36, -+ .flow_id_end = 39, -+ .l0node_start = 48, -+ .l0node_end = 63, -+ .l1node_start = 8, -+ .l1node_end = 11, -+ }, -+ { .ucastq_start = 160, -+ .ucastq_end = 175, -+ .mcastq_start = 276, -+ .mcastq_end = 279, -+ .flow_id_start = 40, -+ .flow_id_end = 43, -+ .l0node_start = 64, -+ .l0node_end = 79, -+ .l1node_start = 12, -+ .l1node_end = 15, -+ }, -+ { .ucastq_start = 176, -+ .ucastq_end = 191, -+ .mcastq_start = 280, -+ .mcastq_end = 283, -+ .flow_id_start = 44, -+ .flow_id_end = 47, -+ .l0node_start = 80, -+ .l0node_end = 95, -+ .l1node_start = 16, -+ .l1node_end = 19, -+ }, -+ { .ucastq_start = 192, -+ .ucastq_end = 207, -+ .mcastq_start = 284, -+ .mcastq_end = 287, -+ .flow_id_start = 48, -+ .flow_id_end = 51, -+ .l0node_start = 96, -+ .l0node_end = 111, -+ .l1node_start = 20, -+ .l1node_end = 23, -+ }, -+ { .ucastq_start = 208, -+ .ucastq_end = 223, -+ .mcastq_start = 288, -+ .mcastq_end = 291, -+ .flow_id_start = 52, -+ .flow_id_end = 55, -+ .l0node_start = 112, -+ .l0node_end = 127, -+ .l1node_start = 24, -+ .l1node_end = 27, -+ }, -+ { .ucastq_start = 224, -+ .ucastq_end = 239, -+ .mcastq_start = 292, -+ .mcastq_end = 295, -+ .flow_id_start = 56, -+ .flow_id_end = 59, -+ .l0node_start = 128, -+ .l0node_end = 143, -+ .l1node_start = 28, -+ .l1node_end = 31, -+ }, -+ { .ucastq_start = 240, -+ .ucastq_end = 255, -+ .mcastq_start = 296, -+ .mcastq_end = 299, -+ .flow_id_start = 60, -+ .flow_id_end = 63, -+ .l0node_start = 144, -+ .l0node_end = 159, -+ .l1node_start = 32, -+ .l1node_end = 35, -+ }, -+ { .ucastq_start = 64, -+ .ucastq_end = 143, -+ .mcastq_start = 0, -+ .mcastq_end = 0, -+ .flow_id_start = 1, -+ .flow_id_end = 35, -+ .l0node_start = 8, -+ .l0node_end = 47, -+ .l1node_start = 1, -+ .l1node_end = 7, -+ }, -+}; -+ - /* Set the PPE queue level scheduler configuration. */ - static int ppe_scheduler_l0_queue_map_set(struct ppe_device *ppe_dev, - int node_id, int port, -@@ -807,6 +940,149 @@ int ppe_queue_scheduler_set(struct ppe_d - port, scheduler_cfg); - } - -+/** -+ * ppe_queue_ucast_base_set - Set PPE unicast queue base ID and profile ID -+ * @ppe_dev: PPE device -+ * @queue_dst: PPE queue destination configuration -+ * @queue_base: PPE queue base ID -+ * @profile_id: Profile ID -+ * -+ * The PPE unicast queue base ID and profile ID are configured based on the -+ * destination port information that can be service code or CPU code or the -+ * destination port. -+ * -+ * Return: 0 on success, negative error code on failure. -+ */ -+int ppe_queue_ucast_base_set(struct ppe_device *ppe_dev, -+ struct ppe_queue_ucast_dest queue_dst, -+ int queue_base, int profile_id) -+{ -+ int index, profile_size; -+ u32 val, reg; -+ -+ profile_size = queue_dst.src_profile << 8; -+ if (queue_dst.service_code_en) -+ index = PPE_QUEUE_BASE_SERVICE_CODE + profile_size + -+ queue_dst.service_code; -+ else if (queue_dst.cpu_code_en) -+ index = PPE_QUEUE_BASE_CPU_CODE + profile_size + -+ queue_dst.cpu_code; -+ else -+ index = profile_size + queue_dst.dest_port; -+ -+ val = FIELD_PREP(PPE_UCAST_QUEUE_MAP_TBL_PROFILE_ID, profile_id); -+ val |= FIELD_PREP(PPE_UCAST_QUEUE_MAP_TBL_QUEUE_ID, queue_base); -+ reg = PPE_UCAST_QUEUE_MAP_TBL_ADDR + index * PPE_UCAST_QUEUE_MAP_TBL_INC; -+ -+ return regmap_write(ppe_dev->regmap, reg, val); -+} -+ -+/** -+ * ppe_queue_ucast_offset_pri_set - Set PPE unicast queue offset based on priority -+ * @ppe_dev: PPE device -+ * @profile_id: Profile ID -+ * @priority: PPE internal priority to be used to set queue offset -+ * @queue_offset: Queue offset used for calculating the destination queue ID -+ * -+ * The PPE unicast queue offset is configured based on the PPE -+ * internal priority. -+ * -+ * Return: 0 on success, negative error code on failure. -+ */ -+int ppe_queue_ucast_offset_pri_set(struct ppe_device *ppe_dev, -+ int profile_id, -+ int priority, -+ int queue_offset) -+{ -+ u32 val, reg; -+ int index; -+ -+ index = (profile_id << 4) + priority; -+ val = FIELD_PREP(PPE_UCAST_PRIORITY_MAP_TBL_CLASS, queue_offset); -+ reg = PPE_UCAST_PRIORITY_MAP_TBL_ADDR + index * PPE_UCAST_PRIORITY_MAP_TBL_INC; -+ -+ return regmap_write(ppe_dev->regmap, reg, val); -+} -+ -+/** -+ * ppe_queue_ucast_offset_hash_set - Set PPE unicast queue offset based on hash -+ * @ppe_dev: PPE device -+ * @profile_id: Profile ID -+ * @rss_hash: Packet hash value to be used to set queue offset -+ * @queue_offset: Queue offset used for calculating the destination queue ID -+ * -+ * The PPE unicast queue offset is configured based on the RSS hash value. -+ * -+ * Return: 0 on success, negative error code on failure. -+ */ -+int ppe_queue_ucast_offset_hash_set(struct ppe_device *ppe_dev, -+ int profile_id, -+ int rss_hash, -+ int queue_offset) -+{ -+ u32 val, reg; -+ int index; -+ -+ index = (profile_id << 8) + rss_hash; -+ val = FIELD_PREP(PPE_UCAST_HASH_MAP_TBL_HASH, queue_offset); -+ reg = PPE_UCAST_HASH_MAP_TBL_ADDR + index * PPE_UCAST_HASH_MAP_TBL_INC; -+ -+ return regmap_write(ppe_dev->regmap, reg, val); -+} -+ -+/** -+ * ppe_port_resource_get - Get PPE resource per port -+ * @ppe_dev: PPE device -+ * @port: PPE port -+ * @type: Resource type -+ * @res_start: Resource start ID returned -+ * @res_end: Resource end ID returned -+ * -+ * PPE resource is assigned per PPE port, which is acquired for QoS scheduler. -+ * -+ * Return: 0 on success, negative error code on failure. -+ */ -+int ppe_port_resource_get(struct ppe_device *ppe_dev, int port, -+ enum ppe_resource_type type, -+ int *res_start, int *res_end) -+{ -+ struct ppe_port_schedule_resource res; -+ -+ /* The reserved resource with the maximum port ID of PPE is -+ * also allowed to be acquired. -+ */ -+ if (port > ppe_dev->num_ports) -+ return -EINVAL; -+ -+ res = ppe_scheduler_res[port]; -+ switch (type) { -+ case PPE_RES_UCAST: -+ *res_start = res.ucastq_start; -+ *res_end = res.ucastq_end; -+ break; -+ case PPE_RES_MCAST: -+ *res_start = res.mcastq_start; -+ *res_end = res.mcastq_end; -+ break; -+ case PPE_RES_FLOW_ID: -+ *res_start = res.flow_id_start; -+ *res_end = res.flow_id_end; -+ break; -+ case PPE_RES_L0_NODE: -+ *res_start = res.l0node_start; -+ *res_end = res.l0node_end; -+ break; -+ case PPE_RES_L1_NODE: -+ *res_start = res.l1node_start; -+ *res_end = res.l1node_end; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ - static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id, - const struct ppe_bm_port_config port_cfg) - { -@@ -1140,6 +1416,80 @@ sch_config_fail: - return ret; - }; - -+/* Configure PPE queue destination of each PPE port. */ -+static int ppe_queue_dest_init(struct ppe_device *ppe_dev) -+{ -+ int ret, port_id, index, q_base, q_offset, res_start, res_end, pri_max; -+ struct ppe_queue_ucast_dest queue_dst; -+ -+ for (port_id = 0; port_id < ppe_dev->num_ports; port_id++) { -+ memset(&queue_dst, 0, sizeof(queue_dst)); -+ -+ ret = ppe_port_resource_get(ppe_dev, port_id, PPE_RES_UCAST, -+ &res_start, &res_end); -+ if (ret) -+ return ret; -+ -+ q_base = res_start; -+ queue_dst.dest_port = port_id; -+ -+ /* Configure queue base ID and profile ID that is same as -+ * physical port ID. -+ */ -+ ret = ppe_queue_ucast_base_set(ppe_dev, queue_dst, -+ q_base, port_id); -+ if (ret) -+ return ret; -+ -+ /* Queue priority range supported by each PPE port */ -+ ret = ppe_port_resource_get(ppe_dev, port_id, PPE_RES_L0_NODE, -+ &res_start, &res_end); -+ if (ret) -+ return ret; -+ -+ pri_max = res_end - res_start; -+ -+ /* Redirect ARP reply packet with the max priority on CPU port, -+ * which keeps the ARP reply directed to CPU (CPU code is 101) -+ * with highest priority queue of EDMA. -+ */ -+ if (port_id == 0) { -+ memset(&queue_dst, 0, sizeof(queue_dst)); -+ -+ queue_dst.cpu_code_en = true; -+ queue_dst.cpu_code = 101; -+ ret = ppe_queue_ucast_base_set(ppe_dev, queue_dst, -+ q_base + pri_max, -+ 0); -+ if (ret) -+ return ret; -+ } -+ -+ /* Initialize the queue offset of internal priority. */ -+ for (index = 0; index < PPE_QUEUE_INTER_PRI_NUM; index++) { -+ q_offset = index > pri_max ? pri_max : index; -+ -+ ret = ppe_queue_ucast_offset_pri_set(ppe_dev, port_id, -+ index, q_offset); -+ if (ret) -+ return ret; -+ } -+ -+ /* Initialize the queue offset of RSS hash as 0 to avoid the -+ * random hardware value that will lead to the unexpected -+ * destination queue generated. -+ */ -+ for (index = 0; index < PPE_QUEUE_HASH_NUM; index++) { -+ ret = ppe_queue_ucast_offset_hash_set(ppe_dev, port_id, -+ index, 0); -+ if (ret) -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ - int ppe_hw_config(struct ppe_device *ppe_dev) - { - int ret; -@@ -1152,5 +1502,9 @@ int ppe_hw_config(struct ppe_device *ppe - if (ret) - return ret; - -- return ppe_config_scheduler(ppe_dev); -+ ret = ppe_config_scheduler(ppe_dev); -+ if (ret) -+ return ret; -+ -+ return ppe_queue_dest_init(ppe_dev); - } ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h -@@ -8,6 +8,16 @@ - - #include "ppe.h" - -+/* There are different table index ranges for configuring queue base ID of -+ * the destination port, CPU code and service code. -+ */ -+#define PPE_QUEUE_BASE_DEST_PORT 0 -+#define PPE_QUEUE_BASE_CPU_CODE 1024 -+#define PPE_QUEUE_BASE_SERVICE_CODE 2048 -+ -+#define PPE_QUEUE_INTER_PRI_NUM 16 -+#define PPE_QUEUE_HASH_NUM 256 -+ - /** - * enum ppe_scheduler_frame_mode - PPE scheduler frame mode. - * @PPE_SCH_WITH_IPG_PREAMBLE_FRAME_CRC: The scheduled frame includes IPG, -@@ -42,8 +52,61 @@ struct ppe_scheduler_cfg { - enum ppe_scheduler_frame_mode frame_mode; - }; - -+/** -+ * enum ppe_resource_type - PPE resource type. -+ * @PPE_RES_UCAST: Unicast queue resource. -+ * @PPE_RES_MCAST: Multicast queue resource. -+ * @PPE_RES_L0_NODE: Level 0 for queue based node resource. -+ * @PPE_RES_L1_NODE: Level 1 for flow based node resource. -+ * @PPE_RES_FLOW_ID: Flow based node resource. -+ */ -+enum ppe_resource_type { -+ PPE_RES_UCAST, -+ PPE_RES_MCAST, -+ PPE_RES_L0_NODE, -+ PPE_RES_L1_NODE, -+ PPE_RES_FLOW_ID, -+}; -+ -+/** -+ * struct ppe_queue_ucast_dest - PPE unicast queue destination. -+ * @src_profile: Source profile. -+ * @service_code_en: Enable service code to map the queue base ID. -+ * @service_code: Service code. -+ * @cpu_code_en: Enable CPU code to map the queue base ID. -+ * @cpu_code: CPU code. -+ * @dest_port: destination port. -+ * -+ * PPE egress queue ID is decided by the service code if enabled, otherwise -+ * by the CPU code if enabled, or by destination port if both service code -+ * and CPU code are disabled. -+ */ -+struct ppe_queue_ucast_dest { -+ int src_profile; -+ bool service_code_en; -+ int service_code; -+ bool cpu_code_en; -+ int cpu_code; -+ int dest_port; -+}; -+ - int ppe_hw_config(struct ppe_device *ppe_dev); - int ppe_queue_scheduler_set(struct ppe_device *ppe_dev, - int node_id, bool flow_level, int port, - struct ppe_scheduler_cfg scheduler_cfg); -+int ppe_queue_ucast_base_set(struct ppe_device *ppe_dev, -+ struct ppe_queue_ucast_dest queue_dst, -+ int queue_base, -+ int profile_id); -+int ppe_queue_ucast_offset_pri_set(struct ppe_device *ppe_dev, -+ int profile_id, -+ int priority, -+ int queue_offset); -+int ppe_queue_ucast_offset_hash_set(struct ppe_device *ppe_dev, -+ int profile_id, -+ int rss_hash, -+ int queue_offset); -+int ppe_port_resource_get(struct ppe_device *ppe_dev, int port, -+ enum ppe_resource_type type, -+ int *res_start, int *res_end); - #endif ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -@@ -164,6 +164,27 @@ - #define PPE_BM_PORT_FC_SET_PRE_ALLOC(tbl_cfg, value) \ - u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_BM_PORT_FC_W1_PRE_ALLOC) - -+/* The queue base configurations based on destination port, -+ * service code or CPU code. -+ */ -+#define PPE_UCAST_QUEUE_MAP_TBL_ADDR 0x810000 -+#define PPE_UCAST_QUEUE_MAP_TBL_ENTRIES 3072 -+#define PPE_UCAST_QUEUE_MAP_TBL_INC 0x10 -+#define PPE_UCAST_QUEUE_MAP_TBL_PROFILE_ID GENMASK(3, 0) -+#define PPE_UCAST_QUEUE_MAP_TBL_QUEUE_ID GENMASK(11, 4) -+ -+/* The queue offset configurations based on RSS hash value. */ -+#define PPE_UCAST_HASH_MAP_TBL_ADDR 0x830000 -+#define PPE_UCAST_HASH_MAP_TBL_ENTRIES 4096 -+#define PPE_UCAST_HASH_MAP_TBL_INC 0x10 -+#define PPE_UCAST_HASH_MAP_TBL_HASH GENMASK(7, 0) -+ -+/* The queue offset configurations based on PPE internal priority. */ -+#define PPE_UCAST_PRIORITY_MAP_TBL_ADDR 0x842000 -+#define PPE_UCAST_PRIORITY_MAP_TBL_ENTRIES 256 -+#define PPE_UCAST_PRIORITY_MAP_TBL_INC 0x10 -+#define PPE_UCAST_PRIORITY_MAP_TBL_CLASS GENMASK(3, 0) -+ - /* PPE unicast queue (0-255) configurations. */ - #define PPE_AC_UNICAST_QUEUE_CFG_TBL_ADDR 0x848000 - #define PPE_AC_UNICAST_QUEUE_CFG_TBL_ENTRIES 256 diff --git a/target/linux/qualcommbe/patches-6.12/0330-net-ethernet-qualcomm-Initialize-PPE-service-code-se.patch b/target/linux/qualcommbe/patches-6.12/0330-net-ethernet-qualcomm-Initialize-PPE-service-code-se.patch deleted file mode 100644 index 176b7d6bb4..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0330-net-ethernet-qualcomm-Initialize-PPE-service-code-se.patch +++ /dev/null @@ -1,384 +0,0 @@ -From 4147ce0d95816bded5c5e6cb276b1aa9f2620045 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 9 Feb 2025 22:29:42 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Initialize PPE service code settings - -PPE service code is a special code (0-255) that is defined by PPE for -PPE's packet processing stages, as per the network functions required -for the packet. - -For packet being sent out by ARM cores on Ethernet ports, The service -code 1 is used as the default service code. This service code is used -to bypass most of packet processing stages of the PPE before the packet -transmitted out PPE port, since the software network stack has already -processed the packet. - -Signed-off-by: Luo Jie ---- - .../net/ethernet/qualcomm/ppe/ppe_config.c | 95 +++++++++++- - .../net/ethernet/qualcomm/ppe/ppe_config.h | 145 ++++++++++++++++++ - drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 53 +++++++ - 3 files changed, 292 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -@@ -8,6 +8,7 @@ - */ - - #include -+#include - #include - #include - #include -@@ -1083,6 +1084,75 @@ int ppe_port_resource_get(struct ppe_dev - return 0; - } - -+/** -+ * ppe_sc_config_set - Set PPE service code configuration -+ * @ppe_dev: PPE device -+ * @sc: Service ID, 0-255 supported by PPE -+ * @cfg: Service code configuration -+ * -+ * PPE service code is used by the PPE during its packet processing stages, -+ * to perform or bypass certain selected packet operations on the packet. -+ * -+ * Return: 0 on success, negative error code on failure. -+ */ -+int ppe_sc_config_set(struct ppe_device *ppe_dev, int sc, struct ppe_sc_cfg cfg) -+{ -+ u32 val, reg, servcode_val[2] = {}; -+ unsigned long bitmap_value; -+ int ret; -+ -+ val = FIELD_PREP(PPE_IN_L2_SERVICE_TBL_DST_PORT_ID_VALID, cfg.dest_port_valid); -+ val |= FIELD_PREP(PPE_IN_L2_SERVICE_TBL_DST_PORT_ID, cfg.dest_port); -+ val |= FIELD_PREP(PPE_IN_L2_SERVICE_TBL_DST_DIRECTION, cfg.is_src); -+ -+ bitmap_value = bitmap_read(cfg.bitmaps.egress, 0, PPE_SC_BYPASS_EGRESS_SIZE); -+ val |= FIELD_PREP(PPE_IN_L2_SERVICE_TBL_DST_BYPASS_BITMAP, bitmap_value); -+ val |= FIELD_PREP(PPE_IN_L2_SERVICE_TBL_RX_CNT_EN, -+ test_bit(PPE_SC_BYPASS_COUNTER_RX, cfg.bitmaps.counter)); -+ val |= FIELD_PREP(PPE_IN_L2_SERVICE_TBL_TX_CNT_EN, -+ test_bit(PPE_SC_BYPASS_COUNTER_TX, cfg.bitmaps.counter)); -+ reg = PPE_IN_L2_SERVICE_TBL_ADDR + PPE_IN_L2_SERVICE_TBL_INC * sc; -+ -+ ret = regmap_write(ppe_dev->regmap, reg, val); -+ if (ret) -+ return ret; -+ -+ bitmap_value = bitmap_read(cfg.bitmaps.ingress, 0, PPE_SC_BYPASS_INGRESS_SIZE); -+ PPE_SERVICE_SET_BYPASS_BITMAP(servcode_val, bitmap_value); -+ PPE_SERVICE_SET_RX_CNT_EN(servcode_val, -+ test_bit(PPE_SC_BYPASS_COUNTER_RX_VLAN, cfg.bitmaps.counter)); -+ reg = PPE_SERVICE_TBL_ADDR + PPE_SERVICE_TBL_INC * sc; -+ -+ ret = regmap_bulk_write(ppe_dev->regmap, reg, -+ servcode_val, ARRAY_SIZE(servcode_val)); -+ if (ret) -+ return ret; -+ -+ reg = PPE_EG_SERVICE_TBL_ADDR + PPE_EG_SERVICE_TBL_INC * sc; -+ ret = regmap_bulk_read(ppe_dev->regmap, reg, -+ servcode_val, ARRAY_SIZE(servcode_val)); -+ if (ret) -+ return ret; -+ -+ PPE_EG_SERVICE_SET_NEXT_SERVCODE(servcode_val, cfg.next_service_code); -+ PPE_EG_SERVICE_SET_UPDATE_ACTION(servcode_val, cfg.eip_field_update_bitmap); -+ PPE_EG_SERVICE_SET_HW_SERVICE(servcode_val, cfg.eip_hw_service); -+ PPE_EG_SERVICE_SET_OFFSET_SEL(servcode_val, cfg.eip_offset_sel); -+ PPE_EG_SERVICE_SET_TX_CNT_EN(servcode_val, -+ test_bit(PPE_SC_BYPASS_COUNTER_TX_VLAN, cfg.bitmaps.counter)); -+ -+ ret = regmap_bulk_write(ppe_dev->regmap, reg, -+ servcode_val, ARRAY_SIZE(servcode_val)); -+ if (ret) -+ return ret; -+ -+ bitmap_value = bitmap_read(cfg.bitmaps.tunnel, 0, PPE_SC_BYPASS_TUNNEL_SIZE); -+ val = FIELD_PREP(PPE_TL_SERVICE_TBL_BYPASS_BITMAP, bitmap_value); -+ reg = PPE_TL_SERVICE_TBL_ADDR + PPE_TL_SERVICE_TBL_INC * sc; -+ -+ return regmap_write(ppe_dev->regmap, reg, val); -+} -+ - static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id, - const struct ppe_bm_port_config port_cfg) - { -@@ -1490,6 +1560,25 @@ static int ppe_queue_dest_init(struct pp - return 0; - } - -+/* Initialize the service code 1 used by CPU port. */ -+static int ppe_servcode_init(struct ppe_device *ppe_dev) -+{ -+ struct ppe_sc_cfg sc_cfg = {}; -+ -+ bitmap_zero(sc_cfg.bitmaps.counter, PPE_SC_BYPASS_COUNTER_SIZE); -+ bitmap_zero(sc_cfg.bitmaps.tunnel, PPE_SC_BYPASS_TUNNEL_SIZE); -+ -+ bitmap_fill(sc_cfg.bitmaps.ingress, PPE_SC_BYPASS_INGRESS_SIZE); -+ clear_bit(PPE_SC_BYPASS_INGRESS_FAKE_MAC_HEADER, sc_cfg.bitmaps.ingress); -+ clear_bit(PPE_SC_BYPASS_INGRESS_SERVICE_CODE, sc_cfg.bitmaps.ingress); -+ clear_bit(PPE_SC_BYPASS_INGRESS_FAKE_L2_PROTO, sc_cfg.bitmaps.ingress); -+ -+ bitmap_fill(sc_cfg.bitmaps.egress, PPE_SC_BYPASS_EGRESS_SIZE); -+ clear_bit(PPE_SC_BYPASS_EGRESS_ACL_POST_ROUTING_CHECK, sc_cfg.bitmaps.egress); -+ -+ return ppe_sc_config_set(ppe_dev, PPE_EDMA_SC_BYPASS_ID, sc_cfg); -+} -+ - int ppe_hw_config(struct ppe_device *ppe_dev) - { - int ret; -@@ -1506,5 +1595,9 @@ int ppe_hw_config(struct ppe_device *ppe - if (ret) - return ret; - -- return ppe_queue_dest_init(ppe_dev); -+ ret = ppe_queue_dest_init(ppe_dev); -+ if (ret) -+ return ret; -+ -+ return ppe_servcode_init(ppe_dev); - } ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h -@@ -6,6 +6,8 @@ - #ifndef __PPE_CONFIG_H__ - #define __PPE_CONFIG_H__ - -+#include -+ - #include "ppe.h" - - /* There are different table index ranges for configuring queue base ID of -@@ -18,6 +20,9 @@ - #define PPE_QUEUE_INTER_PRI_NUM 16 - #define PPE_QUEUE_HASH_NUM 256 - -+/* The service code is used by EDMA port to transmit packet to PPE. */ -+#define PPE_EDMA_SC_BYPASS_ID 1 -+ - /** - * enum ppe_scheduler_frame_mode - PPE scheduler frame mode. - * @PPE_SCH_WITH_IPG_PREAMBLE_FRAME_CRC: The scheduled frame includes IPG, -@@ -90,6 +95,144 @@ struct ppe_queue_ucast_dest { - int dest_port; - }; - -+/* Hardware bitmaps for bypassing features of the ingress packet. */ -+enum ppe_sc_ingress_type { -+ PPE_SC_BYPASS_INGRESS_VLAN_TAG_FMT_CHECK = 0, -+ PPE_SC_BYPASS_INGRESS_VLAN_MEMBER_CHECK = 1, -+ PPE_SC_BYPASS_INGRESS_VLAN_TRANSLATE = 2, -+ PPE_SC_BYPASS_INGRESS_MY_MAC_CHECK = 3, -+ PPE_SC_BYPASS_INGRESS_DIP_LOOKUP = 4, -+ PPE_SC_BYPASS_INGRESS_FLOW_LOOKUP = 5, -+ PPE_SC_BYPASS_INGRESS_FLOW_ACTION = 6, -+ PPE_SC_BYPASS_INGRESS_ACL = 7, -+ PPE_SC_BYPASS_INGRESS_FAKE_MAC_HEADER = 8, -+ PPE_SC_BYPASS_INGRESS_SERVICE_CODE = 9, -+ PPE_SC_BYPASS_INGRESS_WRONG_PKT_FMT_L2 = 10, -+ PPE_SC_BYPASS_INGRESS_WRONG_PKT_FMT_L3_IPV4 = 11, -+ PPE_SC_BYPASS_INGRESS_WRONG_PKT_FMT_L3_IPV6 = 12, -+ PPE_SC_BYPASS_INGRESS_WRONG_PKT_FMT_L4 = 13, -+ PPE_SC_BYPASS_INGRESS_FLOW_SERVICE_CODE = 14, -+ PPE_SC_BYPASS_INGRESS_ACL_SERVICE_CODE = 15, -+ PPE_SC_BYPASS_INGRESS_FAKE_L2_PROTO = 16, -+ PPE_SC_BYPASS_INGRESS_PPPOE_TERMINATION = 17, -+ PPE_SC_BYPASS_INGRESS_DEFAULT_VLAN = 18, -+ PPE_SC_BYPASS_INGRESS_DEFAULT_PCP = 19, -+ PPE_SC_BYPASS_INGRESS_VSI_ASSIGN = 20, -+ /* Values 21-23 are not specified by hardware. */ -+ PPE_SC_BYPASS_INGRESS_VLAN_ASSIGN_FAIL = 24, -+ PPE_SC_BYPASS_INGRESS_SOURCE_GUARD = 25, -+ PPE_SC_BYPASS_INGRESS_MRU_MTU_CHECK = 26, -+ PPE_SC_BYPASS_INGRESS_FLOW_SRC_CHECK = 27, -+ PPE_SC_BYPASS_INGRESS_FLOW_QOS = 28, -+ /* This must be last as it determines the size of the BITMAP. */ -+ PPE_SC_BYPASS_INGRESS_SIZE, -+}; -+ -+/* Hardware bitmaps for bypassing features of the egress packet. */ -+enum ppe_sc_egress_type { -+ PPE_SC_BYPASS_EGRESS_VLAN_MEMBER_CHECK = 0, -+ PPE_SC_BYPASS_EGRESS_VLAN_TRANSLATE = 1, -+ PPE_SC_BYPASS_EGRESS_VLAN_TAG_FMT_CTRL = 2, -+ PPE_SC_BYPASS_EGRESS_FDB_LEARN = 3, -+ PPE_SC_BYPASS_EGRESS_FDB_REFRESH = 4, -+ PPE_SC_BYPASS_EGRESS_L2_SOURCE_SECURITY = 5, -+ PPE_SC_BYPASS_EGRESS_MANAGEMENT_FWD = 6, -+ PPE_SC_BYPASS_EGRESS_BRIDGING_FWD = 7, -+ PPE_SC_BYPASS_EGRESS_IN_STP_FLTR = 8, -+ PPE_SC_BYPASS_EGRESS_EG_STP_FLTR = 9, -+ PPE_SC_BYPASS_EGRESS_SOURCE_FLTR = 10, -+ PPE_SC_BYPASS_EGRESS_POLICER = 11, -+ PPE_SC_BYPASS_EGRESS_L2_PKT_EDIT = 12, -+ PPE_SC_BYPASS_EGRESS_L3_PKT_EDIT = 13, -+ PPE_SC_BYPASS_EGRESS_ACL_POST_ROUTING_CHECK = 14, -+ PPE_SC_BYPASS_EGRESS_PORT_ISOLATION = 15, -+ PPE_SC_BYPASS_EGRESS_PRE_ACL_QOS = 16, -+ PPE_SC_BYPASS_EGRESS_POST_ACL_QOS = 17, -+ PPE_SC_BYPASS_EGRESS_DSCP_QOS = 18, -+ PPE_SC_BYPASS_EGRESS_PCP_QOS = 19, -+ PPE_SC_BYPASS_EGRESS_PREHEADER_QOS = 20, -+ PPE_SC_BYPASS_EGRESS_FAKE_MAC_DROP = 21, -+ PPE_SC_BYPASS_EGRESS_TUNL_CONTEXT = 22, -+ PPE_SC_BYPASS_EGRESS_FLOW_POLICER = 23, -+ /* This must be last as it determines the size of the BITMAP. */ -+ PPE_SC_BYPASS_EGRESS_SIZE, -+}; -+ -+/* Hardware bitmaps for bypassing counter of packet. */ -+enum ppe_sc_counter_type { -+ PPE_SC_BYPASS_COUNTER_RX_VLAN = 0, -+ PPE_SC_BYPASS_COUNTER_RX = 1, -+ PPE_SC_BYPASS_COUNTER_TX_VLAN = 2, -+ PPE_SC_BYPASS_COUNTER_TX = 3, -+ /* This must be last as it determines the size of the BITMAP. */ -+ PPE_SC_BYPASS_COUNTER_SIZE, -+}; -+ -+/* Hardware bitmaps for bypassing features of tunnel packet. */ -+enum ppe_sc_tunnel_type { -+ PPE_SC_BYPASS_TUNNEL_SERVICE_CODE = 0, -+ PPE_SC_BYPASS_TUNNEL_TUNNEL_HANDLE = 1, -+ PPE_SC_BYPASS_TUNNEL_L3_IF_CHECK = 2, -+ PPE_SC_BYPASS_TUNNEL_VLAN_CHECK = 3, -+ PPE_SC_BYPASS_TUNNEL_DMAC_CHECK = 4, -+ PPE_SC_BYPASS_TUNNEL_UDP_CSUM_0_CHECK = 5, -+ PPE_SC_BYPASS_TUNNEL_TBL_DE_ACCE_CHECK = 6, -+ PPE_SC_BYPASS_TUNNEL_PPPOE_MC_TERM_CHECK = 7, -+ PPE_SC_BYPASS_TUNNEL_TTL_EXCEED_CHECK = 8, -+ PPE_SC_BYPASS_TUNNEL_MAP_SRC_CHECK = 9, -+ PPE_SC_BYPASS_TUNNEL_MAP_DST_CHECK = 10, -+ PPE_SC_BYPASS_TUNNEL_LPM_DST_LOOKUP = 11, -+ PPE_SC_BYPASS_TUNNEL_LPM_LOOKUP = 12, -+ PPE_SC_BYPASS_TUNNEL_WRONG_PKT_FMT_L2 = 13, -+ PPE_SC_BYPASS_TUNNEL_WRONG_PKT_FMT_L3_IPV4 = 14, -+ PPE_SC_BYPASS_TUNNEL_WRONG_PKT_FMT_L3_IPV6 = 15, -+ PPE_SC_BYPASS_TUNNEL_WRONG_PKT_FMT_L4 = 16, -+ PPE_SC_BYPASS_TUNNEL_WRONG_PKT_FMT_TUNNEL = 17, -+ /* Values 18-19 are not specified by hardware. */ -+ PPE_SC_BYPASS_TUNNEL_PRE_IPO = 20, -+ /* This must be last as it determines the size of the BITMAP. */ -+ PPE_SC_BYPASS_TUNNEL_SIZE, -+}; -+ -+/** -+ * struct ppe_sc_bypass - PPE service bypass bitmaps -+ * @ingress: Bitmap of features that can be bypassed on the ingress packet. -+ * @egress: Bitmap of features that can be bypassed on the egress packet. -+ * @counter: Bitmap of features that can be bypassed on the counter type. -+ * @tunnel: Bitmap of features that can be bypassed on the tunnel packet. -+ */ -+struct ppe_sc_bypass { -+ DECLARE_BITMAP(ingress, PPE_SC_BYPASS_INGRESS_SIZE); -+ DECLARE_BITMAP(egress, PPE_SC_BYPASS_EGRESS_SIZE); -+ DECLARE_BITMAP(counter, PPE_SC_BYPASS_COUNTER_SIZE); -+ DECLARE_BITMAP(tunnel, PPE_SC_BYPASS_TUNNEL_SIZE); -+}; -+ -+/** -+ * struct ppe_sc_cfg - PPE service code configuration. -+ * @dest_port_valid: Generate destination port or not. -+ * @dest_port: Destination port ID. -+ * @bitmaps: Bitmap of bypass features. -+ * @is_src: Destination port acts as source port, packet sent to CPU. -+ * @next_service_code: New service code generated. -+ * @eip_field_update_bitmap: Fields updated as actions taken for EIP. -+ * @eip_hw_service: Selected hardware functions for EIP. -+ * @eip_offset_sel: Packet offset selection, using packet's layer 4 offset -+ * or using packet's layer 3 offset for EIP. -+ * -+ * Service code is generated during the packet passing through PPE. -+ */ -+struct ppe_sc_cfg { -+ bool dest_port_valid; -+ int dest_port; -+ struct ppe_sc_bypass bitmaps; -+ bool is_src; -+ int next_service_code; -+ int eip_field_update_bitmap; -+ int eip_hw_service; -+ int eip_offset_sel; -+}; -+ - int ppe_hw_config(struct ppe_device *ppe_dev); - int ppe_queue_scheduler_set(struct ppe_device *ppe_dev, - int node_id, bool flow_level, int port, -@@ -109,4 +252,6 @@ int ppe_queue_ucast_offset_hash_set(stru - int ppe_port_resource_get(struct ppe_device *ppe_dev, int port, - enum ppe_resource_type type, - int *res_start, int *res_end); -+int ppe_sc_config_set(struct ppe_device *ppe_dev, int sc, -+ struct ppe_sc_cfg cfg); - #endif ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -@@ -25,10 +25,63 @@ - #define PPE_BM_SCH_CFG_TBL_SECOND_PORT_VALID BIT(6) - #define PPE_BM_SCH_CFG_TBL_SECOND_PORT GENMASK(11, 8) - -+/* PPE service code configuration for the ingress direction functions, -+ * including bypass configuration for relevant PPE switch core functions -+ * such as flow entry lookup bypass. -+ */ -+#define PPE_SERVICE_TBL_ADDR 0x15000 -+#define PPE_SERVICE_TBL_ENTRIES 256 -+#define PPE_SERVICE_TBL_INC 0x10 -+#define PPE_SERVICE_W0_BYPASS_BITMAP GENMASK(31, 0) -+#define PPE_SERVICE_W1_RX_CNT_EN BIT(0) -+ -+#define PPE_SERVICE_SET_BYPASS_BITMAP(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_SERVICE_W0_BYPASS_BITMAP) -+#define PPE_SERVICE_SET_RX_CNT_EN(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_SERVICE_W1_RX_CNT_EN) -+ - /* PPE queue counters enable/disable control. */ - #define PPE_EG_BRIDGE_CONFIG_ADDR 0x20044 - #define PPE_EG_BRIDGE_CONFIG_QUEUE_CNT_EN BIT(2) - -+/* PPE service code configuration on the egress direction. */ -+#define PPE_EG_SERVICE_TBL_ADDR 0x43000 -+#define PPE_EG_SERVICE_TBL_ENTRIES 256 -+#define PPE_EG_SERVICE_TBL_INC 0x10 -+#define PPE_EG_SERVICE_W0_UPDATE_ACTION GENMASK(31, 0) -+#define PPE_EG_SERVICE_W1_NEXT_SERVCODE GENMASK(7, 0) -+#define PPE_EG_SERVICE_W1_HW_SERVICE GENMASK(13, 8) -+#define PPE_EG_SERVICE_W1_OFFSET_SEL BIT(14) -+#define PPE_EG_SERVICE_W1_TX_CNT_EN BIT(15) -+ -+#define PPE_EG_SERVICE_SET_UPDATE_ACTION(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_EG_SERVICE_W0_UPDATE_ACTION) -+#define PPE_EG_SERVICE_SET_NEXT_SERVCODE(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_EG_SERVICE_W1_NEXT_SERVCODE) -+#define PPE_EG_SERVICE_SET_HW_SERVICE(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_EG_SERVICE_W1_HW_SERVICE) -+#define PPE_EG_SERVICE_SET_OFFSET_SEL(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_EG_SERVICE_W1_OFFSET_SEL) -+#define PPE_EG_SERVICE_SET_TX_CNT_EN(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_EG_SERVICE_W1_TX_CNT_EN) -+ -+/* PPE service code configuration for destination port and counter. */ -+#define PPE_IN_L2_SERVICE_TBL_ADDR 0x66000 -+#define PPE_IN_L2_SERVICE_TBL_ENTRIES 256 -+#define PPE_IN_L2_SERVICE_TBL_INC 0x10 -+#define PPE_IN_L2_SERVICE_TBL_DST_PORT_ID_VALID BIT(0) -+#define PPE_IN_L2_SERVICE_TBL_DST_PORT_ID GENMASK(4, 1) -+#define PPE_IN_L2_SERVICE_TBL_DST_DIRECTION BIT(5) -+#define PPE_IN_L2_SERVICE_TBL_DST_BYPASS_BITMAP GENMASK(29, 6) -+#define PPE_IN_L2_SERVICE_TBL_RX_CNT_EN BIT(30) -+#define PPE_IN_L2_SERVICE_TBL_TX_CNT_EN BIT(31) -+ -+/* PPE service code configuration for the tunnel packet. */ -+#define PPE_TL_SERVICE_TBL_ADDR 0x306000 -+#define PPE_TL_SERVICE_TBL_ENTRIES 256 -+#define PPE_TL_SERVICE_TBL_INC 4 -+#define PPE_TL_SERVICE_TBL_BYPASS_BITMAP GENMASK(31, 0) -+ - /* Port scheduler global config. */ - #define PPE_PSCH_SCH_DEPTH_CFG_ADDR 0x400000 - #define PPE_PSCH_SCH_DEPTH_CFG_INC 4 diff --git a/target/linux/qualcommbe/patches-6.12/0331-net-ethernet-qualcomm-Initialize-PPE-port-control-se.patch b/target/linux/qualcommbe/patches-6.12/0331-net-ethernet-qualcomm-Initialize-PPE-port-control-se.patch deleted file mode 100644 index f1dcb51a87..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0331-net-ethernet-qualcomm-Initialize-PPE-port-control-se.patch +++ /dev/null @@ -1,215 +0,0 @@ -From 63af46200da794acda25cf8083bde0c1576b0859 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 9 Feb 2025 22:29:43 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Initialize PPE port control settings - -1. Enable port specific counters in PPE. -2. Configure the default action as drop when the packet size - is more than the configured MTU of physical port. - -Signed-off-by: Luo Jie ---- - .../net/ethernet/qualcomm/ppe/ppe_config.c | 86 ++++++++++++++++++- - .../net/ethernet/qualcomm/ppe/ppe_config.h | 15 ++++ - drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 47 ++++++++++ - 3 files changed, 147 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -@@ -1153,6 +1153,44 @@ int ppe_sc_config_set(struct ppe_device - return regmap_write(ppe_dev->regmap, reg, val); - } - -+/** -+ * ppe_counter_enable_set - Set PPE port counter enabled -+ * @ppe_dev: PPE device -+ * @port: PPE port ID -+ * -+ * Enable PPE counters on the given port for the unicast packet, multicast -+ * packet and VLAN packet received and transmitted by PPE. -+ * -+ * Return: 0 on success, negative error code on failure. -+ */ -+int ppe_counter_enable_set(struct ppe_device *ppe_dev, int port) -+{ -+ u32 reg, mru_mtu_val[3]; -+ int ret; -+ -+ reg = PPE_MRU_MTU_CTRL_TBL_ADDR + PPE_MRU_MTU_CTRL_TBL_INC * port; -+ ret = regmap_bulk_read(ppe_dev->regmap, reg, -+ mru_mtu_val, ARRAY_SIZE(mru_mtu_val)); -+ if (ret) -+ return ret; -+ -+ PPE_MRU_MTU_CTRL_SET_RX_CNT_EN(mru_mtu_val, true); -+ PPE_MRU_MTU_CTRL_SET_TX_CNT_EN(mru_mtu_val, true); -+ ret = regmap_bulk_write(ppe_dev->regmap, reg, -+ mru_mtu_val, ARRAY_SIZE(mru_mtu_val)); -+ if (ret) -+ return ret; -+ -+ reg = PPE_MC_MTU_CTRL_TBL_ADDR + PPE_MC_MTU_CTRL_TBL_INC * port; -+ ret = regmap_set_bits(ppe_dev->regmap, reg, PPE_MC_MTU_CTRL_TBL_TX_CNT_EN); -+ if (ret) -+ return ret; -+ -+ reg = PPE_PORT_EG_VLAN_TBL_ADDR + PPE_PORT_EG_VLAN_TBL_INC * port; -+ -+ return regmap_set_bits(ppe_dev->regmap, reg, PPE_PORT_EG_VLAN_TBL_TX_COUNTING_EN); -+} -+ - static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id, - const struct ppe_bm_port_config port_cfg) - { -@@ -1579,6 +1617,48 @@ static int ppe_servcode_init(struct ppe_ - return ppe_sc_config_set(ppe_dev, PPE_EDMA_SC_BYPASS_ID, sc_cfg); - } - -+/* Initialize PPE port configurations. */ -+static int ppe_port_config_init(struct ppe_device *ppe_dev) -+{ -+ u32 reg, val, mru_mtu_val[3]; -+ int i, ret; -+ -+ /* MTU and MRU settings are not required for CPU port 0. */ -+ for (i = 1; i < ppe_dev->num_ports; i++) { -+ /* Enable Ethernet port counter */ -+ ret = ppe_counter_enable_set(ppe_dev, i); -+ if (ret) -+ return ret; -+ -+ reg = PPE_MRU_MTU_CTRL_TBL_ADDR + PPE_MRU_MTU_CTRL_TBL_INC * i; -+ ret = regmap_bulk_read(ppe_dev->regmap, reg, -+ mru_mtu_val, ARRAY_SIZE(mru_mtu_val)); -+ if (ret) -+ return ret; -+ -+ /* Drop the packet when the packet size is more than -+ * the MTU or MRU of the physical interface. -+ */ -+ PPE_MRU_MTU_CTRL_SET_MRU_CMD(mru_mtu_val, PPE_ACTION_DROP); -+ PPE_MRU_MTU_CTRL_SET_MTU_CMD(mru_mtu_val, PPE_ACTION_DROP); -+ ret = regmap_bulk_write(ppe_dev->regmap, reg, -+ mru_mtu_val, ARRAY_SIZE(mru_mtu_val)); -+ if (ret) -+ return ret; -+ -+ reg = PPE_MC_MTU_CTRL_TBL_ADDR + PPE_MC_MTU_CTRL_TBL_INC * i; -+ val = FIELD_PREP(PPE_MC_MTU_CTRL_TBL_MTU_CMD, PPE_ACTION_DROP); -+ ret = regmap_update_bits(ppe_dev->regmap, reg, -+ PPE_MC_MTU_CTRL_TBL_MTU_CMD, -+ val); -+ if (ret) -+ return ret; -+ } -+ -+ /* Enable CPU port counters. */ -+ return ppe_counter_enable_set(ppe_dev, 0); -+} -+ - int ppe_hw_config(struct ppe_device *ppe_dev) - { - int ret; -@@ -1599,5 +1679,9 @@ int ppe_hw_config(struct ppe_device *ppe - if (ret) - return ret; - -- return ppe_servcode_init(ppe_dev); -+ ret = ppe_servcode_init(ppe_dev); -+ if (ret) -+ return ret; -+ -+ return ppe_port_config_init(ppe_dev); - } ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h -@@ -233,6 +233,20 @@ struct ppe_sc_cfg { - int eip_offset_sel; - }; - -+/** -+ * enum ppe_action_type - PPE action of the received packet. -+ * @PPE_ACTION_FORWARD: Packet forwarded per L2/L3 process. -+ * @PPE_ACTION_DROP: Packet dropped by PPE. -+ * @PPE_ACTION_COPY_TO_CPU: Packet copied to CPU port per multicast queue. -+ * @PPE_ACTION_REDIRECT_TO_CPU: Packet redirected to CPU port per unicast queue. -+ */ -+enum ppe_action_type { -+ PPE_ACTION_FORWARD = 0, -+ PPE_ACTION_DROP = 1, -+ PPE_ACTION_COPY_TO_CPU = 2, -+ PPE_ACTION_REDIRECT_TO_CPU = 3, -+}; -+ - int ppe_hw_config(struct ppe_device *ppe_dev); - int ppe_queue_scheduler_set(struct ppe_device *ppe_dev, - int node_id, bool flow_level, int port, -@@ -254,4 +268,5 @@ int ppe_port_resource_get(struct ppe_dev - int *res_start, int *res_end); - int ppe_sc_config_set(struct ppe_device *ppe_dev, int sc, - struct ppe_sc_cfg cfg); -+int ppe_counter_enable_set(struct ppe_device *ppe_dev, int port); - #endif ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -@@ -40,6 +40,18 @@ - #define PPE_SERVICE_SET_RX_CNT_EN(tbl_cfg, value) \ - u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_SERVICE_W1_RX_CNT_EN) - -+/* PPE port egress VLAN configurations. */ -+#define PPE_PORT_EG_VLAN_TBL_ADDR 0x20020 -+#define PPE_PORT_EG_VLAN_TBL_ENTRIES 8 -+#define PPE_PORT_EG_VLAN_TBL_INC 4 -+#define PPE_PORT_EG_VLAN_TBL_VLAN_TYPE BIT(0) -+#define PPE_PORT_EG_VLAN_TBL_CTAG_MODE GENMASK(2, 1) -+#define PPE_PORT_EG_VLAN_TBL_STAG_MODE GENMASK(4, 3) -+#define PPE_PORT_EG_VLAN_TBL_VSI_TAG_MODE_EN BIT(5) -+#define PPE_PORT_EG_VLAN_TBL_PCP_PROP_CMD BIT(6) -+#define PPE_PORT_EG_VLAN_TBL_DEI_PROP_CMD BIT(7) -+#define PPE_PORT_EG_VLAN_TBL_TX_COUNTING_EN BIT(8) -+ - /* PPE queue counters enable/disable control. */ - #define PPE_EG_BRIDGE_CONFIG_ADDR 0x20044 - #define PPE_EG_BRIDGE_CONFIG_QUEUE_CNT_EN BIT(2) -@@ -65,6 +77,41 @@ - #define PPE_EG_SERVICE_SET_TX_CNT_EN(tbl_cfg, value) \ - u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_EG_SERVICE_W1_TX_CNT_EN) - -+/* PPE port control configurations for the traffic to the multicast queues. */ -+#define PPE_MC_MTU_CTRL_TBL_ADDR 0x60a00 -+#define PPE_MC_MTU_CTRL_TBL_ENTRIES 8 -+#define PPE_MC_MTU_CTRL_TBL_INC 4 -+#define PPE_MC_MTU_CTRL_TBL_MTU GENMASK(13, 0) -+#define PPE_MC_MTU_CTRL_TBL_MTU_CMD GENMASK(15, 14) -+#define PPE_MC_MTU_CTRL_TBL_TX_CNT_EN BIT(16) -+ -+/* PPE port control configurations for the traffic to the unicast queues. */ -+#define PPE_MRU_MTU_CTRL_TBL_ADDR 0x65000 -+#define PPE_MRU_MTU_CTRL_TBL_ENTRIES 256 -+#define PPE_MRU_MTU_CTRL_TBL_INC 0x10 -+#define PPE_MRU_MTU_CTRL_W0_MRU GENMASK(13, 0) -+#define PPE_MRU_MTU_CTRL_W0_MRU_CMD GENMASK(15, 14) -+#define PPE_MRU_MTU_CTRL_W0_MTU GENMASK(29, 16) -+#define PPE_MRU_MTU_CTRL_W0_MTU_CMD GENMASK(31, 30) -+#define PPE_MRU_MTU_CTRL_W1_RX_CNT_EN BIT(0) -+#define PPE_MRU_MTU_CTRL_W1_TX_CNT_EN BIT(1) -+#define PPE_MRU_MTU_CTRL_W1_SRC_PROFILE GENMASK(3, 2) -+#define PPE_MRU_MTU_CTRL_W1_INNER_PREC_LOW BIT(31) -+#define PPE_MRU_MTU_CTRL_W2_INNER_PREC_HIGH GENMASK(1, 0) -+ -+#define PPE_MRU_MTU_CTRL_SET_MRU(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_MRU_MTU_CTRL_W0_MRU) -+#define PPE_MRU_MTU_CTRL_SET_MRU_CMD(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_MRU_MTU_CTRL_W0_MRU_CMD) -+#define PPE_MRU_MTU_CTRL_SET_MTU(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_MRU_MTU_CTRL_W0_MTU) -+#define PPE_MRU_MTU_CTRL_SET_MTU_CMD(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_MRU_MTU_CTRL_W0_MTU_CMD) -+#define PPE_MRU_MTU_CTRL_SET_RX_CNT_EN(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_MRU_MTU_CTRL_W1_RX_CNT_EN) -+#define PPE_MRU_MTU_CTRL_SET_TX_CNT_EN(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_MRU_MTU_CTRL_W1_TX_CNT_EN) -+ - /* PPE service code configuration for destination port and counter. */ - #define PPE_IN_L2_SERVICE_TBL_ADDR 0x66000 - #define PPE_IN_L2_SERVICE_TBL_ENTRIES 256 diff --git a/target/linux/qualcommbe/patches-6.12/0332-net-ethernet-qualcomm-Initialize-PPE-RSS-hash-settin.patch b/target/linux/qualcommbe/patches-6.12/0332-net-ethernet-qualcomm-Initialize-PPE-RSS-hash-settin.patch deleted file mode 100644 index fc0764284d..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0332-net-ethernet-qualcomm-Initialize-PPE-RSS-hash-settin.patch +++ /dev/null @@ -1,344 +0,0 @@ -From 796be78fffeebe77237a6464da7ebe9807d670f0 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 9 Feb 2025 22:29:44 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Initialize PPE RSS hash settings - -PPE RSS hash is generated during PPE receive, based on the packet -content (3 tuples or 5 tuples) and as per the configured RSS seed. -The hash is then used to select the queue to transmit the packet -to the ARM CPU. - -This patch initializes the RSS hash settings that are used to -generate the hash for the packet during PPE packet receive. - -Signed-off-by: Luo Jie ---- - .../net/ethernet/qualcomm/ppe/ppe_config.c | 194 +++++++++++++++++- - .../net/ethernet/qualcomm/ppe/ppe_config.h | 39 ++++ - drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 40 ++++ - 3 files changed, 272 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -@@ -1191,6 +1191,143 @@ int ppe_counter_enable_set(struct ppe_de - return regmap_set_bits(ppe_dev->regmap, reg, PPE_PORT_EG_VLAN_TBL_TX_COUNTING_EN); - } - -+static int ppe_rss_hash_ipv4_config(struct ppe_device *ppe_dev, int index, -+ struct ppe_rss_hash_cfg cfg) -+{ -+ u32 reg, val; -+ -+ switch (index) { -+ case 0: -+ val = FIELD_PREP(PPE_RSS_HASH_MIX_IPV4_VAL, cfg.hash_sip_mix[0]); -+ break; -+ case 1: -+ val = FIELD_PREP(PPE_RSS_HASH_MIX_IPV4_VAL, cfg.hash_dip_mix[0]); -+ break; -+ case 2: -+ val = FIELD_PREP(PPE_RSS_HASH_MIX_IPV4_VAL, cfg.hash_protocol_mix); -+ break; -+ case 3: -+ val = FIELD_PREP(PPE_RSS_HASH_MIX_IPV4_VAL, cfg.hash_dport_mix); -+ break; -+ case 4: -+ val = FIELD_PREP(PPE_RSS_HASH_MIX_IPV4_VAL, cfg.hash_sport_mix); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ reg = PPE_RSS_HASH_MIX_IPV4_ADDR + index * PPE_RSS_HASH_MIX_IPV4_INC; -+ -+ return regmap_write(ppe_dev->regmap, reg, val); -+} -+ -+static int ppe_rss_hash_ipv6_config(struct ppe_device *ppe_dev, int index, -+ struct ppe_rss_hash_cfg cfg) -+{ -+ u32 reg, val; -+ -+ switch (index) { -+ case 0 ... 3: -+ val = FIELD_PREP(PPE_RSS_HASH_MIX_VAL, cfg.hash_sip_mix[index]); -+ break; -+ case 4 ... 7: -+ val = FIELD_PREP(PPE_RSS_HASH_MIX_VAL, cfg.hash_dip_mix[index - 4]); -+ break; -+ case 8: -+ val = FIELD_PREP(PPE_RSS_HASH_MIX_VAL, cfg.hash_protocol_mix); -+ break; -+ case 9: -+ val = FIELD_PREP(PPE_RSS_HASH_MIX_VAL, cfg.hash_dport_mix); -+ break; -+ case 10: -+ val = FIELD_PREP(PPE_RSS_HASH_MIX_VAL, cfg.hash_sport_mix); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ reg = PPE_RSS_HASH_MIX_ADDR + index * PPE_RSS_HASH_MIX_INC; -+ -+ return regmap_write(ppe_dev->regmap, reg, val); -+} -+ -+/** -+ * ppe_rss_hash_config_set - Configure the PPE hash settings for the packet received. -+ * @ppe_dev: PPE device. -+ * @mode: Configure RSS hash for the packet type IPv4 and IPv6. -+ * @cfg: RSS hash configuration. -+ * -+ * PPE RSS hash settings are configured for the packet type IPv4 and IPv6. -+ * -+ * Return: 0 on success, negative error code on failure. -+ */ -+int ppe_rss_hash_config_set(struct ppe_device *ppe_dev, int mode, -+ struct ppe_rss_hash_cfg cfg) -+{ -+ u32 val, reg; -+ int i, ret; -+ -+ if (mode & PPE_RSS_HASH_MODE_IPV4) { -+ val = FIELD_PREP(PPE_RSS_HASH_MASK_IPV4_HASH_MASK, cfg.hash_mask); -+ val |= FIELD_PREP(PPE_RSS_HASH_MASK_IPV4_FRAGMENT, cfg.hash_fragment_mode); -+ ret = regmap_write(ppe_dev->regmap, PPE_RSS_HASH_MASK_IPV4_ADDR, val); -+ if (ret) -+ return ret; -+ -+ val = FIELD_PREP(PPE_RSS_HASH_SEED_IPV4_VAL, cfg.hash_seed); -+ ret = regmap_write(ppe_dev->regmap, PPE_RSS_HASH_SEED_IPV4_ADDR, val); -+ if (ret) -+ return ret; -+ -+ for (i = 0; i < PPE_RSS_HASH_MIX_IPV4_ENTRIES; i++) { -+ ret = ppe_rss_hash_ipv4_config(ppe_dev, i, cfg); -+ if (ret) -+ return ret; -+ } -+ -+ for (i = 0; i < PPE_RSS_HASH_FIN_IPV4_ENTRIES; i++) { -+ val = FIELD_PREP(PPE_RSS_HASH_FIN_IPV4_INNER, cfg.hash_fin_inner[i]); -+ val |= FIELD_PREP(PPE_RSS_HASH_FIN_IPV4_OUTER, cfg.hash_fin_outer[i]); -+ reg = PPE_RSS_HASH_FIN_IPV4_ADDR + i * PPE_RSS_HASH_FIN_IPV4_INC; -+ -+ ret = regmap_write(ppe_dev->regmap, reg, val); -+ if (ret) -+ return ret; -+ } -+ } -+ -+ if (mode & PPE_RSS_HASH_MODE_IPV6) { -+ val = FIELD_PREP(PPE_RSS_HASH_MASK_HASH_MASK, cfg.hash_mask); -+ val |= FIELD_PREP(PPE_RSS_HASH_MASK_FRAGMENT, cfg.hash_fragment_mode); -+ ret = regmap_write(ppe_dev->regmap, PPE_RSS_HASH_MASK_ADDR, val); -+ if (ret) -+ return ret; -+ -+ val = FIELD_PREP(PPE_RSS_HASH_SEED_VAL, cfg.hash_seed); -+ ret = regmap_write(ppe_dev->regmap, PPE_RSS_HASH_SEED_ADDR, val); -+ if (ret) -+ return ret; -+ -+ for (i = 0; i < PPE_RSS_HASH_MIX_ENTRIES; i++) { -+ ret = ppe_rss_hash_ipv6_config(ppe_dev, i, cfg); -+ if (ret) -+ return ret; -+ } -+ -+ for (i = 0; i < PPE_RSS_HASH_FIN_ENTRIES; i++) { -+ val = FIELD_PREP(PPE_RSS_HASH_FIN_INNER, cfg.hash_fin_inner[i]); -+ val |= FIELD_PREP(PPE_RSS_HASH_FIN_OUTER, cfg.hash_fin_outer[i]); -+ reg = PPE_RSS_HASH_FIN_ADDR + i * PPE_RSS_HASH_FIN_INC; -+ -+ ret = regmap_write(ppe_dev->regmap, reg, val); -+ if (ret) -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ - static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id, - const struct ppe_bm_port_config port_cfg) - { -@@ -1659,6 +1796,57 @@ static int ppe_port_config_init(struct p - return ppe_counter_enable_set(ppe_dev, 0); - } - -+/* Initialize the PPE RSS configuration for IPv4 and IPv6 packet receive. -+ * RSS settings are to calculate the random RSS hash value generated during -+ * packet receive. This hash is then used to generate the queue offset used -+ * to determine the queue used to transmit the packet. -+ */ -+static int ppe_rss_hash_init(struct ppe_device *ppe_dev) -+{ -+ u16 fins[PPE_RSS_HASH_TUPLES] = { 0x205, 0x264, 0x227, 0x245, 0x201 }; -+ u8 ips[PPE_RSS_HASH_IP_LENGTH] = { 0x13, 0xb, 0x13, 0xb }; -+ struct ppe_rss_hash_cfg hash_cfg; -+ int i, ret; -+ -+ hash_cfg.hash_seed = get_random_u32(); -+ hash_cfg.hash_mask = 0xfff; -+ -+ /* Use 5 tuple as RSS hash key for the first fragment of TCP, UDP -+ * and UDP-Lite packets. -+ */ -+ hash_cfg.hash_fragment_mode = false; -+ -+ /* The final common seed configs used to calculate the RSS has value, -+ * which is available for both IPv4 and IPv6 packet. -+ */ -+ for (i = 0; i < ARRAY_SIZE(fins); i++) { -+ hash_cfg.hash_fin_inner[i] = fins[i] & 0x1f; -+ hash_cfg.hash_fin_outer[i] = fins[i] >> 5; -+ } -+ -+ /* RSS seeds for IP protocol, L4 destination & source port and -+ * destination & source IP used to calculate the RSS hash value. -+ */ -+ hash_cfg.hash_protocol_mix = 0x13; -+ hash_cfg.hash_dport_mix = 0xb; -+ hash_cfg.hash_sport_mix = 0x13; -+ hash_cfg.hash_dip_mix[0] = 0xb; -+ hash_cfg.hash_sip_mix[0] = 0x13; -+ -+ /* Configure RSS seed configs for IPv4 packet. */ -+ ret = ppe_rss_hash_config_set(ppe_dev, PPE_RSS_HASH_MODE_IPV4, hash_cfg); -+ if (ret) -+ return ret; -+ -+ for (i = 0; i < ARRAY_SIZE(ips); i++) { -+ hash_cfg.hash_sip_mix[i] = ips[i]; -+ hash_cfg.hash_dip_mix[i] = ips[i]; -+ } -+ -+ /* Configure RSS seed configs for IPv6 packet. */ -+ return ppe_rss_hash_config_set(ppe_dev, PPE_RSS_HASH_MODE_IPV6, hash_cfg); -+} -+ - int ppe_hw_config(struct ppe_device *ppe_dev) - { - int ret; -@@ -1683,5 +1871,9 @@ int ppe_hw_config(struct ppe_device *ppe - if (ret) - return ret; - -- return ppe_port_config_init(ppe_dev); -+ ret = ppe_port_config_init(ppe_dev); -+ if (ret) -+ return ret; -+ -+ return ppe_rss_hash_init(ppe_dev); - } ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h -@@ -23,6 +23,12 @@ - /* The service code is used by EDMA port to transmit packet to PPE. */ - #define PPE_EDMA_SC_BYPASS_ID 1 - -+/* The PPE RSS hash configured for IPv4 and IPv6 packet separately. */ -+#define PPE_RSS_HASH_MODE_IPV4 BIT(0) -+#define PPE_RSS_HASH_MODE_IPV6 BIT(1) -+#define PPE_RSS_HASH_IP_LENGTH 4 -+#define PPE_RSS_HASH_TUPLES 5 -+ - /** - * enum ppe_scheduler_frame_mode - PPE scheduler frame mode. - * @PPE_SCH_WITH_IPG_PREAMBLE_FRAME_CRC: The scheduled frame includes IPG, -@@ -247,6 +253,37 @@ enum ppe_action_type { - PPE_ACTION_REDIRECT_TO_CPU = 3, - }; - -+/** -+ * struct ppe_rss_hash_cfg - PPE RSS hash configuration. -+ * @hash_mask: Mask of the generated hash value. -+ * @hash_fragment_mode: Hash generation mode for the first fragment of TCP, -+ * UDP and UDP-Lite packets, to use either 3 tuple or 5 tuple for RSS hash -+ * key computation. -+ * @hash_seed: Seed to generate RSS hash. -+ * @hash_sip_mix: Source IP selection. -+ * @hash_dip_mix: Destination IP selection. -+ * @hash_protocol_mix: Protocol selection. -+ * @hash_sport_mix: Source L4 port selection. -+ * @hash_dport_mix: Destination L4 port selection. -+ * @hash_fin_inner: RSS hash value first selection. -+ * @hash_fin_outer: RSS hash value second selection. -+ * -+ * PPE RSS hash value is generated for the packet based on the RSS hash -+ * configured. -+ */ -+struct ppe_rss_hash_cfg { -+ u32 hash_mask; -+ bool hash_fragment_mode; -+ u32 hash_seed; -+ u8 hash_sip_mix[PPE_RSS_HASH_IP_LENGTH]; -+ u8 hash_dip_mix[PPE_RSS_HASH_IP_LENGTH]; -+ u8 hash_protocol_mix; -+ u8 hash_sport_mix; -+ u8 hash_dport_mix; -+ u8 hash_fin_inner[PPE_RSS_HASH_TUPLES]; -+ u8 hash_fin_outer[PPE_RSS_HASH_TUPLES]; -+}; -+ - int ppe_hw_config(struct ppe_device *ppe_dev); - int ppe_queue_scheduler_set(struct ppe_device *ppe_dev, - int node_id, bool flow_level, int port, -@@ -269,4 +306,6 @@ int ppe_port_resource_get(struct ppe_dev - int ppe_sc_config_set(struct ppe_device *ppe_dev, int sc, - struct ppe_sc_cfg cfg); - int ppe_counter_enable_set(struct ppe_device *ppe_dev, int port); -+int ppe_rss_hash_config_set(struct ppe_device *ppe_dev, int mode, -+ struct ppe_rss_hash_cfg hash_cfg); - #endif ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -@@ -16,6 +16,46 @@ - #define PPE_BM_SCH_CTRL_SCH_OFFSET GENMASK(14, 8) - #define PPE_BM_SCH_CTRL_SCH_EN BIT(31) - -+/* RSS settings are to calculate the random RSS hash value generated during -+ * packet receive to ARM cores. This hash is then used to generate the queue -+ * offset used to determine the queue used to transmit the packet to ARM cores. -+ */ -+#define PPE_RSS_HASH_MASK_ADDR 0xb4318 -+#define PPE_RSS_HASH_MASK_HASH_MASK GENMASK(20, 0) -+#define PPE_RSS_HASH_MASK_FRAGMENT BIT(28) -+ -+#define PPE_RSS_HASH_SEED_ADDR 0xb431c -+#define PPE_RSS_HASH_SEED_VAL GENMASK(31, 0) -+ -+#define PPE_RSS_HASH_MIX_ADDR 0xb4320 -+#define PPE_RSS_HASH_MIX_ENTRIES 11 -+#define PPE_RSS_HASH_MIX_INC 4 -+#define PPE_RSS_HASH_MIX_VAL GENMASK(4, 0) -+ -+#define PPE_RSS_HASH_FIN_ADDR 0xb4350 -+#define PPE_RSS_HASH_FIN_ENTRIES 5 -+#define PPE_RSS_HASH_FIN_INC 4 -+#define PPE_RSS_HASH_FIN_INNER GENMASK(4, 0) -+#define PPE_RSS_HASH_FIN_OUTER GENMASK(9, 5) -+ -+#define PPE_RSS_HASH_MASK_IPV4_ADDR 0xb4380 -+#define PPE_RSS_HASH_MASK_IPV4_HASH_MASK GENMASK(20, 0) -+#define PPE_RSS_HASH_MASK_IPV4_FRAGMENT BIT(28) -+ -+#define PPE_RSS_HASH_SEED_IPV4_ADDR 0xb4384 -+#define PPE_RSS_HASH_SEED_IPV4_VAL GENMASK(31, 0) -+ -+#define PPE_RSS_HASH_MIX_IPV4_ADDR 0xb4390 -+#define PPE_RSS_HASH_MIX_IPV4_ENTRIES 5 -+#define PPE_RSS_HASH_MIX_IPV4_INC 4 -+#define PPE_RSS_HASH_MIX_IPV4_VAL GENMASK(4, 0) -+ -+#define PPE_RSS_HASH_FIN_IPV4_ADDR 0xb43b0 -+#define PPE_RSS_HASH_FIN_IPV4_ENTRIES 5 -+#define PPE_RSS_HASH_FIN_IPV4_INC 4 -+#define PPE_RSS_HASH_FIN_IPV4_INNER GENMASK(4, 0) -+#define PPE_RSS_HASH_FIN_IPV4_OUTER GENMASK(9, 5) -+ - #define PPE_BM_SCH_CFG_TBL_ADDR 0xc000 - #define PPE_BM_SCH_CFG_TBL_ENTRIES 128 - #define PPE_BM_SCH_CFG_TBL_INC 0x10 diff --git a/target/linux/qualcommbe/patches-6.12/0333-net-ethernet-qualcomm-Initialize-PPE-queue-to-Ethern.patch b/target/linux/qualcommbe/patches-6.12/0333-net-ethernet-qualcomm-Initialize-PPE-queue-to-Ethern.patch deleted file mode 100644 index e05748f0f3..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0333-net-ethernet-qualcomm-Initialize-PPE-queue-to-Ethern.patch +++ /dev/null @@ -1,122 +0,0 @@ -From c4a321bc120fabc318df165a7fcdeddfcf052253 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 9 Feb 2025 22:29:45 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Initialize PPE queue to Ethernet DMA - ring mapping - -Configure the selected queues to map with an Ethernet DMA ring for the -packet to receive on ARM cores. - -As default initialization, all queues assigned to CPU port 0 are mapped -to the EDMA ring 0. This configuration is later updated during Ethernet -DMA initialization. - -Signed-off-by: Luo Jie ---- - .../net/ethernet/qualcomm/ppe/ppe_config.c | 47 ++++++++++++++++++- - .../net/ethernet/qualcomm/ppe/ppe_config.h | 6 +++ - drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 5 ++ - 3 files changed, 57 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -@@ -1328,6 +1328,28 @@ int ppe_rss_hash_config_set(struct ppe_d - return 0; - } - -+/** -+ * ppe_ring_queue_map_set - Set the PPE queue to Ethernet DMA ring mapping -+ * @ppe_dev: PPE device -+ * @ring_id: Ethernet DMA ring ID -+ * @queue_map: Bit map of queue IDs to given Ethernet DMA ring -+ * -+ * Configure the mapping from a set of PPE queues to a given Ethernet DMA ring. -+ * -+ * Return: 0 on success, negative error code on failure. -+ */ -+int ppe_ring_queue_map_set(struct ppe_device *ppe_dev, int ring_id, u32 *queue_map) -+{ -+ u32 reg, queue_bitmap_val[PPE_RING_TO_QUEUE_BITMAP_WORD_CNT]; -+ -+ memcpy(queue_bitmap_val, queue_map, sizeof(queue_bitmap_val)); -+ reg = PPE_RING_Q_MAP_TBL_ADDR + PPE_RING_Q_MAP_TBL_INC * ring_id; -+ -+ return regmap_bulk_write(ppe_dev->regmap, reg, -+ queue_bitmap_val, -+ ARRAY_SIZE(queue_bitmap_val)); -+} -+ - static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id, - const struct ppe_bm_port_config port_cfg) - { -@@ -1847,6 +1869,25 @@ static int ppe_rss_hash_init(struct ppe_ - return ppe_rss_hash_config_set(ppe_dev, PPE_RSS_HASH_MODE_IPV6, hash_cfg); - } - -+/* Initialize mapping between PPE queues assigned to CPU port 0 -+ * to Ethernet DMA ring 0. -+ */ -+static int ppe_queues_to_ring_init(struct ppe_device *ppe_dev) -+{ -+ u32 queue_bmap[PPE_RING_TO_QUEUE_BITMAP_WORD_CNT] = {}; -+ int ret, queue_id, queue_max; -+ -+ ret = ppe_port_resource_get(ppe_dev, 0, PPE_RES_UCAST, -+ &queue_id, &queue_max); -+ if (ret) -+ return ret; -+ -+ for (; queue_id <= queue_max; queue_id++) -+ queue_bmap[queue_id / 32] |= BIT_MASK(queue_id % 32); -+ -+ return ppe_ring_queue_map_set(ppe_dev, 0, queue_bmap); -+} -+ - int ppe_hw_config(struct ppe_device *ppe_dev) - { - int ret; -@@ -1875,5 +1916,9 @@ int ppe_hw_config(struct ppe_device *ppe - if (ret) - return ret; - -- return ppe_rss_hash_init(ppe_dev); -+ ret = ppe_rss_hash_init(ppe_dev); -+ if (ret) -+ return ret; -+ -+ return ppe_queues_to_ring_init(ppe_dev); - } ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h -@@ -29,6 +29,9 @@ - #define PPE_RSS_HASH_IP_LENGTH 4 - #define PPE_RSS_HASH_TUPLES 5 - -+/* PPE supports 300 queues, each bit presents as one queue. */ -+#define PPE_RING_TO_QUEUE_BITMAP_WORD_CNT 10 -+ - /** - * enum ppe_scheduler_frame_mode - PPE scheduler frame mode. - * @PPE_SCH_WITH_IPG_PREAMBLE_FRAME_CRC: The scheduled frame includes IPG, -@@ -308,4 +311,7 @@ int ppe_sc_config_set(struct ppe_device - int ppe_counter_enable_set(struct ppe_device *ppe_dev, int port); - int ppe_rss_hash_config_set(struct ppe_device *ppe_dev, int mode, - struct ppe_rss_hash_cfg hash_cfg); -+int ppe_ring_queue_map_set(struct ppe_device *ppe_dev, -+ int ring_id, -+ u32 *queue_map); - #endif ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -@@ -207,6 +207,11 @@ - #define PPE_L0_COMP_CFG_TBL_SHAPER_METER_LEN GENMASK(1, 0) - #define PPE_L0_COMP_CFG_TBL_NODE_METER_LEN GENMASK(3, 2) - -+/* PPE queue to Ethernet DMA ring mapping table. */ -+#define PPE_RING_Q_MAP_TBL_ADDR 0x42a000 -+#define PPE_RING_Q_MAP_TBL_ENTRIES 24 -+#define PPE_RING_Q_MAP_TBL_INC 0x40 -+ - /* Table addresses for per-queue dequeue setting. */ - #define PPE_DEQ_OPR_TBL_ADDR 0x430000 - #define PPE_DEQ_OPR_TBL_ENTRIES 300 diff --git a/target/linux/qualcommbe/patches-6.12/0334-net-ethernet-qualcomm-Initialize-PPE-L2-bridge-setti.patch b/target/linux/qualcommbe/patches-6.12/0334-net-ethernet-qualcomm-Initialize-PPE-L2-bridge-setti.patch deleted file mode 100644 index 28a48163a6..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0334-net-ethernet-qualcomm-Initialize-PPE-L2-bridge-setti.patch +++ /dev/null @@ -1,193 +0,0 @@ -From cf7282d1e5712953516fa1cc0ffaae405491b3ca Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Sun, 9 Feb 2025 22:29:46 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Initialize PPE L2 bridge settings - -Initialize the L2 bridge settings for the PPE ports to only enable -L2 frame forwarding between CPU port and PPE Ethernet ports. - -The per-port L2 bridge settings are initialized as follows: -For PPE CPU port, the PPE bridge TX is enabled and FDB learning is -disabled. For PPE physical ports, the default L2 forwarding action -is initialized to forward to CPU port only. - -L2/FDB learning and forwarding will not be enabled for PPE physical -ports yet, since the port's VSI (Virtual Switch Instance) and VSI -membership are not yet configured, which are required for FDB -forwarding. The VSI and FDB forwarding will later be enabled when -switchdev is enabled. - -Signed-off-by: Lei Wei -Signed-off-by: Luo Jie ---- - .../net/ethernet/qualcomm/ppe/ppe_config.c | 80 ++++++++++++++++++- - drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 50 ++++++++++++ - 2 files changed, 129 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -@@ -1888,6 +1888,80 @@ static int ppe_queues_to_ring_init(struc - return ppe_ring_queue_map_set(ppe_dev, 0, queue_bmap); - } - -+/* Initialize PPE bridge settings to only enable L2 frame receive and -+ * transmit between CPU port and PPE Ethernet ports. -+ */ -+static int ppe_bridge_init(struct ppe_device *ppe_dev) -+{ -+ u32 reg, mask, port_cfg[4], vsi_cfg[2]; -+ int ret, i; -+ -+ /* Configure the following settings for CPU port0: -+ * a.) Enable Bridge TX -+ * b.) Disable FDB new address learning -+ * c.) Disable station move address learning -+ */ -+ mask = PPE_PORT_BRIDGE_TXMAC_EN; -+ mask |= PPE_PORT_BRIDGE_NEW_LRN_EN; -+ mask |= PPE_PORT_BRIDGE_STA_MOVE_LRN_EN; -+ ret = regmap_update_bits(ppe_dev->regmap, -+ PPE_PORT_BRIDGE_CTRL_ADDR, -+ mask, -+ PPE_PORT_BRIDGE_TXMAC_EN); -+ if (ret) -+ return ret; -+ -+ for (i = 1; i < ppe_dev->num_ports; i++) { -+ /* Enable invalid VSI forwarding for all the physical ports -+ * to CPU port0, in case no VSI is assigned to the physical -+ * port. -+ */ -+ reg = PPE_L2_VP_PORT_TBL_ADDR + PPE_L2_VP_PORT_TBL_INC * i; -+ ret = regmap_bulk_read(ppe_dev->regmap, reg, -+ port_cfg, ARRAY_SIZE(port_cfg)); -+ -+ if (ret) -+ return ret; -+ -+ PPE_L2_PORT_SET_INVALID_VSI_FWD_EN(port_cfg, true); -+ PPE_L2_PORT_SET_DST_INFO(port_cfg, 0); -+ -+ ret = regmap_bulk_write(ppe_dev->regmap, reg, -+ port_cfg, ARRAY_SIZE(port_cfg)); -+ if (ret) -+ return ret; -+ } -+ -+ for (i = 0; i < PPE_VSI_TBL_ENTRIES; i++) { -+ /* Set the VSI forward membership to include only CPU port0. -+ * FDB learning and forwarding take place only after switchdev -+ * is supported later to create the VSI and join the physical -+ * ports to the VSI port member. -+ */ -+ reg = PPE_VSI_TBL_ADDR + PPE_VSI_TBL_INC * i; -+ ret = regmap_bulk_read(ppe_dev->regmap, reg, -+ vsi_cfg, ARRAY_SIZE(vsi_cfg)); -+ if (ret) -+ return ret; -+ -+ PPE_VSI_SET_MEMBER_PORT_BITMAP(vsi_cfg, BIT(0)); -+ PPE_VSI_SET_UUC_BITMAP(vsi_cfg, BIT(0)); -+ PPE_VSI_SET_UMC_BITMAP(vsi_cfg, BIT(0)); -+ PPE_VSI_SET_BC_BITMAP(vsi_cfg, BIT(0)); -+ PPE_VSI_SET_NEW_ADDR_LRN_EN(vsi_cfg, true); -+ PPE_VSI_SET_NEW_ADDR_FWD_CMD(vsi_cfg, PPE_ACTION_FORWARD); -+ PPE_VSI_SET_STATION_MOVE_LRN_EN(vsi_cfg, true); -+ PPE_VSI_SET_STATION_MOVE_FWD_CMD(vsi_cfg, PPE_ACTION_FORWARD); -+ -+ ret = regmap_bulk_write(ppe_dev->regmap, reg, -+ vsi_cfg, ARRAY_SIZE(vsi_cfg)); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} -+ - int ppe_hw_config(struct ppe_device *ppe_dev) - { - int ret; -@@ -1920,5 +1994,9 @@ int ppe_hw_config(struct ppe_device *ppe - if (ret) - return ret; - -- return ppe_queues_to_ring_init(ppe_dev); -+ ret = ppe_queues_to_ring_init(ppe_dev); -+ if (ret) -+ return ret; -+ -+ return ppe_bridge_init(ppe_dev); - } ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -@@ -117,6 +117,14 @@ - #define PPE_EG_SERVICE_SET_TX_CNT_EN(tbl_cfg, value) \ - u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_EG_SERVICE_W1_TX_CNT_EN) - -+/* PPE port bridge configuration */ -+#define PPE_PORT_BRIDGE_CTRL_ADDR 0x60300 -+#define PPE_PORT_BRIDGE_CTRL_ENTRIES 8 -+#define PPE_PORT_BRIDGE_CTRL_INC 4 -+#define PPE_PORT_BRIDGE_NEW_LRN_EN BIT(0) -+#define PPE_PORT_BRIDGE_STA_MOVE_LRN_EN BIT(3) -+#define PPE_PORT_BRIDGE_TXMAC_EN BIT(16) -+ - /* PPE port control configurations for the traffic to the multicast queues. */ - #define PPE_MC_MTU_CTRL_TBL_ADDR 0x60a00 - #define PPE_MC_MTU_CTRL_TBL_ENTRIES 8 -@@ -125,6 +133,36 @@ - #define PPE_MC_MTU_CTRL_TBL_MTU_CMD GENMASK(15, 14) - #define PPE_MC_MTU_CTRL_TBL_TX_CNT_EN BIT(16) - -+/* PPE VSI configurations */ -+#define PPE_VSI_TBL_ADDR 0x63800 -+#define PPE_VSI_TBL_ENTRIES 64 -+#define PPE_VSI_TBL_INC 0x10 -+#define PPE_VSI_W0_MEMBER_PORT_BITMAP GENMASK(7, 0) -+#define PPE_VSI_W0_UUC_BITMAP GENMASK(15, 8) -+#define PPE_VSI_W0_UMC_BITMAP GENMASK(23, 16) -+#define PPE_VSI_W0_BC_BITMAP GENMASK(31, 24) -+#define PPE_VSI_W1_NEW_ADDR_LRN_EN BIT(0) -+#define PPE_VSI_W1_NEW_ADDR_FWD_CMD GENMASK(2, 1) -+#define PPE_VSI_W1_STATION_MOVE_LRN_EN BIT(3) -+#define PPE_VSI_W1_STATION_MOVE_FWD_CMD GENMASK(5, 4) -+ -+#define PPE_VSI_SET_MEMBER_PORT_BITMAP(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_VSI_W0_MEMBER_PORT_BITMAP) -+#define PPE_VSI_SET_UUC_BITMAP(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_VSI_W0_UUC_BITMAP) -+#define PPE_VSI_SET_UMC_BITMAP(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_VSI_W0_UMC_BITMAP) -+#define PPE_VSI_SET_BC_BITMAP(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_VSI_W0_BC_BITMAP) -+#define PPE_VSI_SET_NEW_ADDR_LRN_EN(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_VSI_W1_NEW_ADDR_LRN_EN) -+#define PPE_VSI_SET_NEW_ADDR_FWD_CMD(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_VSI_W1_NEW_ADDR_FWD_CMD) -+#define PPE_VSI_SET_STATION_MOVE_LRN_EN(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_VSI_W1_STATION_MOVE_LRN_EN) -+#define PPE_VSI_SET_STATION_MOVE_FWD_CMD(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_VSI_W1_STATION_MOVE_FWD_CMD) -+ - /* PPE port control configurations for the traffic to the unicast queues. */ - #define PPE_MRU_MTU_CTRL_TBL_ADDR 0x65000 - #define PPE_MRU_MTU_CTRL_TBL_ENTRIES 256 -@@ -163,6 +201,18 @@ - #define PPE_IN_L2_SERVICE_TBL_RX_CNT_EN BIT(30) - #define PPE_IN_L2_SERVICE_TBL_TX_CNT_EN BIT(31) - -+/* L2 Port configurations */ -+#define PPE_L2_VP_PORT_TBL_ADDR 0x98000 -+#define PPE_L2_VP_PORT_TBL_ENTRIES 256 -+#define PPE_L2_VP_PORT_TBL_INC 0x10 -+#define PPE_L2_VP_PORT_W0_INVALID_VSI_FWD_EN BIT(0) -+#define PPE_L2_VP_PORT_W0_DST_INFO GENMASK(9, 2) -+ -+#define PPE_L2_PORT_SET_INVALID_VSI_FWD_EN(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_L2_VP_PORT_W0_INVALID_VSI_FWD_EN) -+#define PPE_L2_PORT_SET_DST_INFO(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_L2_VP_PORT_W0_DST_INFO) -+ - /* PPE service code configuration for the tunnel packet. */ - #define PPE_TL_SERVICE_TBL_ADDR 0x306000 - #define PPE_TL_SERVICE_TBL_ENTRIES 256 diff --git a/target/linux/qualcommbe/patches-6.12/0335-net-ethernet-qualcomm-Add-PPE-debugfs-support-for-PP.patch b/target/linux/qualcommbe/patches-6.12/0335-net-ethernet-qualcomm-Add-PPE-debugfs-support-for-PP.patch deleted file mode 100644 index e748bca604..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0335-net-ethernet-qualcomm-Add-PPE-debugfs-support-for-PP.patch +++ /dev/null @@ -1,950 +0,0 @@ -From fc25088f79cccb934d69e563221068589565926f Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 9 Feb 2025 22:29:47 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Add PPE debugfs support for PPE - counters - -The PPE hardware counters maintain counters for packets handled by -the various functional blocks of PPE. They help in tracing the packets -passed through PPE and debugging any packet drops. - -The counters displayed by this debugfs file are ones that are common -for all Ethernet ports, and they do not include the counters that are -specific for a MAC port. Hence they cannot be displayed using ethtool. -The per-MAC counters will be supported using "ethtool -S" along with -the netdevice driver. - -The PPE hardware packet counters are made available through -the debugfs entry "/sys/kernel/debug/ppe/packet_counters". - -Signed-off-by: Luo Jie ---- - drivers/net/ethernet/qualcomm/ppe/Makefile | 2 +- - drivers/net/ethernet/qualcomm/ppe/ppe.c | 11 + - drivers/net/ethernet/qualcomm/ppe/ppe.h | 3 + - .../net/ethernet/qualcomm/ppe/ppe_debugfs.c | 692 ++++++++++++++++++ - .../net/ethernet/qualcomm/ppe/ppe_debugfs.h | 16 + - drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 102 +++ - 6 files changed, 825 insertions(+), 1 deletion(-) - create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe_debugfs.c - create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe_debugfs.h - ---- a/drivers/net/ethernet/qualcomm/ppe/Makefile -+++ b/drivers/net/ethernet/qualcomm/ppe/Makefile -@@ -4,4 +4,4 @@ - # - - obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o --qcom-ppe-objs := ppe.o ppe_config.o -+qcom-ppe-objs := ppe.o ppe_config.o ppe_debugfs.o ---- a/drivers/net/ethernet/qualcomm/ppe/ppe.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.c -@@ -16,6 +16,7 @@ - - #include "ppe.h" - #include "ppe_config.h" -+#include "ppe_debugfs.h" - - #define PPE_PORT_MAX 8 - #define PPE_CLK_RATE 353000000 -@@ -199,11 +200,20 @@ static int qcom_ppe_probe(struct platfor - if (ret) - return dev_err_probe(dev, ret, "PPE HW config failed\n"); - -+ ppe_debugfs_setup(ppe_dev); - platform_set_drvdata(pdev, ppe_dev); - - return 0; - } - -+static void qcom_ppe_remove(struct platform_device *pdev) -+{ -+ struct ppe_device *ppe_dev; -+ -+ ppe_dev = platform_get_drvdata(pdev); -+ ppe_debugfs_teardown(ppe_dev); -+} -+ - static const struct of_device_id qcom_ppe_of_match[] = { - { .compatible = "qcom,ipq9574-ppe" }, - {} -@@ -216,6 +226,7 @@ static struct platform_driver qcom_ppe_d - .of_match_table = qcom_ppe_of_match, - }, - .probe = qcom_ppe_probe, -+ .remove = qcom_ppe_remove, - }; - module_platform_driver(qcom_ppe_driver); - ---- a/drivers/net/ethernet/qualcomm/ppe/ppe.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.h -@@ -11,6 +11,7 @@ - - struct device; - struct regmap; -+struct dentry; - - /** - * struct ppe_device - PPE device private data. -@@ -18,6 +19,7 @@ struct regmap; - * @regmap: PPE register map. - * @clk_rate: PPE clock rate. - * @num_ports: Number of PPE ports. -+ * @debugfs_root: Debugfs root entry. - * @num_icc_paths: Number of interconnect paths. - * @icc_paths: Interconnect path array. - * -@@ -30,6 +32,7 @@ struct ppe_device { - struct regmap *regmap; - unsigned long clk_rate; - unsigned int num_ports; -+ struct dentry *debugfs_root; - unsigned int num_icc_paths; - struct icc_bulk_data icc_paths[] __counted_by(num_icc_paths); - }; ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_debugfs.c -@@ -0,0 +1,692 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+/* PPE debugfs routines for display of PPE counters useful for debug. */ -+ -+#include -+#include -+#include -+#include -+ -+#include "ppe.h" -+#include "ppe_config.h" -+#include "ppe_debugfs.h" -+#include "ppe_regs.h" -+ -+#define PPE_PKT_CNT_TBL_SIZE 3 -+#define PPE_DROP_PKT_CNT_TBL_SIZE 5 -+ -+#define PPE_W0_PKT_CNT GENMASK(31, 0) -+#define PPE_W2_DROP_PKT_CNT_LOW GENMASK(31, 8) -+#define PPE_W3_DROP_PKT_CNT_HIGH GENMASK(7, 0) -+ -+#define PPE_GET_PKT_CNT(tbl_cnt) \ -+ u32_get_bits(*((u32 *)(tbl_cnt)), PPE_W0_PKT_CNT) -+#define PPE_GET_DROP_PKT_CNT_LOW(tbl_cnt) \ -+ u32_get_bits(*((u32 *)(tbl_cnt) + 0x2), PPE_W2_DROP_PKT_CNT_LOW) -+#define PPE_GET_DROP_PKT_CNT_HIGH(tbl_cnt) \ -+ u32_get_bits(*((u32 *)(tbl_cnt) + 0x3), PPE_W3_DROP_PKT_CNT_HIGH) -+ -+#define PRINT_COUNTER_PREFIX(desc, cnt_type) \ -+ seq_printf(seq, "%-16s %16s", desc, cnt_type) -+ -+#define PRINT_CPU_CODE_COUNTER(cnt, code) \ -+ seq_printf(seq, "%10u(cpucode:%d)", cnt, code) -+ -+#define PRINT_DROP_CODE_COUNTER(cnt, port, code) \ -+ seq_printf(seq, "%10u(port=%d),dropcode:%d", cnt, port, code) -+ -+#define PRINT_SINGLE_COUNTER(tag, cnt, str, index) \ -+do { \ -+ if (!((tag) % 4)) \ -+ seq_printf(seq, "\n%-16s %16s", "", ""); \ -+ seq_printf(seq, "%10u(%s=%04d)", cnt, str, index); \ -+} while (0) -+ -+#define PRINT_TWO_COUNTERS(tag, cnt0, cnt1, str, index) \ -+do { \ -+ if (!((tag) % 4)) \ -+ seq_printf(seq, "\n%-16s %16s", "", ""); \ -+ seq_printf(seq, "%10u/%u(%s=%04d)", cnt0, cnt1, str, index); \ -+} while (0) -+ -+/** -+ * enum ppe_cnt_size_type - PPE counter size type -+ * @PPE_PKT_CNT_SIZE_1WORD: Counter size with single register -+ * @PPE_PKT_CNT_SIZE_3WORD: Counter size with table of 3 words -+ * @PPE_PKT_CNT_SIZE_5WORD: Counter size with table of 5 words -+ * -+ * PPE takes the different register size to record the packet counters. -+ * It uses single register, or register table with 3 words or 5 words. -+ * The counter with table size 5 words also records the drop counter. -+ * There are also some other counter types occupying sizes less than 32 -+ * bits, which is not covered by this enumeration type. -+ */ -+enum ppe_cnt_size_type { -+ PPE_PKT_CNT_SIZE_1WORD, -+ PPE_PKT_CNT_SIZE_3WORD, -+ PPE_PKT_CNT_SIZE_5WORD, -+}; -+ -+static int ppe_pkt_cnt_get(struct ppe_device *ppe_dev, u32 reg, -+ enum ppe_cnt_size_type cnt_type, -+ u32 *cnt, u32 *drop_cnt) -+{ -+ u32 drop_pkt_cnt[PPE_DROP_PKT_CNT_TBL_SIZE]; -+ u32 pkt_cnt[PPE_PKT_CNT_TBL_SIZE]; -+ u32 value; -+ int ret; -+ -+ switch (cnt_type) { -+ case PPE_PKT_CNT_SIZE_1WORD: -+ ret = regmap_read(ppe_dev->regmap, reg, &value); -+ if (ret) -+ return ret; -+ -+ *cnt = value; -+ break; -+ case PPE_PKT_CNT_SIZE_3WORD: -+ ret = regmap_bulk_read(ppe_dev->regmap, reg, -+ pkt_cnt, ARRAY_SIZE(pkt_cnt)); -+ if (ret) -+ return ret; -+ -+ *cnt = PPE_GET_PKT_CNT(pkt_cnt); -+ break; -+ case PPE_PKT_CNT_SIZE_5WORD: -+ ret = regmap_bulk_read(ppe_dev->regmap, reg, -+ drop_pkt_cnt, ARRAY_SIZE(drop_pkt_cnt)); -+ if (ret) -+ return ret; -+ -+ *cnt = PPE_GET_PKT_CNT(drop_pkt_cnt); -+ -+ /* Drop counter with low 24 bits. */ -+ value = PPE_GET_DROP_PKT_CNT_LOW(drop_pkt_cnt); -+ *drop_cnt = FIELD_PREP(GENMASK(23, 0), value); -+ -+ /* Drop counter with high 8 bits. */ -+ value = PPE_GET_DROP_PKT_CNT_HIGH(drop_pkt_cnt); -+ *drop_cnt |= FIELD_PREP(GENMASK(31, 24), value); -+ break; -+ } -+ -+ return 0; -+} -+ -+static void ppe_tbl_pkt_cnt_clear(struct ppe_device *ppe_dev, u32 reg, -+ enum ppe_cnt_size_type cnt_type) -+{ -+ u32 drop_pkt_cnt[PPE_DROP_PKT_CNT_TBL_SIZE] = {}; -+ u32 pkt_cnt[PPE_PKT_CNT_TBL_SIZE] = {}; -+ -+ switch (cnt_type) { -+ case PPE_PKT_CNT_SIZE_1WORD: -+ regmap_write(ppe_dev->regmap, reg, 0); -+ break; -+ case PPE_PKT_CNT_SIZE_3WORD: -+ regmap_bulk_write(ppe_dev->regmap, reg, -+ pkt_cnt, ARRAY_SIZE(pkt_cnt)); -+ break; -+ case PPE_PKT_CNT_SIZE_5WORD: -+ regmap_bulk_write(ppe_dev->regmap, reg, -+ drop_pkt_cnt, ARRAY_SIZE(drop_pkt_cnt)); -+ break; -+ } -+} -+ -+/* The number of packets dropped because of no buffer available, no PPE -+ * buffer assigned to these packets. -+ */ -+static void ppe_port_rx_drop_counter_get(struct ppe_device *ppe_dev, -+ struct seq_file *seq) -+{ -+ u32 reg, drop_cnt = 0; -+ int ret, i, tag = 0; -+ -+ PRINT_COUNTER_PREFIX("PRX_DROP_CNT", "SILENT_DROP:"); -+ for (i = 0; i < PPE_DROP_CNT_TBL_ENTRIES; i++) { -+ reg = PPE_DROP_CNT_TBL_ADDR + i * PPE_DROP_CNT_TBL_INC; -+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD, -+ &drop_cnt, NULL); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ if (drop_cnt > 0) { -+ tag++; -+ PRINT_SINGLE_COUNTER(tag, drop_cnt, "port", i); -+ } -+ } -+ -+ seq_putc(seq, '\n'); -+} -+ -+/* The number of packets dropped because hardware buffers were available -+ * only partially for the packet. -+ */ -+static void ppe_port_rx_bm_drop_counter_get(struct ppe_device *ppe_dev, -+ struct seq_file *seq) -+{ -+ u32 reg, pkt_cnt = 0; -+ int ret, i, tag = 0; -+ -+ PRINT_COUNTER_PREFIX("PRX_BM_DROP_CNT", "OVERFLOW_DROP:"); -+ for (i = 0; i < PPE_DROP_STAT_TBL_ENTRIES; i++) { -+ reg = PPE_DROP_STAT_TBL_ADDR + PPE_DROP_STAT_TBL_INC * i; -+ -+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD, -+ &pkt_cnt, NULL); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ if (pkt_cnt > 0) { -+ tag++; -+ PRINT_SINGLE_COUNTER(tag, pkt_cnt, "port", i); -+ } -+ } -+ -+ seq_putc(seq, '\n'); -+} -+ -+/* The number of currently occupied buffers, that can't be flushed. */ -+static void ppe_port_rx_bm_port_counter_get(struct ppe_device *ppe_dev, -+ struct seq_file *seq) -+{ -+ int used_cnt, react_cnt; -+ int ret, i, tag = 0; -+ u32 reg, val; -+ -+ PRINT_COUNTER_PREFIX("PRX_BM_PORT_CNT", "USED/REACT:"); -+ for (i = 0; i < PPE_BM_USED_CNT_TBL_ENTRIES; i++) { -+ reg = PPE_BM_USED_CNT_TBL_ADDR + i * PPE_BM_USED_CNT_TBL_INC; -+ ret = regmap_read(ppe_dev->regmap, reg, &val); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ /* The number of PPE buffers used for caching the received -+ * packets before the pause frame sent. -+ */ -+ used_cnt = FIELD_GET(PPE_BM_USED_CNT_VAL, val); -+ -+ reg = PPE_BM_REACT_CNT_TBL_ADDR + i * PPE_BM_REACT_CNT_TBL_INC; -+ ret = regmap_read(ppe_dev->regmap, reg, &val); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ /* The number of PPE buffers used for caching the received -+ * packets after pause frame sent out. -+ */ -+ react_cnt = FIELD_GET(PPE_BM_REACT_CNT_VAL, val); -+ -+ if (used_cnt > 0 || react_cnt > 0) { -+ tag++; -+ PRINT_TWO_COUNTERS(tag, used_cnt, react_cnt, "port", i); -+ } -+ } -+ -+ seq_putc(seq, '\n'); -+} -+ -+/* The number of packets processed by the ingress parser module of PPE. */ -+static void ppe_parse_pkt_counter_get(struct ppe_device *ppe_dev, -+ struct seq_file *seq) -+{ -+ u32 reg, cnt = 0, tunnel_cnt = 0; -+ int i, ret, tag = 0; -+ -+ PRINT_COUNTER_PREFIX("IPR_PKT_CNT", "TPRX/IPRX:"); -+ for (i = 0; i < PPE_IPR_PKT_CNT_TBL_ENTRIES; i++) { -+ reg = PPE_TPR_PKT_CNT_TBL_ADDR + i * PPE_TPR_PKT_CNT_TBL_INC; -+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD, -+ &tunnel_cnt, NULL); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ reg = PPE_IPR_PKT_CNT_TBL_ADDR + i * PPE_IPR_PKT_CNT_TBL_INC; -+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD, -+ &cnt, NULL); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ if (tunnel_cnt > 0 || cnt > 0) { -+ tag++; -+ PRINT_TWO_COUNTERS(tag, tunnel_cnt, cnt, "port", i); -+ } -+ } -+ -+ seq_putc(seq, '\n'); -+} -+ -+/* The number of packets received or dropped on the ingress direction. */ -+static void ppe_port_rx_counter_get(struct ppe_device *ppe_dev, -+ struct seq_file *seq) -+{ -+ u32 reg, pkt_cnt = 0, drop_cnt = 0; -+ int ret, i, tag = 0; -+ -+ PRINT_COUNTER_PREFIX("PORT_RX_CNT", "RX/RX_DROP:"); -+ for (i = 0; i < PPE_PHY_PORT_RX_CNT_TBL_ENTRIES; i++) { -+ reg = PPE_PHY_PORT_RX_CNT_TBL_ADDR + PPE_PHY_PORT_RX_CNT_TBL_INC * i; -+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_5WORD, -+ &pkt_cnt, &drop_cnt); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ if (pkt_cnt > 0) { -+ tag++; -+ PRINT_TWO_COUNTERS(tag, pkt_cnt, drop_cnt, "port", i); -+ } -+ } -+ -+ seq_putc(seq, '\n'); -+} -+ -+/* The number of packets received or dropped by the port. */ -+static void ppe_vp_rx_counter_get(struct ppe_device *ppe_dev, -+ struct seq_file *seq) -+{ -+ u32 reg, pkt_cnt = 0, drop_cnt = 0; -+ int ret, i, tag = 0; -+ -+ PRINT_COUNTER_PREFIX("VPORT_RX_CNT", "RX/RX_DROP:"); -+ for (i = 0; i < PPE_PORT_RX_CNT_TBL_ENTRIES; i++) { -+ reg = PPE_PORT_RX_CNT_TBL_ADDR + PPE_PORT_RX_CNT_TBL_INC * i; -+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_5WORD, -+ &pkt_cnt, &drop_cnt); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ if (pkt_cnt > 0) { -+ tag++; -+ PRINT_TWO_COUNTERS(tag, pkt_cnt, drop_cnt, "port", i); -+ } -+ } -+ -+ seq_putc(seq, '\n'); -+} -+ -+/* The number of packets received or dropped by layer 2 processing. */ -+static void ppe_pre_l2_counter_get(struct ppe_device *ppe_dev, -+ struct seq_file *seq) -+{ -+ u32 reg, pkt_cnt = 0, drop_cnt = 0; -+ int ret, i, tag = 0; -+ -+ PRINT_COUNTER_PREFIX("PRE_L2_CNT", "RX/RX_DROP:"); -+ for (i = 0; i < PPE_PRE_L2_CNT_TBL_ENTRIES; i++) { -+ reg = PPE_PRE_L2_CNT_TBL_ADDR + PPE_PRE_L2_CNT_TBL_INC * i; -+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_5WORD, -+ &pkt_cnt, &drop_cnt); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ if (pkt_cnt > 0) { -+ tag++; -+ PRINT_TWO_COUNTERS(tag, pkt_cnt, drop_cnt, "vsi", i); -+ } -+ } -+ -+ seq_putc(seq, '\n'); -+} -+ -+/* The number of VLAN packets received by PPE. */ -+static void ppe_vlan_counter_get(struct ppe_device *ppe_dev, -+ struct seq_file *seq) -+{ -+ u32 reg, pkt_cnt = 0; -+ int ret, i, tag = 0; -+ -+ PRINT_COUNTER_PREFIX("VLAN_CNT", "RX:"); -+ for (i = 0; i < PPE_VLAN_CNT_TBL_ENTRIES; i++) { -+ reg = PPE_VLAN_CNT_TBL_ADDR + PPE_VLAN_CNT_TBL_INC * i; -+ -+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD, -+ &pkt_cnt, NULL); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ if (pkt_cnt > 0) { -+ tag++; -+ PRINT_SINGLE_COUNTER(tag, pkt_cnt, "vsi", i); -+ } -+ } -+ -+ seq_putc(seq, '\n'); -+} -+ -+/* The number of packets handed to CPU by PPE. */ -+static void ppe_cpu_code_counter_get(struct ppe_device *ppe_dev, -+ struct seq_file *seq) -+{ -+ u32 reg, pkt_cnt = 0; -+ int ret, i; -+ -+ PRINT_COUNTER_PREFIX("CPU_CODE_CNT", "CODE:"); -+ for (i = 0; i < PPE_DROP_CPU_CNT_TBL_ENTRIES; i++) { -+ reg = PPE_DROP_CPU_CNT_TBL_ADDR + PPE_DROP_CPU_CNT_TBL_INC * i; -+ -+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD, -+ &pkt_cnt, NULL); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ if (!pkt_cnt) -+ continue; -+ -+ /* There are 256 CPU codes saved in the first 256 entries -+ * of register table, and 128 drop codes for each PPE port -+ * (0-7), the total entries is 256 + 8 * 128. -+ */ -+ if (i < 256) -+ PRINT_CPU_CODE_COUNTER(pkt_cnt, i); -+ else -+ PRINT_DROP_CODE_COUNTER(pkt_cnt, (i - 256) % 8, -+ (i - 256) / 8); -+ seq_putc(seq, '\n'); -+ PRINT_COUNTER_PREFIX("", ""); -+ } -+ -+ seq_putc(seq, '\n'); -+} -+ -+/* The number of packets forwarded by VLAN on the egress direction. */ -+static void ppe_eg_vsi_counter_get(struct ppe_device *ppe_dev, -+ struct seq_file *seq) -+{ -+ u32 reg, pkt_cnt = 0; -+ int ret, i, tag = 0; -+ -+ PRINT_COUNTER_PREFIX("EG_VSI_CNT", "TX:"); -+ for (i = 0; i < PPE_EG_VSI_COUNTER_TBL_ENTRIES; i++) { -+ reg = PPE_EG_VSI_COUNTER_TBL_ADDR + PPE_EG_VSI_COUNTER_TBL_INC * i; -+ -+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD, -+ &pkt_cnt, NULL); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ if (pkt_cnt > 0) { -+ tag++; -+ PRINT_SINGLE_COUNTER(tag, pkt_cnt, "vsi", i); -+ } -+ } -+ -+ seq_putc(seq, '\n'); -+} -+ -+/* The number of packets trasmitted or dropped by port. */ -+static void ppe_vp_tx_counter_get(struct ppe_device *ppe_dev, -+ struct seq_file *seq) -+{ -+ u32 reg, pkt_cnt = 0, drop_cnt = 0; -+ int ret, i, tag = 0; -+ -+ PRINT_COUNTER_PREFIX("VPORT_TX_CNT", "TX/TX_DROP:"); -+ for (i = 0; i < PPE_VPORT_TX_COUNTER_TBL_ENTRIES; i++) { -+ reg = PPE_VPORT_TX_COUNTER_TBL_ADDR + PPE_VPORT_TX_COUNTER_TBL_INC * i; -+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD, -+ &pkt_cnt, NULL); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ reg = PPE_VPORT_TX_DROP_CNT_TBL_ADDR + PPE_VPORT_TX_DROP_CNT_TBL_INC * i; -+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD, -+ &drop_cnt, NULL); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ if (pkt_cnt > 0 || drop_cnt > 0) { -+ tag++; -+ PRINT_TWO_COUNTERS(tag, pkt_cnt, drop_cnt, "port", i); -+ } -+ } -+ -+ seq_putc(seq, '\n'); -+} -+ -+/* The number of packets trasmitted or dropped on the egress direction. */ -+static void ppe_port_tx_counter_get(struct ppe_device *ppe_dev, -+ struct seq_file *seq) -+{ -+ u32 reg, pkt_cnt = 0, drop_cnt = 0; -+ int ret, i, tag = 0; -+ -+ PRINT_COUNTER_PREFIX("PORT_TX_CNT", "TX/TX_DROP:"); -+ for (i = 0; i < PPE_PORT_TX_COUNTER_TBL_ENTRIES; i++) { -+ reg = PPE_PORT_TX_COUNTER_TBL_ADDR + PPE_PORT_TX_COUNTER_TBL_INC * i; -+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD, -+ &pkt_cnt, NULL); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ reg = PPE_PORT_TX_DROP_CNT_TBL_ADDR + PPE_PORT_TX_DROP_CNT_TBL_INC * i; -+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD, -+ &drop_cnt, NULL); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ if (pkt_cnt > 0 || drop_cnt > 0) { -+ tag++; -+ PRINT_TWO_COUNTERS(tag, pkt_cnt, drop_cnt, "port", i); -+ } -+ } -+ -+ seq_putc(seq, '\n'); -+} -+ -+/* The number of packets transmitted or pending by the PPE queue. */ -+static void ppe_queue_tx_counter_get(struct ppe_device *ppe_dev, -+ struct seq_file *seq) -+{ -+ u32 reg, val, pkt_cnt = 0, pend_cnt = 0; -+ int ret, i, tag = 0; -+ -+ PRINT_COUNTER_PREFIX("QUEUE_TX_CNT", "TX/PEND:"); -+ for (i = 0; i < PPE_QUEUE_TX_COUNTER_TBL_ENTRIES; i++) { -+ reg = PPE_QUEUE_TX_COUNTER_TBL_ADDR + PPE_QUEUE_TX_COUNTER_TBL_INC * i; -+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD, -+ &pkt_cnt, NULL); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ if (i < PPE_AC_UNICAST_QUEUE_CFG_TBL_ENTRIES) { -+ reg = PPE_AC_UNICAST_QUEUE_CNT_TBL_ADDR + -+ PPE_AC_UNICAST_QUEUE_CNT_TBL_INC * i; -+ ret = regmap_read(ppe_dev->regmap, reg, &val); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ pend_cnt = FIELD_GET(PPE_AC_UNICAST_QUEUE_CNT_TBL_PEND_CNT, val); -+ } else { -+ reg = PPE_AC_MULTICAST_QUEUE_CNT_TBL_ADDR + -+ PPE_AC_MULTICAST_QUEUE_CNT_TBL_INC * -+ (i - PPE_AC_UNICAST_QUEUE_CFG_TBL_ENTRIES); -+ ret = regmap_read(ppe_dev->regmap, reg, &val); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ pend_cnt = FIELD_GET(PPE_AC_MULTICAST_QUEUE_CNT_TBL_PEND_CNT, val); -+ } -+ -+ if (pkt_cnt > 0 || pend_cnt > 0) { -+ tag++; -+ PRINT_TWO_COUNTERS(tag, pkt_cnt, pend_cnt, "queue", i); -+ } -+ } -+ -+ seq_putc(seq, '\n'); -+} -+ -+/* Display the various packet counters of PPE. */ -+static int ppe_packet_counter_show(struct seq_file *seq, void *v) -+{ -+ struct ppe_device *ppe_dev = seq->private; -+ -+ ppe_port_rx_drop_counter_get(ppe_dev, seq); -+ ppe_port_rx_bm_drop_counter_get(ppe_dev, seq); -+ ppe_port_rx_bm_port_counter_get(ppe_dev, seq); -+ ppe_parse_pkt_counter_get(ppe_dev, seq); -+ ppe_port_rx_counter_get(ppe_dev, seq); -+ ppe_vp_rx_counter_get(ppe_dev, seq); -+ ppe_pre_l2_counter_get(ppe_dev, seq); -+ ppe_vlan_counter_get(ppe_dev, seq); -+ ppe_cpu_code_counter_get(ppe_dev, seq); -+ ppe_eg_vsi_counter_get(ppe_dev, seq); -+ ppe_vp_tx_counter_get(ppe_dev, seq); -+ ppe_port_tx_counter_get(ppe_dev, seq); -+ ppe_queue_tx_counter_get(ppe_dev, seq); -+ -+ return 0; -+} -+ -+static int ppe_packet_counter_open(struct inode *inode, struct file *file) -+{ -+ return single_open(file, ppe_packet_counter_show, inode->i_private); -+} -+ -+static ssize_t ppe_packet_counter_clear(struct file *file, -+ const char __user *buf, -+ size_t count, loff_t *pos) -+{ -+ struct ppe_device *ppe_dev = file_inode(file)->i_private; -+ u32 reg; -+ int i; -+ -+ for (i = 0; i < PPE_DROP_CNT_TBL_ENTRIES; i++) { -+ reg = PPE_DROP_CNT_TBL_ADDR + i * PPE_DROP_CNT_TBL_INC; -+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD); -+ } -+ -+ for (i = 0; i < PPE_DROP_STAT_TBL_ENTRIES; i++) { -+ reg = PPE_DROP_STAT_TBL_ADDR + PPE_DROP_STAT_TBL_INC * i; -+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD); -+ } -+ -+ for (i = 0; i < PPE_IPR_PKT_CNT_TBL_ENTRIES; i++) { -+ reg = PPE_IPR_PKT_CNT_TBL_ADDR + i * PPE_IPR_PKT_CNT_TBL_INC; -+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD); -+ -+ reg = PPE_TPR_PKT_CNT_TBL_ADDR + i * PPE_TPR_PKT_CNT_TBL_INC; -+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD); -+ } -+ -+ for (i = 0; i < PPE_VLAN_CNT_TBL_ENTRIES; i++) { -+ reg = PPE_VLAN_CNT_TBL_ADDR + PPE_VLAN_CNT_TBL_INC * i; -+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD); -+ } -+ -+ for (i = 0; i < PPE_PRE_L2_CNT_TBL_ENTRIES; i++) { -+ reg = PPE_PRE_L2_CNT_TBL_ADDR + PPE_PRE_L2_CNT_TBL_INC * i; -+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_5WORD); -+ } -+ -+ for (i = 0; i < PPE_PORT_TX_COUNTER_TBL_ENTRIES; i++) { -+ reg = PPE_PORT_TX_DROP_CNT_TBL_ADDR + PPE_PORT_TX_DROP_CNT_TBL_INC * i; -+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD); -+ -+ reg = PPE_PORT_TX_COUNTER_TBL_ADDR + PPE_PORT_TX_COUNTER_TBL_INC * i; -+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD); -+ } -+ -+ for (i = 0; i < PPE_EG_VSI_COUNTER_TBL_ENTRIES; i++) { -+ reg = PPE_EG_VSI_COUNTER_TBL_ADDR + PPE_EG_VSI_COUNTER_TBL_INC * i; -+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD); -+ } -+ -+ for (i = 0; i < PPE_VPORT_TX_COUNTER_TBL_ENTRIES; i++) { -+ reg = PPE_VPORT_TX_COUNTER_TBL_ADDR + PPE_VPORT_TX_COUNTER_TBL_INC * i; -+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD); -+ -+ reg = PPE_VPORT_TX_DROP_CNT_TBL_ADDR + PPE_VPORT_TX_DROP_CNT_TBL_INC * i; -+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD); -+ } -+ -+ for (i = 0; i < PPE_QUEUE_TX_COUNTER_TBL_ENTRIES; i++) { -+ reg = PPE_QUEUE_TX_COUNTER_TBL_ADDR + PPE_QUEUE_TX_COUNTER_TBL_INC * i; -+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD); -+ } -+ -+ ppe_tbl_pkt_cnt_clear(ppe_dev, PPE_EPE_DBG_IN_CNT_ADDR, PPE_PKT_CNT_SIZE_1WORD); -+ ppe_tbl_pkt_cnt_clear(ppe_dev, PPE_EPE_DBG_OUT_CNT_ADDR, PPE_PKT_CNT_SIZE_1WORD); -+ -+ for (i = 0; i < PPE_DROP_CPU_CNT_TBL_ENTRIES; i++) { -+ reg = PPE_DROP_CPU_CNT_TBL_ADDR + PPE_DROP_CPU_CNT_TBL_INC * i; -+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD); -+ } -+ -+ for (i = 0; i < PPE_PORT_RX_CNT_TBL_ENTRIES; i++) { -+ reg = PPE_PORT_RX_CNT_TBL_ADDR + PPE_PORT_RX_CNT_TBL_INC * i; -+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_5WORD); -+ } -+ -+ for (i = 0; i < PPE_PHY_PORT_RX_CNT_TBL_ENTRIES; i++) { -+ reg = PPE_PHY_PORT_RX_CNT_TBL_ADDR + PPE_PHY_PORT_RX_CNT_TBL_INC * i; -+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_5WORD); -+ } -+ -+ return count; -+} -+ -+static const struct file_operations ppe_debugfs_packet_counter_fops = { -+ .owner = THIS_MODULE, -+ .open = ppe_packet_counter_open, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = single_release, -+ .write = ppe_packet_counter_clear, -+}; -+ -+void ppe_debugfs_setup(struct ppe_device *ppe_dev) -+{ -+ ppe_dev->debugfs_root = debugfs_create_dir("ppe", NULL); -+ debugfs_create_file("packet_counters", 0444, -+ ppe_dev->debugfs_root, -+ ppe_dev, -+ &ppe_debugfs_packet_counter_fops); -+} -+ -+void ppe_debugfs_teardown(struct ppe_device *ppe_dev) -+{ -+ debugfs_remove_recursive(ppe_dev->debugfs_root); -+ ppe_dev->debugfs_root = NULL; -+} ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_debugfs.h -@@ -0,0 +1,16 @@ -+/* SPDX-License-Identifier: GPL-2.0-only -+ * -+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+/* PPE debugfs counters setup. */ -+ -+#ifndef __PPE_DEBUGFS_H__ -+#define __PPE_DEBUGFS_H__ -+ -+#include "ppe.h" -+ -+void ppe_debugfs_setup(struct ppe_device *ppe_dev); -+void ppe_debugfs_teardown(struct ppe_device *ppe_dev); -+ -+#endif ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -@@ -16,6 +16,39 @@ - #define PPE_BM_SCH_CTRL_SCH_OFFSET GENMASK(14, 8) - #define PPE_BM_SCH_CTRL_SCH_EN BIT(31) - -+/* PPE drop counters. */ -+#define PPE_DROP_CNT_TBL_ADDR 0xb024 -+#define PPE_DROP_CNT_TBL_ENTRIES 8 -+#define PPE_DROP_CNT_TBL_INC 4 -+ -+/* BM port drop counters. */ -+#define PPE_DROP_STAT_TBL_ADDR 0xe000 -+#define PPE_DROP_STAT_TBL_ENTRIES 30 -+#define PPE_DROP_STAT_TBL_INC 0x10 -+ -+#define PPE_EPE_DBG_IN_CNT_ADDR 0x26054 -+#define PPE_EPE_DBG_OUT_CNT_ADDR 0x26070 -+ -+/* Egress VLAN counters. */ -+#define PPE_EG_VSI_COUNTER_TBL_ADDR 0x41000 -+#define PPE_EG_VSI_COUNTER_TBL_ENTRIES 64 -+#define PPE_EG_VSI_COUNTER_TBL_INC 0x10 -+ -+/* Port TX counters. */ -+#define PPE_PORT_TX_COUNTER_TBL_ADDR 0x45000 -+#define PPE_PORT_TX_COUNTER_TBL_ENTRIES 8 -+#define PPE_PORT_TX_COUNTER_TBL_INC 0x10 -+ -+/* Virtual port TX counters. */ -+#define PPE_VPORT_TX_COUNTER_TBL_ADDR 0x47000 -+#define PPE_VPORT_TX_COUNTER_TBL_ENTRIES 256 -+#define PPE_VPORT_TX_COUNTER_TBL_INC 0x10 -+ -+/* Queue counters. */ -+#define PPE_QUEUE_TX_COUNTER_TBL_ADDR 0x4a000 -+#define PPE_QUEUE_TX_COUNTER_TBL_ENTRIES 300 -+#define PPE_QUEUE_TX_COUNTER_TBL_INC 0x10 -+ - /* RSS settings are to calculate the random RSS hash value generated during - * packet receive to ARM cores. This hash is then used to generate the queue - * offset used to determine the queue used to transmit the packet to ARM cores. -@@ -213,6 +246,51 @@ - #define PPE_L2_PORT_SET_DST_INFO(tbl_cfg, value) \ - u32p_replace_bits((u32 *)tbl_cfg, value, PPE_L2_VP_PORT_W0_DST_INFO) - -+/* Port RX and RX drop counters. */ -+#define PPE_PORT_RX_CNT_TBL_ADDR 0x150000 -+#define PPE_PORT_RX_CNT_TBL_ENTRIES 256 -+#define PPE_PORT_RX_CNT_TBL_INC 0x20 -+ -+/* Physical port RX and RX drop counters. */ -+#define PPE_PHY_PORT_RX_CNT_TBL_ADDR 0x156000 -+#define PPE_PHY_PORT_RX_CNT_TBL_ENTRIES 8 -+#define PPE_PHY_PORT_RX_CNT_TBL_INC 0x20 -+ -+/* Counters for the packet to CPU port. */ -+#define PPE_DROP_CPU_CNT_TBL_ADDR 0x160000 -+#define PPE_DROP_CPU_CNT_TBL_ENTRIES 1280 -+#define PPE_DROP_CPU_CNT_TBL_INC 0x10 -+ -+/* VLAN counters. */ -+#define PPE_VLAN_CNT_TBL_ADDR 0x178000 -+#define PPE_VLAN_CNT_TBL_ENTRIES 64 -+#define PPE_VLAN_CNT_TBL_INC 0x10 -+ -+/* PPE L2 counters. */ -+#define PPE_PRE_L2_CNT_TBL_ADDR 0x17c000 -+#define PPE_PRE_L2_CNT_TBL_ENTRIES 64 -+#define PPE_PRE_L2_CNT_TBL_INC 0x20 -+ -+/* Port TX drop counters. */ -+#define PPE_PORT_TX_DROP_CNT_TBL_ADDR 0x17d000 -+#define PPE_PORT_TX_DROP_CNT_TBL_ENTRIES 8 -+#define PPE_PORT_TX_DROP_CNT_TBL_INC 0x10 -+ -+/* Virtual port TX counters. */ -+#define PPE_VPORT_TX_DROP_CNT_TBL_ADDR 0x17e000 -+#define PPE_VPORT_TX_DROP_CNT_TBL_ENTRIES 256 -+#define PPE_VPORT_TX_DROP_CNT_TBL_INC 0x10 -+ -+/* Counters for the tunnel packet. */ -+#define PPE_TPR_PKT_CNT_TBL_ADDR 0x1d0080 -+#define PPE_TPR_PKT_CNT_TBL_ENTRIES 8 -+#define PPE_TPR_PKT_CNT_TBL_INC 4 -+ -+/* Counters for the all packet received. */ -+#define PPE_IPR_PKT_CNT_TBL_ADDR 0x1e0080 -+#define PPE_IPR_PKT_CNT_TBL_ENTRIES 8 -+#define PPE_IPR_PKT_CNT_TBL_INC 4 -+ - /* PPE service code configuration for the tunnel packet. */ - #define PPE_TL_SERVICE_TBL_ADDR 0x306000 - #define PPE_TL_SERVICE_TBL_ENTRIES 256 -@@ -325,6 +403,18 @@ - #define PPE_BM_PORT_GROUP_ID_INC 0x4 - #define PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID GENMASK(1, 0) - -+/* Counters for PPE buffers used for packets cached. */ -+#define PPE_BM_USED_CNT_TBL_ADDR 0x6001c0 -+#define PPE_BM_USED_CNT_TBL_ENTRIES 15 -+#define PPE_BM_USED_CNT_TBL_INC 0x4 -+#define PPE_BM_USED_CNT_VAL GENMASK(10, 0) -+ -+/* Counters for PPE buffers used for packets received after pause frame sent. */ -+#define PPE_BM_REACT_CNT_TBL_ADDR 0x600240 -+#define PPE_BM_REACT_CNT_TBL_ENTRIES 15 -+#define PPE_BM_REACT_CNT_TBL_INC 0x4 -+#define PPE_BM_REACT_CNT_VAL GENMASK(8, 0) -+ - #define PPE_BM_SHARED_GROUP_CFG_ADDR 0x600290 - #define PPE_BM_SHARED_GROUP_CFG_ENTRIES 4 - #define PPE_BM_SHARED_GROUP_CFG_INC 0x4 -@@ -449,6 +539,18 @@ - #define PPE_AC_GRP_SET_BUF_LIMIT(tbl_cfg, value) \ - u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_AC_GRP_W1_BUF_LIMIT) - -+/* Counters for packets handled by unicast queues (0-255). */ -+#define PPE_AC_UNICAST_QUEUE_CNT_TBL_ADDR 0x84e000 -+#define PPE_AC_UNICAST_QUEUE_CNT_TBL_ENTRIES 256 -+#define PPE_AC_UNICAST_QUEUE_CNT_TBL_INC 0x10 -+#define PPE_AC_UNICAST_QUEUE_CNT_TBL_PEND_CNT GENMASK(12, 0) -+ -+/* Counters for packets handled by multicast queues (256-299). */ -+#define PPE_AC_MULTICAST_QUEUE_CNT_TBL_ADDR 0x852000 -+#define PPE_AC_MULTICAST_QUEUE_CNT_TBL_ENTRIES 44 -+#define PPE_AC_MULTICAST_QUEUE_CNT_TBL_INC 0x10 -+#define PPE_AC_MULTICAST_QUEUE_CNT_TBL_PEND_CNT GENMASK(12, 0) -+ - /* Table addresses for per-queue enqueue setting. */ - #define PPE_ENQ_OPR_TBL_ADDR 0x85c000 - #define PPE_ENQ_OPR_TBL_ENTRIES 300 diff --git a/target/linux/qualcommbe/patches-6.12/0336-MAINTAINERS-Add-maintainer-for-Qualcomm-PPE-driver.patch b/target/linux/qualcommbe/patches-6.12/0336-MAINTAINERS-Add-maintainer-for-Qualcomm-PPE-driver.patch deleted file mode 100644 index 852bf522eb..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0336-MAINTAINERS-Add-maintainer-for-Qualcomm-PPE-driver.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 28098c348414fa97531449d4e27ba1587e67c2d9 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 9 Feb 2025 22:29:48 +0800 -Subject: [PATCH] MAINTAINERS: Add maintainer for Qualcomm PPE driver - -Add maintainer entry for PPE (Packet Process Engine) driver -supported for Qualcomm IPQ SoCs. - -Signed-off-by: Luo Jie ---- - MAINTAINERS | 8 ++++++++ - 1 file changed, 8 insertions(+) - ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -19146,6 +19146,14 @@ S: Maintained - F: Documentation/devicetree/bindings/mtd/qcom,nandc.yaml - F: drivers/mtd/nand/raw/qcom_nandc.c - -+QUALCOMM PPE DRIVER -+M: Luo Jie -+L: netdev@vger.kernel.org -+S: Supported -+F: Documentation/devicetree/bindings/net/qcom,ipq9574-ppe.yaml -+F: Documentation/networking/device_drivers/ethernet/qualcomm/ppe/ppe.rst -+F: drivers/net/ethernet/qualcomm/ppe/ -+ - QUALCOMM QSEECOM DRIVER - M: Maximilian Luz - L: linux-arm-msm@vger.kernel.org diff --git a/target/linux/qualcommbe/patches-6.12/0337-net-ethernet-qualcomm-Add-PPE-scheduler-config.patch b/target/linux/qualcommbe/patches-6.12/0337-net-ethernet-qualcomm-Add-PPE-scheduler-config.patch deleted file mode 100644 index d6292f8bf5..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0337-net-ethernet-qualcomm-Add-PPE-scheduler-config.patch +++ /dev/null @@ -1,201 +0,0 @@ -From 93cf3297818ee61607f0a8d1d34e4fb7fcde3cdf Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Tue, 26 Dec 2023 20:18:09 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Add PPE scheduler config - -PPE scheduler config determines the priority of scheduling the -packet. The scheduler config is used for supporting the QoS -offload in PPE hardware. - -Change-Id: I4811bd133074757371775a6a69a1cc3cfaa8d0d0 -Signed-off-by: Luo Jie -Alex G: rebase patch on top of PPE driver submission from 20250209. - Add the ppe_queue_priority_set() function and its - dependencies. They will be used in the edma support in - susequent changes. - ppe_queue_priority_set() used to be part of ppe_api.c, and - is hereby moved to ppe_config.c . -Signed-off-by: Alexandru Gagniuc ---- - .../net/ethernet/qualcomm/ppe/ppe_config.c | 141 ++++++++++++++++++ - .../net/ethernet/qualcomm/ppe/ppe_config.h | 5 + - 2 files changed, 146 insertions(+) - ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -@@ -864,6 +864,51 @@ static int ppe_scheduler_l0_queue_map_se - val); - } - -+/* Get the first level scheduler configuration. */ -+static int ppe_scheduler_l0_queue_map_get(struct ppe_device *ppe_dev, -+ int node_id, int *port, -+ struct ppe_scheduler_cfg *scheduler_cfg) -+{ -+ u32 val, reg; -+ int ret; -+ -+ reg = PPE_L0_FLOW_MAP_TBL_ADDR + node_id * PPE_L0_FLOW_MAP_TBL_INC; -+ ret = regmap_read(ppe_dev->regmap, reg, &val); -+ if (ret) -+ return ret; -+ -+ scheduler_cfg->flow_id = FIELD_GET(PPE_L0_FLOW_MAP_TBL_FLOW_ID, val); -+ scheduler_cfg->pri = FIELD_GET(PPE_L0_FLOW_MAP_TBL_C_PRI, val); -+ scheduler_cfg->drr_node_wt = FIELD_GET(PPE_L0_FLOW_MAP_TBL_C_NODE_WT, val); -+ -+ reg = PPE_L0_C_FLOW_CFG_TBL_ADDR + -+ (scheduler_cfg->flow_id * PPE_QUEUE_SCH_PRI_NUM + scheduler_cfg->pri) * -+ PPE_L0_C_FLOW_CFG_TBL_INC; -+ -+ ret = regmap_read(ppe_dev->regmap, reg, &val); -+ if (ret) -+ return ret; -+ -+ scheduler_cfg->drr_node_id = FIELD_GET(PPE_L0_C_FLOW_CFG_TBL_NODE_ID, val); -+ scheduler_cfg->unit_is_packet = FIELD_GET(PPE_L0_C_FLOW_CFG_TBL_NODE_CREDIT_UNIT, val); -+ -+ reg = PPE_L0_FLOW_PORT_MAP_TBL_ADDR + node_id * PPE_L0_FLOW_PORT_MAP_TBL_INC; -+ ret = regmap_read(ppe_dev->regmap, reg, &val); -+ if (ret) -+ return ret; -+ -+ *port = FIELD_GET(PPE_L0_FLOW_PORT_MAP_TBL_PORT_NUM, val); -+ -+ reg = PPE_L0_COMP_CFG_TBL_ADDR + node_id * PPE_L0_COMP_CFG_TBL_INC; -+ ret = regmap_read(ppe_dev->regmap, reg, &val); -+ if (ret) -+ return ret; -+ -+ scheduler_cfg->frame_mode = FIELD_GET(PPE_L0_COMP_CFG_TBL_NODE_METER_LEN, val); -+ -+ return 0; -+} -+ - /* Set the PPE flow level scheduler configuration. */ - static int ppe_scheduler_l1_queue_map_set(struct ppe_device *ppe_dev, - int node_id, int port, -@@ -916,6 +961,50 @@ static int ppe_scheduler_l1_queue_map_se - return regmap_update_bits(ppe_dev->regmap, reg, PPE_L1_COMP_CFG_TBL_NODE_METER_LEN, val); - } - -+/* Get the second level scheduler configuration. */ -+static int ppe_scheduler_l1_queue_map_get(struct ppe_device *ppe_dev, -+ int node_id, int *port, -+ struct ppe_scheduler_cfg *scheduler_cfg) -+{ -+ u32 val, reg; -+ int ret; -+ -+ reg = PPE_L1_FLOW_MAP_TBL_ADDR + node_id * PPE_L1_FLOW_MAP_TBL_INC; -+ ret = regmap_read(ppe_dev->regmap, reg, &val); -+ if (ret) -+ return ret; -+ -+ scheduler_cfg->flow_id = FIELD_GET(PPE_L1_FLOW_MAP_TBL_FLOW_ID, val); -+ scheduler_cfg->pri = FIELD_GET(PPE_L1_FLOW_MAP_TBL_C_PRI, val); -+ scheduler_cfg->drr_node_wt = FIELD_GET(PPE_L1_FLOW_MAP_TBL_C_NODE_WT, val); -+ -+ reg = PPE_L1_C_FLOW_CFG_TBL_ADDR + -+ (scheduler_cfg->flow_id * PPE_QUEUE_SCH_PRI_NUM + scheduler_cfg->pri) * -+ PPE_L1_C_FLOW_CFG_TBL_INC; -+ ret = regmap_read(ppe_dev->regmap, reg, &val); -+ if (ret) -+ return ret; -+ -+ scheduler_cfg->drr_node_id = FIELD_GET(PPE_L1_C_FLOW_CFG_TBL_NODE_ID, val); -+ scheduler_cfg->unit_is_packet = FIELD_GET(PPE_L1_C_FLOW_CFG_TBL_NODE_CREDIT_UNIT, val); -+ -+ reg = PPE_L1_FLOW_PORT_MAP_TBL_ADDR + node_id * PPE_L1_FLOW_PORT_MAP_TBL_INC; -+ ret = regmap_read(ppe_dev->regmap, reg, &val); -+ if (ret) -+ return ret; -+ -+ *port = FIELD_GET(PPE_L1_FLOW_PORT_MAP_TBL_PORT_NUM, val); -+ -+ reg = PPE_L1_COMP_CFG_TBL_ADDR + node_id * PPE_L1_COMP_CFG_TBL_INC; -+ ret = regmap_read(ppe_dev->regmap, reg, &val); -+ if (ret) -+ return ret; -+ -+ scheduler_cfg->frame_mode = FIELD_GET(PPE_L1_COMP_CFG_TBL_NODE_METER_LEN, val); -+ -+ return 0; -+} -+ - /** - * ppe_queue_scheduler_set - Configure scheduler for PPE hardware queue - * @ppe_dev: PPE device -@@ -942,6 +1031,58 @@ int ppe_queue_scheduler_set(struct ppe_d - } - - /** -+ * ppe_queue_scheduler_get - get QoS scheduler of PPE hardware queue -+ * @ppe_dev: PPE device -+ * @node_id: PPE node ID -+ * @flow_level: Flow level scheduler or queue level scheduler -+ * @port: PPE port ID to get scheduler config -+ * @scheduler_cfg: QoS scheduler configuration -+ * -+ * The hardware QoS function is supported by PPE, the current scheduler -+ * configuration can be acquired based on the queue ID of PPE port. -+ * -+ * Return 0 on success, negative error code on failure. -+ */ -+int ppe_queue_scheduler_get(struct ppe_device *ppe_dev, -+ int node_id, bool flow_level, int *port, -+ struct ppe_scheduler_cfg *scheduler_cfg) -+{ -+ if (flow_level) -+ return ppe_scheduler_l1_queue_map_get(ppe_dev, node_id, -+ port, scheduler_cfg); -+ -+ return ppe_scheduler_l0_queue_map_get(ppe_dev, node_id, -+ port, scheduler_cfg); -+} -+ -+ -+/** -+ * ppe_queue_priority_set - set scheduler priority of PPE hardware queue -+ * @ppe_dev: PPE device -+ * @node_id: PPE hardware node ID, which is either queue ID or flow ID -+ * @priority: Qos scheduler priority -+ * -+ * Configure scheduler priority of PPE hardware queque, the maximum node -+ * ID supported is PPE_QUEUE_ID_NUM added by PPE_FLOW_ID_NUM, queue ID -+ * belongs to level 0, flow ID belongs to level 1 in the packet pipeline. -+ * -+ * Return 0 on success, negative error code on failure. -+ */ -+int ppe_queue_priority_set(struct ppe_device *ppe_dev, -+ int node_id, int priority) -+{ -+ struct ppe_scheduler_cfg sch_cfg; -+ int ret, port, level = 0; -+ -+ ret = ppe_queue_scheduler_get(ppe_dev, node_id, level, &port, &sch_cfg); -+ if (ret) -+ return ret; -+ -+ sch_cfg.pri = priority; -+ return ppe_queue_scheduler_set(ppe_dev, node_id, level, port, sch_cfg); -+} -+ -+/** - * ppe_queue_ucast_base_set - Set PPE unicast queue base ID and profile ID - * @ppe_dev: PPE device - * @queue_dst: PPE queue destination configuration ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h -@@ -291,6 +291,11 @@ int ppe_hw_config(struct ppe_device *ppe - int ppe_queue_scheduler_set(struct ppe_device *ppe_dev, - int node_id, bool flow_level, int port, - struct ppe_scheduler_cfg scheduler_cfg); -+int ppe_queue_scheduler_get(struct ppe_device *ppe_dev, -+ int node_id, bool flow_level, int *port, -+ struct ppe_scheduler_cfg *scheduler_cfg); -+int ppe_queue_priority_set(struct ppe_device *ppe_dev, -+ int queue_id, int priority); - int ppe_queue_ucast_base_set(struct ppe_device *ppe_dev, - struct ppe_queue_ucast_dest queue_dst, - int queue_base, diff --git a/target/linux/qualcommbe/patches-6.12/0338-net-ethernet-qualcomm-Add-phylink-support-for-PPE-MA.patch b/target/linux/qualcommbe/patches-6.12/0338-net-ethernet-qualcomm-Add-phylink-support-for-PPE-MA.patch deleted file mode 100644 index 05b18e820d..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0338-net-ethernet-qualcomm-Add-phylink-support-for-PPE-MA.patch +++ /dev/null @@ -1,1040 +0,0 @@ -From dbb3711ab25ea410ad5286b2f39dccd954cda225 Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Thu, 29 Feb 2024 16:59:53 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Add phylink support for PPE MAC - ports - -Add MAC initialization and phylink functions for PPE MAC ports. - -Change-Id: I39dcba671732392bcfa2e734473fd083989bfbec -Signed-off-by: Lei Wei ---- - drivers/net/ethernet/qualcomm/Kconfig | 3 + - drivers/net/ethernet/qualcomm/ppe/Makefile | 2 +- - drivers/net/ethernet/qualcomm/ppe/ppe.c | 9 + - drivers/net/ethernet/qualcomm/ppe/ppe.h | 2 + - drivers/net/ethernet/qualcomm/ppe/ppe_port.c | 728 +++++++++++++++++++ - drivers/net/ethernet/qualcomm/ppe/ppe_port.h | 76 ++ - drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 124 ++++ - 7 files changed, 943 insertions(+), 1 deletion(-) - create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe_port.c - create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe_port.h - ---- a/drivers/net/ethernet/qualcomm/Kconfig -+++ b/drivers/net/ethernet/qualcomm/Kconfig -@@ -66,6 +66,9 @@ config QCOM_PPE - depends on HAS_IOMEM && OF - depends on COMMON_CLK - select REGMAP_MMIO -+ select PHYLINK -+ select PCS_QCOM_IPQ_UNIPHY -+ select SFP - help - This driver supports the Qualcomm Technologies, Inc. packet - process engine (PPE) available with IPQ SoC. The PPE includes ---- a/drivers/net/ethernet/qualcomm/ppe/Makefile -+++ b/drivers/net/ethernet/qualcomm/ppe/Makefile -@@ -4,4 +4,4 @@ - # - - obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o --qcom-ppe-objs := ppe.o ppe_config.o ppe_debugfs.o -+qcom-ppe-objs := ppe.o ppe_config.o ppe_debugfs.o ppe_port.o ---- a/drivers/net/ethernet/qualcomm/ppe/ppe.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.c -@@ -17,6 +17,7 @@ - #include "ppe.h" - #include "ppe_config.h" - #include "ppe_debugfs.h" -+#include "ppe_port.h" - - #define PPE_PORT_MAX 8 - #define PPE_CLK_RATE 353000000 -@@ -200,6 +201,11 @@ static int qcom_ppe_probe(struct platfor - if (ret) - return dev_err_probe(dev, ret, "PPE HW config failed\n"); - -+ ret = ppe_port_mac_init(ppe_dev); -+ if (ret) -+ return dev_err_probe(dev, ret, -+ "PPE Port MAC initialization failed\n"); -+ - ppe_debugfs_setup(ppe_dev); - platform_set_drvdata(pdev, ppe_dev); - -@@ -212,6 +218,9 @@ static void qcom_ppe_remove(struct platf - - ppe_dev = platform_get_drvdata(pdev); - ppe_debugfs_teardown(ppe_dev); -+ ppe_port_mac_deinit(ppe_dev); -+ -+ platform_set_drvdata(pdev, NULL); - } - - static const struct of_device_id qcom_ppe_of_match[] = { ---- a/drivers/net/ethernet/qualcomm/ppe/ppe.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.h -@@ -20,6 +20,7 @@ struct dentry; - * @clk_rate: PPE clock rate. - * @num_ports: Number of PPE ports. - * @debugfs_root: Debugfs root entry. -+ * @ports: PPE MAC ports. - * @num_icc_paths: Number of interconnect paths. - * @icc_paths: Interconnect path array. - * -@@ -33,6 +34,7 @@ struct ppe_device { - unsigned long clk_rate; - unsigned int num_ports; - struct dentry *debugfs_root; -+ struct ppe_ports *ports; - unsigned int num_icc_paths; - struct icc_bulk_data icc_paths[] __counted_by(num_icc_paths); - }; ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_port.c -@@ -0,0 +1,728 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+/* PPE Port MAC initialization and PPE port MAC functions. */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "ppe.h" -+#include "ppe_port.h" -+#include "ppe_regs.h" -+ -+/* PPE MAC max frame size which including 4bytes FCS */ -+#define PPE_PORT_MAC_MAX_FRAME_SIZE 0x3000 -+ -+/* PPE BM port start for PPE MAC ports */ -+#define PPE_BM_PORT_MAC_START 7 -+ -+/* PPE port clock and reset name */ -+static const char * const ppe_port_clk_rst_name[] = { -+ [PPE_PORT_CLK_RST_MAC] = "mac", -+ [PPE_PORT_CLK_RST_RX] = "rx", -+ [PPE_PORT_CLK_RST_TX] = "tx", -+}; -+ -+/* PPE port and MAC reset */ -+static int ppe_port_mac_reset(struct ppe_port *ppe_port) -+{ -+ struct ppe_device *ppe_dev = ppe_port->ppe_dev; -+ int ret; -+ -+ ret = reset_control_assert(ppe_port->rstcs[PPE_PORT_CLK_RST_MAC]); -+ if (ret) -+ goto error; -+ -+ ret = reset_control_assert(ppe_port->rstcs[PPE_PORT_CLK_RST_RX]); -+ if (ret) -+ goto error; -+ -+ ret = reset_control_assert(ppe_port->rstcs[PPE_PORT_CLK_RST_TX]); -+ if (ret) -+ goto error; -+ -+ /* 150ms delay is required by hardware to reset PPE port and MAC */ -+ msleep(150); -+ -+ ret = reset_control_deassert(ppe_port->rstcs[PPE_PORT_CLK_RST_MAC]); -+ if (ret) -+ goto error; -+ -+ ret = reset_control_deassert(ppe_port->rstcs[PPE_PORT_CLK_RST_RX]); -+ if (ret) -+ goto error; -+ -+ ret = reset_control_deassert(ppe_port->rstcs[PPE_PORT_CLK_RST_TX]); -+ if (ret) -+ goto error; -+ -+ return ret; -+ -+error: -+ dev_err(ppe_dev->dev, "%s: port %d reset fail %d\n", -+ __func__, ppe_port->port_id, ret); -+ return ret; -+} -+ -+/* PPE port MAC configuration for phylink */ -+static void ppe_port_mac_config(struct phylink_config *config, -+ unsigned int mode, -+ const struct phylink_link_state *state) -+{ -+ struct ppe_port *ppe_port = container_of(config, struct ppe_port, -+ phylink_config); -+ struct ppe_device *ppe_dev = ppe_port->ppe_dev; -+ int port = ppe_port->port_id; -+ enum ppe_mac_type mac_type; -+ u32 val, mask; -+ int ret; -+ -+ switch (state->interface) { -+ case PHY_INTERFACE_MODE_2500BASEX: -+ case PHY_INTERFACE_MODE_USXGMII: -+ case PHY_INTERFACE_MODE_10GBASER: -+ case PHY_INTERFACE_MODE_10G_QXGMII: -+ mac_type = PPE_MAC_TYPE_XGMAC; -+ break; -+ case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_PSGMII: -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_1000BASEX: -+ mac_type = PPE_MAC_TYPE_GMAC; -+ break; -+ default: -+ dev_err(ppe_dev->dev, "%s: Unsupport interface %s\n", -+ __func__, phy_modes(state->interface)); -+ return; -+ } -+ -+ /* Reset Port MAC for GMAC */ -+ if (mac_type == PPE_MAC_TYPE_GMAC) { -+ ret = ppe_port_mac_reset(ppe_port); -+ if (ret) -+ goto err_mac_config; -+ } -+ -+ /* Port mux to select GMAC or XGMAC */ -+ mask = PPE_PORT_SEL_XGMAC(port); -+ val = mac_type == PPE_MAC_TYPE_GMAC ? 0 : mask; -+ ret = regmap_update_bits(ppe_dev->regmap, -+ PPE_PORT_MUX_CTRL_ADDR, -+ mask, val); -+ if (ret) -+ goto err_mac_config; -+ -+ ppe_port->mac_type = mac_type; -+ -+ return; -+ -+err_mac_config: -+ dev_err(ppe_dev->dev, "%s: port %d MAC config fail %d\n", -+ __func__, port, ret); -+} -+ -+/* PPE port GMAC link up configuration */ -+static int ppe_port_gmac_link_up(struct ppe_port *ppe_port, int speed, -+ int duplex, bool tx_pause, bool rx_pause) -+{ -+ struct ppe_device *ppe_dev = ppe_port->ppe_dev; -+ int ret, port = ppe_port->port_id; -+ u32 reg, val; -+ -+ /* Set GMAC speed */ -+ switch (speed) { -+ case SPEED_1000: -+ val = GMAC_SPEED_1000; -+ break; -+ case SPEED_100: -+ val = GMAC_SPEED_100; -+ break; -+ case SPEED_10: -+ val = GMAC_SPEED_10; -+ break; -+ default: -+ dev_err(ppe_dev->dev, "%s: Invalid GMAC speed %s\n", -+ __func__, phy_speed_to_str(speed)); -+ return -EINVAL; -+ } -+ -+ reg = PPE_PORT_GMAC_ADDR(port); -+ ret = regmap_update_bits(ppe_dev->regmap, reg + GMAC_SPEED_ADDR, -+ GMAC_SPEED_M, val); -+ if (ret) -+ return ret; -+ -+ /* Set duplex, flow control and enable GMAC */ -+ val = GMAC_TRXEN; -+ if (duplex == DUPLEX_FULL) -+ val |= GMAC_DUPLEX_FULL; -+ if (tx_pause) -+ val |= GMAC_TXFCEN; -+ if (rx_pause) -+ val |= GMAC_RXFCEN; -+ -+ ret = regmap_update_bits(ppe_dev->regmap, reg + GMAC_ENABLE_ADDR, -+ GMAC_ENABLE_ALL, val); -+ -+ return ret; -+} -+ -+/* PPE port XGMAC link up configuration */ -+static int ppe_port_xgmac_link_up(struct ppe_port *ppe_port, -+ phy_interface_t interface, -+ int speed, int duplex, -+ bool tx_pause, bool rx_pause) -+{ -+ struct ppe_device *ppe_dev = ppe_port->ppe_dev; -+ int ret, port = ppe_port->port_id; -+ u32 reg, val; -+ -+ /* Set XGMAC TX speed and enable TX */ -+ switch (speed) { -+ case SPEED_10000: -+ if (interface == PHY_INTERFACE_MODE_USXGMII) -+ val = XGMAC_SPEED_10000_USXGMII; -+ else -+ val = XGMAC_SPEED_10000; -+ break; -+ case SPEED_5000: -+ val = XGMAC_SPEED_5000; -+ break; -+ case SPEED_2500: -+ if (interface == PHY_INTERFACE_MODE_USXGMII || -+ interface == PHY_INTERFACE_MODE_10G_QXGMII) -+ val = XGMAC_SPEED_2500_USXGMII; -+ else -+ val = XGMAC_SPEED_2500; -+ break; -+ case SPEED_1000: -+ val = XGMAC_SPEED_1000; -+ break; -+ case SPEED_100: -+ val = XGMAC_SPEED_100; -+ break; -+ case SPEED_10: -+ val = XGMAC_SPEED_10; -+ break; -+ default: -+ dev_err(ppe_dev->dev, "%s: Invalid XGMAC speed %s\n", -+ __func__, phy_speed_to_str(speed)); -+ return -EINVAL; -+ } -+ -+ reg = PPE_PORT_XGMAC_ADDR(port); -+ val |= XGMAC_TXEN; -+ ret = regmap_update_bits(ppe_dev->regmap, reg + XGMAC_TX_CONFIG_ADDR, -+ XGMAC_SPEED_M | XGMAC_TXEN, val); -+ if (ret) -+ return ret; -+ -+ /* Set XGMAC TX flow control */ -+ val = FIELD_PREP(XGMAC_PAUSE_TIME_M, FIELD_MAX(XGMAC_PAUSE_TIME_M)); -+ val |= tx_pause ? XGMAC_TXFCEN : 0; -+ ret = regmap_update_bits(ppe_dev->regmap, reg + XGMAC_TX_FLOW_CTRL_ADDR, -+ XGMAC_PAUSE_TIME_M | XGMAC_TXFCEN, val); -+ if (ret) -+ return ret; -+ -+ /* Set XGMAC RX flow control */ -+ val = rx_pause ? XGMAC_RXFCEN : 0; -+ ret = regmap_update_bits(ppe_dev->regmap, reg + XGMAC_RX_FLOW_CTRL_ADDR, -+ XGMAC_RXFCEN, val); -+ if (ret) -+ return ret; -+ -+ /* Enable XGMAC RX*/ -+ ret = regmap_update_bits(ppe_dev->regmap, reg + XGMAC_RX_CONFIG_ADDR, -+ XGMAC_RXEN, XGMAC_RXEN); -+ -+ return ret; -+} -+ -+/* PPE port MAC link up configuration for phylink */ -+static void ppe_port_mac_link_up(struct phylink_config *config, -+ struct phy_device *phy, -+ unsigned int mode, -+ phy_interface_t interface, -+ int speed, int duplex, -+ bool tx_pause, bool rx_pause) -+{ -+ struct ppe_port *ppe_port = container_of(config, struct ppe_port, -+ phylink_config); -+ enum ppe_mac_type mac_type = ppe_port->mac_type; -+ struct ppe_device *ppe_dev = ppe_port->ppe_dev; -+ int ret, port = ppe_port->port_id; -+ u32 reg, val; -+ -+ if (mac_type == PPE_MAC_TYPE_GMAC) -+ ret = ppe_port_gmac_link_up(ppe_port, -+ speed, duplex, tx_pause, rx_pause); -+ else -+ ret = ppe_port_xgmac_link_up(ppe_port, interface, -+ speed, duplex, tx_pause, rx_pause); -+ if (ret) -+ goto err_port_mac_link_up; -+ -+ /* Set PPE port BM flow control */ -+ reg = PPE_BM_PORT_FC_MODE_ADDR + -+ PPE_BM_PORT_FC_MODE_INC * (port + PPE_BM_PORT_MAC_START); -+ val = tx_pause ? PPE_BM_PORT_FC_MODE_EN : 0; -+ ret = regmap_update_bits(ppe_dev->regmap, reg, -+ PPE_BM_PORT_FC_MODE_EN, val); -+ if (ret) -+ goto err_port_mac_link_up; -+ -+ /* Enable PPE port TX */ -+ reg = PPE_PORT_BRIDGE_CTRL_ADDR + PPE_PORT_BRIDGE_CTRL_INC * port; -+ ret = regmap_update_bits(ppe_dev->regmap, reg, -+ PPE_PORT_BRIDGE_TXMAC_EN, -+ PPE_PORT_BRIDGE_TXMAC_EN); -+ if (ret) -+ goto err_port_mac_link_up; -+ -+ return; -+ -+err_port_mac_link_up: -+ dev_err(ppe_dev->dev, "%s: port %d link up fail %d\n", -+ __func__, port, ret); -+} -+ -+/* PPE port MAC link down configuration for phylink */ -+static void ppe_port_mac_link_down(struct phylink_config *config, -+ unsigned int mode, -+ phy_interface_t interface) -+{ -+ struct ppe_port *ppe_port = container_of(config, struct ppe_port, -+ phylink_config); -+ enum ppe_mac_type mac_type = ppe_port->mac_type; -+ struct ppe_device *ppe_dev = ppe_port->ppe_dev; -+ int ret, port = ppe_port->port_id; -+ u32 reg; -+ -+ /* Disable PPE port TX */ -+ reg = PPE_PORT_BRIDGE_CTRL_ADDR + PPE_PORT_BRIDGE_CTRL_INC * port; -+ ret = regmap_update_bits(ppe_dev->regmap, reg, -+ PPE_PORT_BRIDGE_TXMAC_EN, 0); -+ if (ret) -+ goto err_port_mac_link_down; -+ -+ /* Disable PPE MAC */ -+ if (mac_type == PPE_MAC_TYPE_GMAC) { -+ reg = PPE_PORT_GMAC_ADDR(port) + GMAC_ENABLE_ADDR; -+ ret = regmap_update_bits(ppe_dev->regmap, reg, GMAC_TRXEN, 0); -+ if (ret) -+ goto err_port_mac_link_down; -+ } else { -+ reg = PPE_PORT_XGMAC_ADDR(port); -+ ret = regmap_update_bits(ppe_dev->regmap, -+ reg + XGMAC_RX_CONFIG_ADDR, -+ XGMAC_RXEN, 0); -+ if (ret) -+ goto err_port_mac_link_down; -+ -+ ret = regmap_update_bits(ppe_dev->regmap, -+ reg + XGMAC_TX_CONFIG_ADDR, -+ XGMAC_TXEN, 0); -+ if (ret) -+ goto err_port_mac_link_down; -+ } -+ -+ return; -+ -+err_port_mac_link_down: -+ dev_err(ppe_dev->dev, "%s: port %d link down fail %d\n", -+ __func__, port, ret); -+} -+ -+/* PPE port MAC PCS selection for phylink */ -+static -+struct phylink_pcs *ppe_port_mac_select_pcs(struct phylink_config *config, -+ phy_interface_t interface) -+{ -+ struct ppe_port *ppe_port = container_of(config, struct ppe_port, -+ phylink_config); -+ struct ppe_device *ppe_dev = ppe_port->ppe_dev; -+ int ret, port = ppe_port->port_id; -+ u32 val; -+ -+ /* PPE port5 can connects with PCS0 or PCS1. In PSGMII -+ * mode, it selects PCS0; otherwise, it selects PCS1. -+ */ -+ if (port == 5) { -+ val = interface == PHY_INTERFACE_MODE_PSGMII ? -+ 0 : PPE_PORT5_SEL_PCS1; -+ ret = regmap_update_bits(ppe_dev->regmap, -+ PPE_PORT_MUX_CTRL_ADDR, -+ PPE_PORT5_SEL_PCS1, val); -+ if (ret) { -+ dev_err(ppe_dev->dev, "%s: port5 select PCS fail %d\n", -+ __func__, ret); -+ return NULL; -+ } -+ } -+ -+ return ppe_port->pcs; -+} -+ -+static const struct phylink_mac_ops ppe_phylink_ops = { -+ .mac_config = ppe_port_mac_config, -+ .mac_link_up = ppe_port_mac_link_up, -+ .mac_link_down = ppe_port_mac_link_down, -+ .mac_select_pcs = ppe_port_mac_select_pcs, -+}; -+ -+/** -+ * ppe_port_phylink_setup() - Set phylink instance for the given PPE port -+ * @ppe_port: PPE port -+ * @netdev: Netdevice -+ * -+ * Description: Wrapper function to help setup phylink for the PPE port -+ * specified by @ppe_port and associated with the net device @netdev. -+ * -+ * Return: 0 upon success or a negative error upon failure. -+ */ -+int ppe_port_phylink_setup(struct ppe_port *ppe_port, struct net_device *netdev) -+{ -+ struct ppe_device *ppe_dev = ppe_port->ppe_dev; -+ struct device_node *pcs_node; -+ int ret; -+ -+ /* Create PCS */ -+ pcs_node = of_parse_phandle(ppe_port->np, "pcs-handle", 0); -+ if (!pcs_node) -+ return -ENODEV; -+ -+ ppe_port->pcs = ipq_pcs_get(pcs_node); -+ of_node_put(pcs_node); -+ if (IS_ERR(ppe_port->pcs)) { -+ dev_err(ppe_dev->dev, "%s: port %d failed to create PCS\n", -+ __func__, ppe_port->port_id); -+ return PTR_ERR(ppe_port->pcs); -+ } -+ -+ /* Port phylink capability */ -+ ppe_port->phylink_config.dev = &netdev->dev; -+ ppe_port->phylink_config.type = PHYLINK_NETDEV; -+ ppe_port->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | -+ MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000 | -+ MAC_2500FD | MAC_5000FD | MAC_10000FD; -+ __set_bit(PHY_INTERFACE_MODE_QSGMII, -+ ppe_port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_PSGMII, -+ ppe_port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_SGMII, -+ ppe_port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_1000BASEX, -+ ppe_port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_2500BASEX, -+ ppe_port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_USXGMII, -+ ppe_port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_10GBASER, -+ ppe_port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_10G_QXGMII, -+ ppe_port->phylink_config.supported_interfaces); -+ -+ /* Create phylink */ -+ ppe_port->phylink = phylink_create(&ppe_port->phylink_config, -+ of_fwnode_handle(ppe_port->np), -+ ppe_port->interface, -+ &ppe_phylink_ops); -+ if (IS_ERR(ppe_port->phylink)) { -+ dev_err(ppe_dev->dev, "%s: port %d failed to create phylink\n", -+ __func__, ppe_port->port_id); -+ ret = PTR_ERR(ppe_port->phylink); -+ goto err_free_pcs; -+ } -+ -+ /* Connect phylink */ -+ ret = phylink_of_phy_connect(ppe_port->phylink, ppe_port->np, 0); -+ if (ret) { -+ dev_err(ppe_dev->dev, "%s: port %d failed to connect phylink\n", -+ __func__, ppe_port->port_id); -+ goto err_free_phylink; -+ } -+ -+ return 0; -+ -+err_free_phylink: -+ phylink_destroy(ppe_port->phylink); -+ ppe_port->phylink = NULL; -+err_free_pcs: -+ ipq_pcs_put(ppe_port->pcs); -+ ppe_port->pcs = NULL; -+ return ret; -+} -+ -+/** -+ * ppe_port_phylink_destroy() - Destroy phylink instance for the given PPE port -+ * @ppe_port: PPE port -+ * -+ * Description: Wrapper function to help destroy phylink for the PPE port -+ * specified by @ppe_port. -+ */ -+void ppe_port_phylink_destroy(struct ppe_port *ppe_port) -+{ -+ /* Destroy phylink */ -+ if (ppe_port->phylink) { -+ rtnl_lock(); -+ phylink_disconnect_phy(ppe_port->phylink); -+ rtnl_unlock(); -+ phylink_destroy(ppe_port->phylink); -+ ppe_port->phylink = NULL; -+ } -+ -+ /* Destroy PCS */ -+ if (ppe_port->pcs) { -+ ipq_pcs_put(ppe_port->pcs); -+ ppe_port->pcs = NULL; -+ } -+} -+ -+/* PPE port clock initialization */ -+static int ppe_port_clock_init(struct ppe_port *ppe_port) -+{ -+ struct device_node *port_node = ppe_port->np; -+ struct reset_control *rstc; -+ struct clk *clk; -+ int i, j, ret; -+ -+ for (i = 0; i < PPE_PORT_CLK_RST_MAX; i++) { -+ /* Get PPE port resets which will be used to reset PPE -+ * port and MAC. -+ */ -+ rstc = of_reset_control_get_exclusive(port_node, -+ ppe_port_clk_rst_name[i]); -+ if (IS_ERR(rstc)) { -+ ret = PTR_ERR(rstc); -+ goto err_rst; -+ } -+ -+ clk = of_clk_get_by_name(port_node, ppe_port_clk_rst_name[i]); -+ if (IS_ERR(clk)) { -+ ret = PTR_ERR(clk); -+ goto err_clk_get; -+ } -+ -+ ret = clk_prepare_enable(clk); -+ if (ret) -+ goto err_clk_en; -+ -+ ppe_port->clks[i] = clk; -+ ppe_port->rstcs[i] = rstc; -+ } -+ -+ return 0; -+ -+err_clk_en: -+ clk_put(clk); -+err_clk_get: -+ reset_control_put(rstc); -+err_rst: -+ for (j = 0; j < i; j++) { -+ clk_disable_unprepare(ppe_port->clks[j]); -+ clk_put(ppe_port->clks[j]); -+ reset_control_put(ppe_port->rstcs[j]); -+ } -+ -+ return ret; -+} -+ -+/* PPE port clock deinitialization */ -+static void ppe_port_clock_deinit(struct ppe_port *ppe_port) -+{ -+ int i; -+ -+ for (i = 0; i < PPE_PORT_CLK_RST_MAX; i++) { -+ clk_disable_unprepare(ppe_port->clks[i]); -+ clk_put(ppe_port->clks[i]); -+ reset_control_put(ppe_port->rstcs[i]); -+ } -+} -+ -+/* PPE port MAC hardware init configuration */ -+static int ppe_port_mac_hw_init(struct ppe_port *ppe_port) -+{ -+ struct ppe_device *ppe_dev = ppe_port->ppe_dev; -+ int ret, port = ppe_port->port_id; -+ u32 reg, val; -+ -+ /* GMAC RX and TX are initialized as disabled */ -+ reg = PPE_PORT_GMAC_ADDR(port); -+ ret = regmap_update_bits(ppe_dev->regmap, -+ reg + GMAC_ENABLE_ADDR, GMAC_TRXEN, 0); -+ if (ret) -+ return ret; -+ -+ /* GMAC max frame size configuration */ -+ val = FIELD_PREP(GMAC_JUMBO_SIZE_M, PPE_PORT_MAC_MAX_FRAME_SIZE); -+ ret = regmap_update_bits(ppe_dev->regmap, reg + GMAC_JUMBO_SIZE_ADDR, -+ GMAC_JUMBO_SIZE_M, val); -+ if (ret) -+ return ret; -+ -+ val = FIELD_PREP(GMAC_MAXFRAME_SIZE_M, PPE_PORT_MAC_MAX_FRAME_SIZE); -+ val |= FIELD_PREP(GMAC_TX_THD_M, 0x1); -+ ret = regmap_update_bits(ppe_dev->regmap, reg + GMAC_CTRL_ADDR, -+ GMAC_CTRL_MASK, val); -+ if (ret) -+ return ret; -+ -+ val = FIELD_PREP(GMAC_HIGH_IPG_M, 0xc); -+ ret = regmap_update_bits(ppe_dev->regmap, reg + GMAC_DBG_CTRL_ADDR, -+ GMAC_HIGH_IPG_M, val); -+ if (ret) -+ return ret; -+ -+ /* Enable and reset GMAC MIB counters and set as read clear -+ * mode, the GMAC MIB counters will be cleared after reading. -+ */ -+ ret = regmap_update_bits(ppe_dev->regmap, reg + GMAC_MIB_CTRL_ADDR, -+ GMAC_MIB_CTRL_MASK, GMAC_MIB_CTRL_MASK); -+ if (ret) -+ return ret; -+ -+ ret = regmap_update_bits(ppe_dev->regmap, reg + GMAC_MIB_CTRL_ADDR, -+ GMAC_MIB_RST, 0); -+ if (ret) -+ return ret; -+ -+ /* XGMAC RX and TX disabled and max frame size configuration */ -+ reg = PPE_PORT_XGMAC_ADDR(port); -+ ret = regmap_update_bits(ppe_dev->regmap, reg + XGMAC_TX_CONFIG_ADDR, -+ XGMAC_TXEN | XGMAC_JD, XGMAC_JD); -+ if (ret) -+ return ret; -+ -+ val = FIELD_PREP(XGMAC_GPSL_M, PPE_PORT_MAC_MAX_FRAME_SIZE); -+ val |= XGMAC_GPSLEN; -+ val |= XGMAC_CST; -+ val |= XGMAC_ACS; -+ ret = regmap_update_bits(ppe_dev->regmap, reg + XGMAC_RX_CONFIG_ADDR, -+ XGMAC_RX_CONFIG_MASK, val); -+ if (ret) -+ return ret; -+ -+ ret = regmap_update_bits(ppe_dev->regmap, reg + XGMAC_WD_TIMEOUT_ADDR, -+ XGMAC_WD_TIMEOUT_MASK, XGMAC_WD_TIMEOUT_VAL); -+ if (ret) -+ return ret; -+ -+ ret = regmap_update_bits(ppe_dev->regmap, reg + XGMAC_PKT_FILTER_ADDR, -+ XGMAC_PKT_FILTER_MASK, XGMAC_PKT_FILTER_VAL); -+ if (ret) -+ return ret; -+ -+ /* Enable and reset XGMAC MIB counters */ -+ ret = regmap_update_bits(ppe_dev->regmap, reg + XGMAC_MMC_CTRL_ADDR, -+ XGMAC_MCF | XGMAC_CNTRST, XGMAC_CNTRST); -+ -+ return ret; -+} -+ -+/** -+ * ppe_port_mac_init() - Initialization of PPE ports for the PPE device -+ * @ppe_dev: PPE device -+ * -+ * Description: Initialize the PPE MAC ports on the PPE device specified -+ * by @ppe_dev. -+ * -+ * Return: 0 upon success or a negative error upon failure. -+ */ -+int ppe_port_mac_init(struct ppe_device *ppe_dev) -+{ -+ struct device_node *ports_node, *port_node; -+ int port, num, ret, j, i = 0; -+ struct ppe_ports *ppe_ports; -+ phy_interface_t phy_mode; -+ -+ ports_node = of_get_child_by_name(ppe_dev->dev->of_node, -+ "ethernet-ports"); -+ if (!ports_node) { -+ dev_err(ppe_dev->dev, "Failed to get ports node\n"); -+ return -ENODEV; -+ } -+ -+ num = of_get_available_child_count(ports_node); -+ -+ ppe_ports = devm_kzalloc(ppe_dev->dev, -+ struct_size(ppe_ports, port, num), -+ GFP_KERNEL); -+ if (!ppe_ports) { -+ ret = -ENOMEM; -+ goto err_ports_node; -+ } -+ -+ ppe_dev->ports = ppe_ports; -+ ppe_ports->num = num; -+ -+ for_each_available_child_of_node(ports_node, port_node) { -+ ret = of_property_read_u32(port_node, "reg", &port); -+ if (ret) { -+ dev_err(ppe_dev->dev, "Failed to get port id\n"); -+ goto err_port_node; -+ } -+ -+ ret = of_get_phy_mode(port_node, &phy_mode); -+ if (ret) { -+ dev_err(ppe_dev->dev, "Failed to get phy mode\n"); -+ goto err_port_node; -+ } -+ -+ ppe_ports->port[i].ppe_dev = ppe_dev; -+ ppe_ports->port[i].port_id = port; -+ ppe_ports->port[i].np = port_node; -+ ppe_ports->port[i].interface = phy_mode; -+ -+ ret = ppe_port_clock_init(&ppe_ports->port[i]); -+ if (ret) { -+ dev_err(ppe_dev->dev, "Failed to initialize port clocks\n"); -+ goto err_port_clk; -+ } -+ -+ ret = ppe_port_mac_hw_init(&ppe_ports->port[i]); -+ if (ret) { -+ dev_err(ppe_dev->dev, "Failed to initialize MAC hardware\n"); -+ goto err_port_node; -+ } -+ -+ i++; -+ } -+ -+ of_node_put(ports_node); -+ return 0; -+ -+err_port_clk: -+ for (j = 0; j < i; j++) -+ ppe_port_clock_deinit(&ppe_ports->port[j]); -+err_port_node: -+ of_node_put(port_node); -+err_ports_node: -+ of_node_put(ports_node); -+ return ret; -+} -+ -+/** -+ * ppe_port_mac_deinit() - Deinitialization of PPE ports for the PPE device -+ * @ppe_dev: PPE device -+ * -+ * Description: Deinitialize the PPE MAC ports on the PPE device specified -+ * by @ppe_dev. -+ */ -+void ppe_port_mac_deinit(struct ppe_device *ppe_dev) -+{ -+ struct ppe_port *ppe_port; -+ int i; -+ -+ for (i = 0; i < ppe_dev->ports->num; i++) { -+ ppe_port = &ppe_dev->ports->port[i]; -+ ppe_port_clock_deinit(ppe_port); -+ } -+} ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_port.h -@@ -0,0 +1,76 @@ -+/* SPDX-License-Identifier: GPL-2.0-only -+ * -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#ifndef __PPE_PORT_H__ -+#define __PPE_PORT_H__ -+ -+#include -+ -+/** -+ * enum ppe_port_clk_rst_type - PPE port clock and reset ID type -+ * @PPE_PORT_CLK_RST_MAC: The clock and reset ID for port MAC -+ * @PPE_PORT_CLK_RST_RX: The clock and reset ID for port receive path -+ * @PPE_PORT_CLK_RST_TX: The clock and reset for port transmit path -+ * @PPE_PORT_CLK_RST_MAX: The maximum of port clock and reset -+ */ -+enum ppe_port_clk_rst_type { -+ PPE_PORT_CLK_RST_MAC, -+ PPE_PORT_CLK_RST_RX, -+ PPE_PORT_CLK_RST_TX, -+ PPE_PORT_CLK_RST_MAX, -+}; -+ -+/** -+ * enum ppe_mac_type - PPE MAC type -+ * @PPE_MAC_TYPE_GMAC: GMAC type -+ * @PPE_MAC_TYPE_XGMAC: XGMAC type -+ */ -+enum ppe_mac_type { -+ PPE_MAC_TYPE_GMAC, -+ PPE_MAC_TYPE_XGMAC, -+}; -+ -+/** -+ * struct ppe_port - Private data for each PPE port -+ * @phylink: Linux phylink instance -+ * @phylink_config: Linux phylink configurations -+ * @pcs: Linux phylink PCS instance -+ * @np: Port device tree node -+ * @ppe_dev: Back pointer to PPE device private data -+ * @interface: Port interface mode -+ * @mac_type: Port MAC type, GMAC or XGMAC -+ * @port_id: Port ID -+ * @clks: Port clocks -+ * @rstcs: Port resets -+ */ -+struct ppe_port { -+ struct phylink *phylink; -+ struct phylink_config phylink_config; -+ struct phylink_pcs *pcs; -+ struct device_node *np; -+ struct ppe_device *ppe_dev; -+ phy_interface_t interface; -+ enum ppe_mac_type mac_type; -+ int port_id; -+ struct clk *clks[PPE_PORT_CLK_RST_MAX]; -+ struct reset_control *rstcs[PPE_PORT_CLK_RST_MAX]; -+}; -+ -+/** -+ * struct ppe_ports - Array of PPE ports -+ * @num: Number of PPE ports -+ * @port: Each PPE port private data -+ */ -+struct ppe_ports { -+ unsigned int num; -+ struct ppe_port port[] __counted_by(num); -+}; -+ -+int ppe_port_mac_init(struct ppe_device *ppe_dev); -+void ppe_port_mac_deinit(struct ppe_device *ppe_dev); -+int ppe_port_phylink_setup(struct ppe_port *ppe_port, -+ struct net_device *netdev); -+void ppe_port_phylink_destroy(struct ppe_port *ppe_port); -+#endif ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -@@ -9,6 +9,17 @@ - - #include - -+/* PPE port mux select control register */ -+#define PPE_PORT_MUX_CTRL_ADDR 0x10 -+#define PPE_PORT6_SEL_XGMAC BIT(13) -+#define PPE_PORT5_SEL_XGMAC BIT(12) -+#define PPE_PORT4_SEL_XGMAC BIT(11) -+#define PPE_PORT3_SEL_XGMAC BIT(10) -+#define PPE_PORT2_SEL_XGMAC BIT(9) -+#define PPE_PORT1_SEL_XGMAC BIT(8) -+#define PPE_PORT5_SEL_PCS1 BIT(4) -+#define PPE_PORT_SEL_XGMAC(x) (BIT(8) << ((x) - 1)) -+ - /* PPE scheduler configurations for buffer manager block. */ - #define PPE_BM_SCH_CTRL_ADDR 0xb000 - #define PPE_BM_SCH_CTRL_INC 4 -@@ -556,4 +567,117 @@ - #define PPE_ENQ_OPR_TBL_ENTRIES 300 - #define PPE_ENQ_OPR_TBL_INC 0x10 - #define PPE_ENQ_OPR_TBL_ENQ_DISABLE BIT(0) -+ -+/* PPE GMAC and XGMAC register base address */ -+#define PPE_PORT_GMAC_ADDR(x) (0x001000 + ((x) - 1) * 0x200) -+#define PPE_PORT_XGMAC_ADDR(x) (0x500000 + ((x) - 1) * 0x4000) -+ -+/* GMAC enable register */ -+#define GMAC_ENABLE_ADDR 0x0 -+#define GMAC_TXFCEN BIT(6) -+#define GMAC_RXFCEN BIT(5) -+#define GMAC_DUPLEX_FULL BIT(4) -+#define GMAC_TXEN BIT(1) -+#define GMAC_RXEN BIT(0) -+ -+#define GMAC_TRXEN \ -+ (GMAC_TXEN | GMAC_RXEN) -+#define GMAC_ENABLE_ALL \ -+ (GMAC_TXFCEN | GMAC_RXFCEN | GMAC_DUPLEX_FULL | GMAC_TXEN | GMAC_RXEN) -+ -+/* GMAC speed register */ -+#define GMAC_SPEED_ADDR 0x4 -+#define GMAC_SPEED_M GENMASK(1, 0) -+#define GMAC_SPEED_10 0 -+#define GMAC_SPEED_100 1 -+#define GMAC_SPEED_1000 2 -+ -+/* GMAC control register */ -+#define GMAC_CTRL_ADDR 0x18 -+#define GMAC_TX_THD_M GENMASK(27, 24) -+#define GMAC_MAXFRAME_SIZE_M GENMASK(21, 8) -+#define GMAC_CRS_SEL BIT(6) -+ -+#define GMAC_CTRL_MASK \ -+ (GMAC_TX_THD_M | GMAC_MAXFRAME_SIZE_M | GMAC_CRS_SEL) -+ -+/* GMAC debug control register */ -+#define GMAC_DBG_CTRL_ADDR 0x1c -+#define GMAC_HIGH_IPG_M GENMASK(15, 8) -+ -+/* GMAC jumbo size register */ -+#define GMAC_JUMBO_SIZE_ADDR 0x30 -+#define GMAC_JUMBO_SIZE_M GENMASK(13, 0) -+ -+/* GMAC MIB control register */ -+#define GMAC_MIB_CTRL_ADDR 0x34 -+#define GMAC_MIB_RD_CLR BIT(2) -+#define GMAC_MIB_RST BIT(1) -+#define GMAC_MIB_EN BIT(0) -+ -+#define GMAC_MIB_CTRL_MASK \ -+ (GMAC_MIB_RD_CLR | GMAC_MIB_RST | GMAC_MIB_EN) -+ -+/* XGMAC TX configuration register */ -+#define XGMAC_TX_CONFIG_ADDR 0x0 -+#define XGMAC_SPEED_M GENMASK(31, 29) -+#define XGMAC_SPEED_10000_USXGMII FIELD_PREP(XGMAC_SPEED_M, 4) -+#define XGMAC_SPEED_10000 FIELD_PREP(XGMAC_SPEED_M, 0) -+#define XGMAC_SPEED_5000 FIELD_PREP(XGMAC_SPEED_M, 5) -+#define XGMAC_SPEED_2500_USXGMII FIELD_PREP(XGMAC_SPEED_M, 6) -+#define XGMAC_SPEED_2500 FIELD_PREP(XGMAC_SPEED_M, 2) -+#define XGMAC_SPEED_1000 FIELD_PREP(XGMAC_SPEED_M, 3) -+#define XGMAC_SPEED_100 XGMAC_SPEED_1000 -+#define XGMAC_SPEED_10 XGMAC_SPEED_1000 -+#define XGMAC_JD BIT(16) -+#define XGMAC_TXEN BIT(0) -+ -+/* XGMAC RX configuration register */ -+#define XGMAC_RX_CONFIG_ADDR 0x4 -+#define XGMAC_GPSL_M GENMASK(29, 16) -+#define XGMAC_WD BIT(7) -+#define XGMAC_GPSLEN BIT(6) -+#define XGMAC_CST BIT(2) -+#define XGMAC_ACS BIT(1) -+#define XGMAC_RXEN BIT(0) -+ -+#define XGMAC_RX_CONFIG_MASK \ -+ (XGMAC_GPSL_M | XGMAC_WD | XGMAC_GPSLEN | XGMAC_CST | \ -+ XGMAC_ACS | XGMAC_RXEN) -+ -+/* XGMAC packet filter register */ -+#define XGMAC_PKT_FILTER_ADDR 0x8 -+#define XGMAC_RA BIT(31) -+#define XGMAC_PCF_M GENMASK(7, 6) -+#define XGMAC_PR BIT(0) -+ -+#define XGMAC_PKT_FILTER_MASK \ -+ (XGMAC_RA | XGMAC_PCF_M | XGMAC_PR) -+#define XGMAC_PKT_FILTER_VAL \ -+ (XGMAC_RA | XGMAC_PR | FIELD_PREP(XGMAC_PCF_M, 0x2)) -+ -+/* XGMAC watchdog timeout register */ -+#define XGMAC_WD_TIMEOUT_ADDR 0xc -+#define XGMAC_PWE BIT(8) -+#define XGMAC_WTO_M GENMASK(3, 0) -+ -+#define XGMAC_WD_TIMEOUT_MASK \ -+ (XGMAC_PWE | XGMAC_WTO_M) -+#define XGMAC_WD_TIMEOUT_VAL \ -+ (XGMAC_PWE | FIELD_PREP(XGMAC_WTO_M, 0xb)) -+ -+/* XGMAC TX flow control register */ -+#define XGMAC_TX_FLOW_CTRL_ADDR 0x70 -+#define XGMAC_PAUSE_TIME_M GENMASK(31, 16) -+#define XGMAC_TXFCEN BIT(1) -+ -+/* XGMAC RX flow control register */ -+#define XGMAC_RX_FLOW_CTRL_ADDR 0x90 -+#define XGMAC_RXFCEN BIT(0) -+ -+/* XGMAC management counters control register */ -+#define XGMAC_MMC_CTRL_ADDR 0x800 -+#define XGMAC_MCF BIT(3) -+#define XGMAC_CNTRST BIT(0) -+ - #endif diff --git a/target/linux/qualcommbe/patches-6.12/0339-net-ethernet-qualcomm-Add-PPE-port-MAC-MIB-statistic.patch b/target/linux/qualcommbe/patches-6.12/0339-net-ethernet-qualcomm-Add-PPE-port-MAC-MIB-statistic.patch deleted file mode 100644 index 1430692a6f..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0339-net-ethernet-qualcomm-Add-PPE-port-MAC-MIB-statistic.patch +++ /dev/null @@ -1,673 +0,0 @@ -From dbcc0d01241a1353d8e11e764cf7fcd390ae3f1f Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Thu, 29 Feb 2024 20:16:14 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Add PPE port MAC MIB statistics - functions - -Add PPE port MAC MIB statistics functions which are used by netdev -ops and ethtool. For GMAC, a polling task is scheduled to read the -MIB counters periodically to avoid 32bit register counter overflow. - -Change-Id: Ic20e240061278f77d703f652e1f7d959db8fac37 -Signed-off-by: Lei Wei ---- - drivers/net/ethernet/qualcomm/ppe/ppe_port.c | 465 +++++++++++++++++++ - drivers/net/ethernet/qualcomm/ppe/ppe_port.h | 13 + - drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 91 ++++ - 3 files changed, 569 insertions(+) - ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_port.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_port.c -@@ -23,6 +23,122 @@ - /* PPE BM port start for PPE MAC ports */ - #define PPE_BM_PORT_MAC_START 7 - -+/* Poll interval time to poll GMAC MIBs for overflow protection, -+ * the time should ensure that the 32bit GMAC packet counter -+ * register would not overflow within this time at line rate -+ * speed for 64B packet size. -+ */ -+#define PPE_GMIB_POLL_INTERVAL_MS 120000 -+ -+#define PPE_MAC_MIB_DESC(_s, _o, _n) \ -+ { \ -+ .size = (_s), \ -+ .offset = (_o), \ -+ .name = (_n), \ -+ } -+ -+/* PPE MAC MIB description */ -+struct ppe_mac_mib_info { -+ u32 size; -+ u32 offset; -+ const char *name; -+}; -+ -+/* PPE GMAC MIB statistics type */ -+enum ppe_gmib_stats_type { -+ gmib_rx_broadcast, -+ gmib_rx_pause, -+ gmib_rx_multicast, -+ gmib_rx_fcserr, -+ gmib_rx_alignerr, -+ gmib_rx_runt, -+ gmib_rx_frag, -+ gmib_rx_jumbofcserr, -+ gmib_rx_jumboalignerr, -+ gmib_rx_pkt64, -+ gmib_rx_pkt65to127, -+ gmib_rx_pkt128to255, -+ gmib_rx_pkt256to511, -+ gmib_rx_pkt512to1023, -+ gmib_rx_pkt1024to1518, -+ gmib_rx_pkt1519tomax, -+ gmib_rx_toolong, -+ gmib_rx_bytes_g, -+ gmib_rx_bytes_b, -+ gmib_rx_unicast, -+ gmib_tx_broadcast, -+ gmib_tx_pause, -+ gmib_tx_multicast, -+ gmib_tx_underrun, -+ gmib_tx_pkt64, -+ gmib_tx_pkt65to127, -+ gmib_tx_pkt128to255, -+ gmib_tx_pkt256to511, -+ gmib_tx_pkt512to1023, -+ gmib_tx_pkt1024to1518, -+ gmib_tx_pkt1519tomax, -+ gmib_tx_bytes, -+ gmib_tx_collisions, -+ gmib_tx_abortcol, -+ gmib_tx_multicol, -+ gmib_tx_singlecol, -+ gmib_tx_excdeffer, -+ gmib_tx_deffer, -+ gmib_tx_latecol, -+ gmib_tx_unicast, -+}; -+ -+/* PPE XGMAC MIB statistics type */ -+enum ppe_xgmib_stats_type { -+ xgmib_tx_bytes, -+ xgmib_tx_frames, -+ xgmib_tx_broadcast_g, -+ xgmib_tx_multicast_g, -+ xgmib_tx_pkt64, -+ xgmib_tx_pkt65to127, -+ xgmib_tx_pkt128to255, -+ xgmib_tx_pkt256to511, -+ xgmib_tx_pkt512to1023, -+ xgmib_tx_pkt1024tomax, -+ xgmib_tx_unicast, -+ xgmib_tx_multicast, -+ xgmib_tx_broadcast, -+ xgmib_tx_underflow_err, -+ xgmib_tx_bytes_g, -+ xgmib_tx_frames_g, -+ xgmib_tx_pause, -+ xgmib_tx_vlan_g, -+ xgmib_tx_lpi_usec, -+ xgmib_tx_lpi_tran, -+ xgmib_rx_frames, -+ xgmib_rx_bytes, -+ xgmib_rx_bytes_g, -+ xgmib_rx_broadcast_g, -+ xgmib_rx_multicast_g, -+ xgmib_rx_crc_err, -+ xgmib_rx_runt_err, -+ xgmib_rx_jabber_err, -+ xgmib_rx_undersize_g, -+ xgmib_rx_oversize_g, -+ xgmib_rx_pkt64, -+ xgmib_rx_pkt65to127, -+ xgmib_rx_pkt128to255, -+ xgmib_rx_pkt256to511, -+ xgmib_rx_pkt512to1023, -+ xgmib_rx_pkt1024tomax, -+ xgmib_rx_unicast_g, -+ xgmib_rx_len_err, -+ xgmib_rx_outofrange_err, -+ xgmib_rx_pause, -+ xgmib_rx_fifo_overflow, -+ xgmib_rx_vlan, -+ xgmib_rx_wdog_err, -+ xgmib_rx_lpi_usec, -+ xgmib_rx_lpi_tran, -+ xgmib_rx_drop_frames, -+ xgmib_rx_drop_bytes, -+}; -+ - /* PPE port clock and reset name */ - static const char * const ppe_port_clk_rst_name[] = { - [PPE_PORT_CLK_RST_MAC] = "port_mac", -@@ -30,6 +146,322 @@ static const char * const ppe_port_clk_r - [PPE_PORT_CLK_RST_TX] = "port_tx", - }; - -+/* PPE GMAC MIB statistics description information */ -+static const struct ppe_mac_mib_info gmib_info[] = { -+ PPE_MAC_MIB_DESC(4, GMAC_RXBROAD_ADDR, "rx_broadcast"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXPAUSE_ADDR, "rx_pause"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXMULTI_ADDR, "rx_multicast"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXFCSERR_ADDR, "rx_fcserr"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXALIGNERR_ADDR, "rx_alignerr"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXRUNT_ADDR, "rx_runt"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXFRAG_ADDR, "rx_frag"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXJUMBOFCSERR_ADDR, "rx_jumbofcserr"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXJUMBOALIGNERR_ADDR, "rx_jumboalignerr"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXPKT64_ADDR, "rx_pkt64"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXPKT65TO127_ADDR, "rx_pkt65to127"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXPKT128TO255_ADDR, "rx_pkt128to255"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXPKT256TO511_ADDR, "rx_pkt256to511"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXPKT512TO1023_ADDR, "rx_pkt512to1023"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXPKT1024TO1518_ADDR, "rx_pkt1024to1518"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXPKT1519TOX_ADDR, "rx_pkt1519tomax"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXTOOLONG_ADDR, "rx_toolong"), -+ PPE_MAC_MIB_DESC(8, GMAC_RXBYTE_G_ADDR, "rx_bytes_g"), -+ PPE_MAC_MIB_DESC(8, GMAC_RXBYTE_B_ADDR, "rx_bytes_b"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXUNI_ADDR, "rx_unicast"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXBROAD_ADDR, "tx_broadcast"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXPAUSE_ADDR, "tx_pause"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXMULTI_ADDR, "tx_multicast"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXUNDERRUN_ADDR, "tx_underrun"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXPKT64_ADDR, "tx_pkt64"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXPKT65TO127_ADDR, "tx_pkt65to127"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXPKT128TO255_ADDR, "tx_pkt128to255"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXPKT256TO511_ADDR, "tx_pkt256to511"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXPKT512TO1023_ADDR, "tx_pkt512to1023"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXPKT1024TO1518_ADDR, "tx_pkt1024to1518"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXPKT1519TOX_ADDR, "tx_pkt1519tomax"), -+ PPE_MAC_MIB_DESC(8, GMAC_TXBYTE_ADDR, "tx_bytes"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXCOLLISIONS_ADDR, "tx_collisions"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXABORTCOL_ADDR, "tx_abortcol"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXMULTICOL_ADDR, "tx_multicol"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXSINGLECOL_ADDR, "tx_singlecol"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXEXCESSIVEDEFER_ADDR, "tx_excdeffer"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXDEFER_ADDR, "tx_deffer"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXLATECOL_ADDR, "tx_latecol"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXUNI_ADDR, "tx_unicast"), -+}; -+ -+/* PPE XGMAC MIB statistics description information */ -+static const struct ppe_mac_mib_info xgmib_info[] = { -+ PPE_MAC_MIB_DESC(8, XGMAC_TXBYTE_GB_ADDR, "tx_bytes"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXPKT_GB_ADDR, "tx_frames"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXBROAD_G_ADDR, "tx_broadcast_g"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXMULTI_G_ADDR, "tx_multicast_g"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXPKT64_GB_ADDR, "tx_pkt64"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXPKT65TO127_GB_ADDR, "tx_pkt65to127"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXPKT128TO255_GB_ADDR, "tx_pkt128to255"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXPKT256TO511_GB_ADDR, "tx_pkt256to511"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXPKT512TO1023_GB_ADDR, "tx_pkt512to1023"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXPKT1024TOMAX_GB_ADDR, "tx_pkt1024tomax"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXUNI_GB_ADDR, "tx_unicast"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXMULTI_GB_ADDR, "tx_multicast"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXBROAD_GB_ADDR, "tx_broadcast"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXUNDERFLOW_ERR_ADDR, "tx_underflow_err"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXBYTE_G_ADDR, "tx_bytes_g"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXPKT_G_ADDR, "tx_frames_g"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXPAUSE_ADDR, "tx_pause"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXVLAN_G_ADDR, "tx_vlan_g"), -+ PPE_MAC_MIB_DESC(4, XGMAC_TXLPI_USEC_ADDR, "tx_lpi_usec"), -+ PPE_MAC_MIB_DESC(4, XGMAC_TXLPI_TRAN_ADDR, "tx_lpi_tran"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXPKT_GB_ADDR, "rx_frames"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXBYTE_GB_ADDR, "rx_bytes"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXBYTE_G_ADDR, "rx_bytes_g"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXBROAD_G_ADDR, "rx_broadcast_g"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXMULTI_G_ADDR, "rx_multicast_g"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXCRC_ERR_ADDR, "rx_crc_err"), -+ PPE_MAC_MIB_DESC(4, XGMAC_RXRUNT_ERR_ADDR, "rx_runt_err"), -+ PPE_MAC_MIB_DESC(4, XGMAC_RXJABBER_ERR_ADDR, "rx_jabber_err"), -+ PPE_MAC_MIB_DESC(4, XGMAC_RXUNDERSIZE_G_ADDR, "rx_undersize_g"), -+ PPE_MAC_MIB_DESC(4, XGMAC_RXOVERSIZE_G_ADDR, "rx_oversize_g"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXPKT64_GB_ADDR, "rx_pkt64"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXPKT65TO127_GB_ADDR, "rx_pkt65to127"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXPKT128TO255_GB_ADDR, "rx_pkt128to255"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXPKT256TO511_GB_ADDR, "rx_pkt256to511"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXPKT512TO1023_GB_ADDR, "rx_pkt512to1023"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXPKT1024TOMAX_GB_ADDR, "rx_pkt1024tomax"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXUNI_G_ADDR, "rx_unicast_g"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXLEN_ERR_ADDR, "rx_len_err"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXOUTOFRANGE_ADDR, "rx_outofrange_err"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXPAUSE_ADDR, "rx_pause"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXFIFOOVERFLOW_ADDR, "rx_fifo_overflow"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXVLAN_GB_ADDR, "rx_vlan"), -+ PPE_MAC_MIB_DESC(4, XGMAC_RXWATCHDOG_ERR_ADDR, "rx_wdog_err"), -+ PPE_MAC_MIB_DESC(4, XGMAC_RXLPI_USEC_ADDR, "rx_lpi_usec"), -+ PPE_MAC_MIB_DESC(4, XGMAC_RXLPI_TRAN_ADDR, "rx_lpi_tran"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXDISCARD_GB_ADDR, "rx_drop_frames"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXDISCARDBYTE_GB_ADDR, "rx_drop_bytes"), -+}; -+ -+/* Get GMAC MIBs from registers and accumulate to PPE port GMIB stats array */ -+static void ppe_port_gmib_update(struct ppe_port *ppe_port) -+{ -+ struct ppe_device *ppe_dev = ppe_port->ppe_dev; -+ const struct ppe_mac_mib_info *mib; -+ int port = ppe_port->port_id; -+ u32 reg, val; -+ int i, ret; -+ -+ for (i = 0; i < ARRAY_SIZE(gmib_info); i++) { -+ mib = &gmib_info[i]; -+ reg = PPE_PORT_GMAC_ADDR(port) + mib->offset; -+ -+ ret = regmap_read(ppe_dev->regmap, reg, &val); -+ if (ret) { -+ dev_warn(ppe_dev->dev, "%s: %d\n", __func__, ret); -+ continue; -+ } -+ -+ ppe_port->gmib_stats[i] += val; -+ if (mib->size == 8) { -+ ret = regmap_read(ppe_dev->regmap, reg + 4, &val); -+ if (ret) { -+ dev_warn(ppe_dev->dev, "%s: %d\n", -+ __func__, ret); -+ continue; -+ } -+ -+ ppe_port->gmib_stats[i] += (u64)val << 32; -+ } -+ } -+} -+ -+/* Polling task to read GMIB statistics to avoid GMIB 32bit register overflow */ -+static void ppe_port_gmib_stats_poll(struct work_struct *work) -+{ -+ struct ppe_port *ppe_port = container_of(work, struct ppe_port, -+ gmib_read.work); -+ spin_lock(&ppe_port->gmib_stats_lock); -+ ppe_port_gmib_update(ppe_port); -+ spin_unlock(&ppe_port->gmib_stats_lock); -+ -+ schedule_delayed_work(&ppe_port->gmib_read, -+ msecs_to_jiffies(PPE_GMIB_POLL_INTERVAL_MS)); -+} -+ -+/* Get the XGMAC MIB counter based on the specific MIB stats type */ -+static u64 ppe_port_xgmib_get(struct ppe_port *ppe_port, -+ enum ppe_xgmib_stats_type xgmib_type) -+{ -+ struct ppe_device *ppe_dev = ppe_port->ppe_dev; -+ const struct ppe_mac_mib_info *mib; -+ int port = ppe_port->port_id; -+ u32 reg, val; -+ u64 data = 0; -+ int ret; -+ -+ mib = &xgmib_info[xgmib_type]; -+ reg = PPE_PORT_XGMAC_ADDR(port) + mib->offset; -+ -+ ret = regmap_read(ppe_dev->regmap, reg, &val); -+ if (ret) { -+ dev_warn(ppe_dev->dev, "%s: %d\n", __func__, ret); -+ goto data_return; -+ } -+ -+ data = val; -+ if (mib->size == 8) { -+ ret = regmap_read(ppe_dev->regmap, reg + 4, &val); -+ if (ret) { -+ dev_warn(ppe_dev->dev, "%s: %d\n", __func__, ret); -+ goto data_return; -+ } -+ -+ data |= (u64)val << 32; -+ } -+ -+data_return: -+ return data; -+} -+ -+/** -+ * ppe_port_get_sset_count() - Get PPE port statistics string count -+ * @ppe_port: PPE port -+ * @sset: string set ID -+ * -+ * Description: Get the MAC statistics string count for the PPE port -+ * specified by @ppe_port. -+ * -+ * Return: The count of the statistics string. -+ */ -+int ppe_port_get_sset_count(struct ppe_port *ppe_port, int sset) -+{ -+ if (sset != ETH_SS_STATS) -+ return 0; -+ -+ if (ppe_port->mac_type == PPE_MAC_TYPE_GMAC) -+ return ARRAY_SIZE(gmib_info); -+ else -+ return ARRAY_SIZE(xgmib_info); -+} -+ -+/** -+ * ppe_port_get_strings() - Get PPE port statistics strings -+ * @ppe_port: PPE port -+ * @stringset: string set ID -+ * @data: pointer to statistics strings -+ * -+ * Description: Get the MAC statistics stings for the PPE port -+ * specified by @ppe_port. The strings are stored in the buffer -+ * indicated by @data which used in the ethtool ops. -+ */ -+void ppe_port_get_strings(struct ppe_port *ppe_port, u32 stringset, u8 *data) -+{ -+ int i; -+ -+ if (stringset != ETH_SS_STATS) -+ return; -+ -+ if (ppe_port->mac_type == PPE_MAC_TYPE_GMAC) { -+ for (i = 0; i < ARRAY_SIZE(gmib_info); i++) -+ strscpy(data + i * ETH_GSTRING_LEN, gmib_info[i].name, -+ ETH_GSTRING_LEN); -+ } else { -+ for (i = 0; i < ARRAY_SIZE(xgmib_info); i++) -+ strscpy(data + i * ETH_GSTRING_LEN, xgmib_info[i].name, -+ ETH_GSTRING_LEN); -+ } -+} -+ -+/** -+ * ppe_port_get_ethtool_stats() - Get PPE port ethtool statistics -+ * @ppe_port: PPE port -+ * @data: pointer to statistics data -+ * -+ * Description: Get the MAC statistics for the PPE port specified -+ * by @ppe_port. The statistics are stored in the buffer indicated -+ * by @data which used in the ethtool ops. -+ */ -+void ppe_port_get_ethtool_stats(struct ppe_port *ppe_port, u64 *data) -+{ -+ int i; -+ -+ if (ppe_port->mac_type == PPE_MAC_TYPE_GMAC) { -+ spin_lock(&ppe_port->gmib_stats_lock); -+ -+ ppe_port_gmib_update(ppe_port); -+ for (i = 0; i < ARRAY_SIZE(gmib_info); i++) -+ data[i] = ppe_port->gmib_stats[i]; -+ -+ spin_unlock(&ppe_port->gmib_stats_lock); -+ } else { -+ for (i = 0; i < ARRAY_SIZE(xgmib_info); i++) -+ data[i] = ppe_port_xgmib_get(ppe_port, i); -+ } -+} -+ -+/** -+ * ppe_port_get_stats64() - Get PPE port statistics -+ * @ppe_port: PPE port -+ * @s: statistics pointer -+ * -+ * Description: Get the MAC statistics for the PPE port specified -+ * by @ppe_port. -+ */ -+void ppe_port_get_stats64(struct ppe_port *ppe_port, -+ struct rtnl_link_stats64 *s) -+{ -+ if (ppe_port->mac_type == PPE_MAC_TYPE_GMAC) { -+ u64 *src = ppe_port->gmib_stats; -+ -+ spin_lock(&ppe_port->gmib_stats_lock); -+ -+ ppe_port_gmib_update(ppe_port); -+ -+ s->rx_packets = src[gmib_rx_unicast] + -+ src[gmib_rx_broadcast] + src[gmib_rx_multicast]; -+ -+ s->tx_packets = src[gmib_tx_unicast] + -+ src[gmib_tx_broadcast] + src[gmib_tx_multicast]; -+ -+ s->rx_bytes = src[gmib_rx_bytes_g]; -+ s->tx_bytes = src[gmib_tx_bytes]; -+ s->multicast = src[gmib_rx_multicast]; -+ -+ s->rx_crc_errors = src[gmib_rx_fcserr] + src[gmib_rx_frag]; -+ s->rx_frame_errors = src[gmib_rx_alignerr]; -+ s->rx_errors = s->rx_crc_errors + s->rx_frame_errors; -+ s->rx_dropped = src[gmib_rx_toolong] + s->rx_errors; -+ -+ s->tx_fifo_errors = src[gmib_tx_underrun]; -+ s->tx_aborted_errors = src[gmib_tx_abortcol]; -+ s->tx_errors = s->tx_fifo_errors + s->tx_aborted_errors; -+ s->collisions = src[gmib_tx_collisions]; -+ -+ spin_unlock(&ppe_port->gmib_stats_lock); -+ } else { -+ s->multicast = ppe_port_xgmib_get(ppe_port, xgmib_rx_multicast_g); -+ -+ s->rx_packets = s->multicast; -+ s->rx_packets += ppe_port_xgmib_get(ppe_port, xgmib_rx_unicast_g); -+ s->rx_packets += ppe_port_xgmib_get(ppe_port, xgmib_rx_broadcast_g); -+ -+ s->tx_packets = ppe_port_xgmib_get(ppe_port, xgmib_tx_frames); -+ s->rx_bytes = ppe_port_xgmib_get(ppe_port, xgmib_rx_bytes); -+ s->tx_bytes = ppe_port_xgmib_get(ppe_port, xgmib_tx_bytes); -+ -+ s->rx_crc_errors = ppe_port_xgmib_get(ppe_port, xgmib_rx_crc_err); -+ s->rx_fifo_errors = ppe_port_xgmib_get(ppe_port, xgmib_rx_fifo_overflow); -+ -+ s->rx_length_errors = ppe_port_xgmib_get(ppe_port, xgmib_rx_len_err); -+ s->rx_errors = s->rx_crc_errors + -+ s->rx_fifo_errors + s->rx_length_errors; -+ s->rx_dropped = s->rx_errors; -+ -+ s->tx_fifo_errors = ppe_port_xgmib_get(ppe_port, xgmib_tx_underflow_err); -+ s->tx_errors = s->tx_packets - -+ ppe_port_xgmib_get(ppe_port, xgmib_tx_frames_g); -+ } -+} -+ - /* PPE port and MAC reset */ - static int ppe_port_mac_reset(struct ppe_port *ppe_port) - { -@@ -261,6 +693,9 @@ static void ppe_port_mac_link_up(struct - int ret, port = ppe_port->port_id; - u32 reg, val; - -+ /* Start GMIB statistics polling */ -+ schedule_delayed_work(&ppe_port->gmib_read, 0); -+ - if (mac_type == PPE_MAC_TYPE_GMAC) - ret = ppe_port_gmac_link_up(ppe_port, - speed, duplex, tx_pause, rx_pause); -@@ -306,6 +741,9 @@ static void ppe_port_mac_link_down(struc - int ret, port = ppe_port->port_id; - u32 reg; - -+ /* Stop GMIB statistics polling */ -+ cancel_delayed_work_sync(&ppe_port->gmib_read); -+ - /* Disable PPE port TX */ - reg = PPE_PORT_BRIDGE_CTRL_ADDR + PPE_PORT_BRIDGE_CTRL_INC * port; - ret = regmap_update_bits(ppe_dev->regmap, reg, -@@ -627,6 +1065,27 @@ static int ppe_port_mac_hw_init(struct p - return ret; - } - -+/* PPE port MAC MIB work task initialization */ -+static int ppe_port_mac_mib_work_init(struct ppe_port *ppe_port) -+{ -+ struct ppe_device *ppe_dev = ppe_port->ppe_dev; -+ u64 *gstats; -+ -+ gstats = devm_kzalloc(ppe_dev->dev, -+ sizeof(*gstats) * ARRAY_SIZE(gmib_info), -+ GFP_KERNEL); -+ if (!gstats) -+ return -ENOMEM; -+ -+ ppe_port->gmib_stats = gstats; -+ -+ spin_lock_init(&ppe_port->gmib_stats_lock); -+ INIT_DELAYED_WORK(&ppe_port->gmib_read, -+ ppe_port_gmib_stats_poll); -+ -+ return 0; -+} -+ - /** - * ppe_port_mac_init() - Initialization of PPE ports for the PPE device - * @ppe_dev: PPE device -@@ -693,6 +1152,12 @@ int ppe_port_mac_init(struct ppe_device - goto err_port_node; - } - -+ ret = ppe_port_mac_mib_work_init(&ppe_ports->port[i]); -+ if (ret) { -+ dev_err(ppe_dev->dev, "Failed to initialize MAC MIB work\n"); -+ goto err_port_node; -+ } -+ - i++; - } - ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_port.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_port.h -@@ -8,6 +8,8 @@ - - #include - -+struct rtnl_link_stats64; -+ - /** - * enum ppe_port_clk_rst_type - PPE port clock and reset ID type - * @PPE_PORT_CLK_RST_MAC: The clock and reset ID for port MAC -@@ -44,6 +46,9 @@ enum ppe_mac_type { - * @port_id: Port ID - * @clks: Port clocks - * @rstcs: Port resets -+ * @gmib_read: Delay work task for GMAC MIB statistics polling function -+ * @gmib_stats: GMAC MIB statistics array -+ * @gmib_stats_lock: Lock to protect GMAC MIB statistics - */ - struct ppe_port { - struct phylink *phylink; -@@ -56,6 +61,9 @@ struct ppe_port { - int port_id; - struct clk *clks[PPE_PORT_CLK_RST_MAX]; - struct reset_control *rstcs[PPE_PORT_CLK_RST_MAX]; -+ struct delayed_work gmib_read; -+ u64 *gmib_stats; -+ spinlock_t gmib_stats_lock; /* Protects GMIB stats */ - }; - - /** -@@ -73,4 +81,9 @@ void ppe_port_mac_deinit(struct ppe_devi - int ppe_port_phylink_setup(struct ppe_port *ppe_port, - struct net_device *netdev); - void ppe_port_phylink_destroy(struct ppe_port *ppe_port); -+int ppe_port_get_sset_count(struct ppe_port *ppe_port, int sset); -+void ppe_port_get_strings(struct ppe_port *ppe_port, u32 stringset, u8 *data); -+void ppe_port_get_ethtool_stats(struct ppe_port *ppe_port, u64 *data); -+void ppe_port_get_stats64(struct ppe_port *ppe_port, -+ struct rtnl_link_stats64 *s); - #endif ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -@@ -618,6 +618,48 @@ - #define GMAC_MIB_CTRL_MASK \ - (GMAC_MIB_RD_CLR | GMAC_MIB_RST | GMAC_MIB_EN) - -+/* GMAC MIB counter registers */ -+#define GMAC_RXBROAD_ADDR 0x40 -+#define GMAC_RXPAUSE_ADDR 0x44 -+#define GMAC_RXMULTI_ADDR 0x48 -+#define GMAC_RXFCSERR_ADDR 0x4C -+#define GMAC_RXALIGNERR_ADDR 0x50 -+#define GMAC_RXRUNT_ADDR 0x54 -+#define GMAC_RXFRAG_ADDR 0x58 -+#define GMAC_RXJUMBOFCSERR_ADDR 0x5C -+#define GMAC_RXJUMBOALIGNERR_ADDR 0x60 -+#define GMAC_RXPKT64_ADDR 0x64 -+#define GMAC_RXPKT65TO127_ADDR 0x68 -+#define GMAC_RXPKT128TO255_ADDR 0x6C -+#define GMAC_RXPKT256TO511_ADDR 0x70 -+#define GMAC_RXPKT512TO1023_ADDR 0x74 -+#define GMAC_RXPKT1024TO1518_ADDR 0x78 -+#define GMAC_RXPKT1519TOX_ADDR 0x7C -+#define GMAC_RXTOOLONG_ADDR 0x80 -+#define GMAC_RXBYTE_G_ADDR 0x84 -+#define GMAC_RXBYTE_B_ADDR 0x8C -+#define GMAC_RXUNI_ADDR 0x94 -+#define GMAC_TXBROAD_ADDR 0xA0 -+#define GMAC_TXPAUSE_ADDR 0xA4 -+#define GMAC_TXMULTI_ADDR 0xA8 -+#define GMAC_TXUNDERRUN_ADDR 0xAC -+#define GMAC_TXPKT64_ADDR 0xB0 -+#define GMAC_TXPKT65TO127_ADDR 0xB4 -+#define GMAC_TXPKT128TO255_ADDR 0xB8 -+#define GMAC_TXPKT256TO511_ADDR 0xBC -+#define GMAC_TXPKT512TO1023_ADDR 0xC0 -+#define GMAC_TXPKT1024TO1518_ADDR 0xC4 -+#define GMAC_TXPKT1519TOX_ADDR 0xC8 -+#define GMAC_TXBYTE_ADDR 0xCC -+#define GMAC_TXCOLLISIONS_ADDR 0xD4 -+#define GMAC_TXABORTCOL_ADDR 0xD8 -+#define GMAC_TXMULTICOL_ADDR 0xDC -+#define GMAC_TXSINGLECOL_ADDR 0xE0 -+#define GMAC_TXEXCESSIVEDEFER_ADDR 0xE4 -+#define GMAC_TXDEFER_ADDR 0xE8 -+#define GMAC_TXLATECOL_ADDR 0xEC -+#define GMAC_TXUNI_ADDR 0xF0 -+ - /* XGMAC TX configuration register */ - #define XGMAC_TX_CONFIG_ADDR 0x0 - #define XGMAC_SPEED_M GENMASK(31, 29) -@@ -680,4 +722,53 @@ - #define XGMAC_MCF BIT(3) - #define XGMAC_CNTRST BIT(0) - -+/* XGMAC MIB counter registers */ -+#define XGMAC_TXBYTE_GB_ADDR 0x814 -+#define XGMAC_TXPKT_GB_ADDR 0x81C -+#define XGMAC_TXBROAD_G_ADDR 0x824 -+#define XGMAC_TXMULTI_G_ADDR 0x82C -+#define XGMAC_TXPKT64_GB_ADDR 0x834 -+#define XGMAC_TXPKT65TO127_GB_ADDR 0x83C -+#define XGMAC_TXPKT128TO255_GB_ADDR 0x844 -+#define XGMAC_TXPKT256TO511_GB_ADDR 0x84C -+#define XGMAC_TXPKT512TO1023_GB_ADDR 0x854 -+#define XGMAC_TXPKT1024TOMAX_GB_ADDR 0x85C -+#define XGMAC_TXUNI_GB_ADDR 0x864 -+#define XGMAC_TXMULTI_GB_ADDR 0x86C -+#define XGMAC_TXBROAD_GB_ADDR 0x874 -+#define XGMAC_TXUNDERFLOW_ERR_ADDR 0x87C -+#define XGMAC_TXBYTE_G_ADDR 0x884 -+#define XGMAC_TXPKT_G_ADDR 0x88C -+#define XGMAC_TXPAUSE_ADDR 0x894 -+#define XGMAC_TXVLAN_G_ADDR 0x89C -+#define XGMAC_TXLPI_USEC_ADDR 0x8A4 -+#define XGMAC_TXLPI_TRAN_ADDR 0x8A8 -+#define XGMAC_RXPKT_GB_ADDR 0x900 -+#define XGMAC_RXBYTE_GB_ADDR 0x908 -+#define XGMAC_RXBYTE_G_ADDR 0x910 -+#define XGMAC_RXBROAD_G_ADDR 0x918 -+#define XGMAC_RXMULTI_G_ADDR 0x920 -+#define XGMAC_RXCRC_ERR_ADDR 0x928 -+#define XGMAC_RXRUNT_ERR_ADDR 0x930 -+#define XGMAC_RXJABBER_ERR_ADDR 0x934 -+#define XGMAC_RXUNDERSIZE_G_ADDR 0x938 -+#define XGMAC_RXOVERSIZE_G_ADDR 0x93C -+#define XGMAC_RXPKT64_GB_ADDR 0x940 -+#define XGMAC_RXPKT65TO127_GB_ADDR 0x948 -+#define XGMAC_RXPKT128TO255_GB_ADDR 0x950 -+#define XGMAC_RXPKT256TO511_GB_ADDR 0x958 -+#define XGMAC_RXPKT512TO1023_GB_ADDR 0x960 -+#define XGMAC_RXPKT1024TOMAX_GB_ADDR 0x968 -+#define XGMAC_RXUNI_G_ADDR 0x970 -+#define XGMAC_RXLEN_ERR_ADDR 0x978 -+#define XGMAC_RXOUTOFRANGE_ADDR 0x980 -+#define XGMAC_RXPAUSE_ADDR 0x988 -+#define XGMAC_RXFIFOOVERFLOW_ADDR 0x990 -+#define XGMAC_RXVLAN_GB_ADDR 0x998 -+#define XGMAC_RXWATCHDOG_ERR_ADDR 0x9A0 -+#define XGMAC_RXLPI_USEC_ADDR 0x9A4 -+#define XGMAC_RXLPI_TRAN_ADDR 0x9A8 -+#define XGMAC_RXDISCARD_GB_ADDR 0x9AC -+#define XGMAC_RXDISCARDBYTE_GB_ADDR 0x9B4 -+ - #endif diff --git a/target/linux/qualcommbe/patches-6.12/0340-net-ethernet-qualcomm-Add-PPE-port-MAC-address-and-E.patch b/target/linux/qualcommbe/patches-6.12/0340-net-ethernet-qualcomm-Add-PPE-port-MAC-address-and-E.patch deleted file mode 100644 index 856a1ed4cc..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0340-net-ethernet-qualcomm-Add-PPE-port-MAC-address-and-E.patch +++ /dev/null @@ -1,172 +0,0 @@ -From 55fbbc8ef90df27a16bca1613a793a578b79a384 Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Fri, 1 Mar 2024 13:36:26 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Add PPE port MAC address and EEE - functions - -Add PPE port MAC address set and EEE set API functions which -will be used by netdev ops and ethtool. - -Change-Id: Id2b3b06ae940b3b6f5227d927316329cdf3caeaa -Signed-off-by: Lei Wei -Alex G: use struct ethtool_keee instead of ethtool_eee -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/ethernet/qualcomm/ppe/ppe_port.c | 75 ++++++++++++++++++++ - drivers/net/ethernet/qualcomm/ppe/ppe_port.h | 3 + - drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 29 ++++++++ - 3 files changed, 107 insertions(+) - ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_port.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_port.c -@@ -462,6 +462,81 @@ void ppe_port_get_stats64(struct ppe_por - } - } - -+/** -+ * ppe_port_set_mac_address() - Set PPE port MAC address -+ * @ppe_port: PPE port -+ * @addr: MAC address -+ * -+ * Description: Set MAC address for the given PPE port. -+ * -+ * Return: 0 upon success or a negative error upon failure. -+ */ -+int ppe_port_set_mac_address(struct ppe_port *ppe_port, const u8 *addr) -+{ -+ struct ppe_device *ppe_dev = ppe_port->ppe_dev; -+ int port = ppe_port->port_id; -+ u32 reg, val; -+ int ret; -+ -+ if (ppe_port->mac_type == PPE_MAC_TYPE_GMAC) { -+ reg = PPE_PORT_GMAC_ADDR(port); -+ val = (addr[5] << 8) | addr[4]; -+ ret = regmap_write(ppe_dev->regmap, reg + GMAC_GOL_ADDR0_ADDR, val); -+ if (ret) -+ return ret; -+ -+ val = (addr[0] << 24) | (addr[1] << 16) | -+ (addr[2] << 8) | addr[3]; -+ ret = regmap_write(ppe_dev->regmap, reg + GMAC_GOL_ADDR1_ADDR, val); -+ if (ret) -+ return ret; -+ } else { -+ reg = PPE_PORT_XGMAC_ADDR(port); -+ val = (addr[5] << 8) | addr[4] | XGMAC_ADDR_EN; -+ ret = regmap_write(ppe_dev->regmap, reg + XGMAC_ADDR0_H_ADDR, val); -+ if (ret) -+ return ret; -+ -+ val = (addr[3] << 24) | (addr[2] << 16) | -+ (addr[1] << 8) | addr[0]; -+ ret = regmap_write(ppe_dev->regmap, reg + XGMAC_ADDR0_L_ADDR, val); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+/** -+ * ppe_port_set_mac_eee() - Set EEE configuration for PPE port MAC -+ * @ppe_port: PPE port -+ * @eee: EEE settings -+ * -+ * Description: Set port MAC EEE settings for the given PPE port. -+ * -+ * Return: 0 upon success or a negative error upon failure. -+ */ -+int ppe_port_set_mac_eee(struct ppe_port *ppe_port, struct ethtool_keee *eee) -+{ -+ struct ppe_device *ppe_dev = ppe_port->ppe_dev; -+ int port = ppe_port->port_id; -+ u32 val; -+ int ret; -+ -+ ret = regmap_read(ppe_dev->regmap, PPE_LPI_EN_ADDR, &val); -+ if (ret) -+ return ret; -+ -+ if (eee->tx_lpi_enabled) -+ val |= PPE_LPI_PORT_EN(port); -+ else -+ val &= ~PPE_LPI_PORT_EN(port); -+ -+ ret = regmap_write(ppe_dev->regmap, PPE_LPI_EN_ADDR, val); -+ -+ return ret; -+} -+ - /* PPE port and MAC reset */ - static int ppe_port_mac_reset(struct ppe_port *ppe_port) - { ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_port.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_port.h -@@ -8,6 +8,7 @@ - - #include - -+struct ethtool_keee; - struct rtnl_link_stats64; - - /** -@@ -86,4 +87,6 @@ void ppe_port_get_strings(struct ppe_por - void ppe_port_get_ethtool_stats(struct ppe_port *ppe_port, u64 *data); - void ppe_port_get_stats64(struct ppe_port *ppe_port, - struct rtnl_link_stats64 *s); -+int ppe_port_set_mac_address(struct ppe_port *ppe_port, const u8 *addr); -+int ppe_port_set_mac_eee(struct ppe_port *ppe_port, struct ethtool_keee *eee); - #endif ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -@@ -20,6 +20,16 @@ - #define PPE_PORT5_SEL_PCS1 BIT(4) - #define PPE_PORT_SEL_XGMAC(x) (BIT(8) << ((x) - 1)) - -+/* PPE port LPI enable register */ -+#define PPE_LPI_EN_ADDR 0x400 -+#define PPE_LPI_PORT1_EN BIT(0) -+#define PPE_LPI_PORT2_EN BIT(1) -+#define PPE_LPI_PORT3_EN BIT(2) -+#define PPE_LPI_PORT4_EN BIT(3) -+#define PPE_LPI_PORT5_EN BIT(4) -+#define PPE_LPI_PORT6_EN BIT(5) -+#define PPE_LPI_PORT_EN(x) (BIT(0) << ((x) - 1)) -+ - /* PPE scheduler configurations for buffer manager block. */ - #define PPE_BM_SCH_CTRL_ADDR 0xb000 - #define PPE_BM_SCH_CTRL_INC 4 -@@ -592,6 +602,17 @@ - #define GMAC_SPEED_100 1 - #define GMAC_SPEED_1000 2 - -+/* GMAC MAC address register */ -+#define GMAC_GOL_ADDR0_ADDR 0x8 -+#define GMAC_ADDR_BYTE5 GENMASK(15, 8) -+#define GMAC_ADDR_BYTE4 GENMASK(7, 0) -+ -+#define GMAC_GOL_ADDR1_ADDR 0xC -+#define GMAC_ADDR_BYTE0 GENMASK(31, 24) -+#define GMAC_ADDR_BYTE1 GENMASK(23, 16) -+#define GMAC_ADDR_BYTE2 GENMASK(15, 8) -+#define GMAC_ADDR_BYTE3 GENMASK(7, 0) -+ - /* GMAC control register */ - #define GMAC_CTRL_ADDR 0x18 - #define GMAC_TX_THD_M GENMASK(27, 24) -@@ -717,6 +738,14 @@ - #define XGMAC_RX_FLOW_CTRL_ADDR 0x90 - #define XGMAC_RXFCEN BIT(0) - -+/* XGMAC MAC address register */ -+#define XGMAC_ADDR0_H_ADDR 0x300 -+#define XGMAC_ADDR_EN BIT(31) -+#define XGMAC_ADDRH GENMASK(15, 0) -+ -+#define XGMAC_ADDR0_L_ADDR 0x304 -+#define XGMAC_ADDRL GENMASK(31, 0) -+ - /* XGMAC management counters control register */ - #define XGMAC_MMC_CTRL_ADDR 0x800 - #define XGMAC_MCF BIT(3) diff --git a/target/linux/qualcommbe/patches-6.12/0341-net-ethernet-qualcomm-Add-API-to-configure-PPE-port-.patch b/target/linux/qualcommbe/patches-6.12/0341-net-ethernet-qualcomm-Add-API-to-configure-PPE-port-.patch deleted file mode 100644 index ae81ddb19d..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0341-net-ethernet-qualcomm-Add-API-to-configure-PPE-port-.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 3981aeae5dd43dea94a0ec10f0b2977ebd102560 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Tue, 5 Mar 2024 16:42:56 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Add API to configure PPE port max - frame size - -This function is called when the MTU of an ethernet port is -configured. It limits the size of packet passed through the -ethernet port. - -Change-Id: I2a4dcd04407156d73770d2becbb7cbc0d56b3754 -Signed-off-by: Luo Jie ---- - drivers/net/ethernet/qualcomm/ppe/ppe_port.c | 44 ++++++++++++++++++++ - drivers/net/ethernet/qualcomm/ppe/ppe_port.h | 1 + - 2 files changed, 45 insertions(+) - ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_port.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_port.c -@@ -537,6 +537,50 @@ int ppe_port_set_mac_eee(struct ppe_port - return ret; - } - -+/** -+ * ppe_port_set_maxframe() - Set port maximum frame size -+ * @ppe_port: PPE port structure -+ * @maxframe_size: Maximum frame size supported by PPE port -+ * -+ * Description: Set MTU of network interface specified by @ppe_port. -+ * -+ * Return: 0 upon success or a negative error upon failure. -+ */ -+int ppe_port_set_maxframe(struct ppe_port *ppe_port, int maxframe_size) -+{ -+ struct ppe_device *ppe_dev = ppe_port->ppe_dev; -+ u32 reg, val, mru_mtu_val[3]; -+ int port = ppe_port->port_id; -+ int ret; -+ -+ /* The max frame size should be MTU added by ETH_HLEN in PPE. */ -+ maxframe_size += ETH_HLEN; -+ -+ /* MAC takes cover the FCS for the calculation of frame size. */ -+ if (maxframe_size > PPE_PORT_MAC_MAX_FRAME_SIZE - ETH_FCS_LEN) -+ return -EINVAL; -+ -+ reg = PPE_MC_MTU_CTRL_TBL_ADDR + PPE_MC_MTU_CTRL_TBL_INC * port; -+ val = FIELD_PREP(PPE_MC_MTU_CTRL_TBL_MTU, maxframe_size); -+ ret = regmap_update_bits(ppe_dev->regmap, reg, -+ PPE_MC_MTU_CTRL_TBL_MTU, -+ val); -+ if (ret) -+ return ret; -+ -+ reg = PPE_MRU_MTU_CTRL_TBL_ADDR + PPE_MRU_MTU_CTRL_TBL_INC * port; -+ ret = regmap_bulk_read(ppe_dev->regmap, reg, -+ mru_mtu_val, ARRAY_SIZE(mru_mtu_val)); -+ if (ret) -+ return ret; -+ -+ PPE_MRU_MTU_CTRL_SET_MRU(mru_mtu_val, maxframe_size); -+ PPE_MRU_MTU_CTRL_SET_MTU(mru_mtu_val, maxframe_size); -+ -+ return regmap_bulk_write(ppe_dev->regmap, reg, -+ mru_mtu_val, ARRAY_SIZE(mru_mtu_val)); -+} -+ - /* PPE port and MAC reset */ - static int ppe_port_mac_reset(struct ppe_port *ppe_port) - { ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_port.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_port.h -@@ -89,4 +89,5 @@ void ppe_port_get_stats64(struct ppe_por - struct rtnl_link_stats64 *s); - int ppe_port_set_mac_address(struct ppe_port *ppe_port, const u8 *addr); - int ppe_port_set_mac_eee(struct ppe_port *ppe_port, struct ethtool_keee *eee); -+int ppe_port_set_maxframe(struct ppe_port *ppe_port, int maxframe_size); - #endif diff --git a/target/linux/qualcommbe/patches-6.12/0342-net-ethernet-qualcomm-Add-EDMA-support-for-QCOM-IPQ9.patch b/target/linux/qualcommbe/patches-6.12/0342-net-ethernet-qualcomm-Add-EDMA-support-for-QCOM-IPQ9.patch deleted file mode 100644 index 0160efdacb..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0342-net-ethernet-qualcomm-Add-EDMA-support-for-QCOM-IPQ9.patch +++ /dev/null @@ -1,932 +0,0 @@ -From 00d4f3cb4f5d1e6924151a4551f06b6a82bf0146 Mon Sep 17 00:00:00 2001 -From: Pavithra R -Date: Wed, 28 Feb 2024 11:25:15 +0530 -Subject: [PATCH] net: ethernet: qualcomm: Add EDMA support for QCOM IPQ9574 - chipset. - -Add the infrastructure functions such as Makefile, -EDMA hardware configuration, clock and IRQ initializations. - -Change-Id: I64f65e554e70e9095b0cf3636fec421569ae6895 -Signed-off-by: Pavithra R -Co-developed-by: Suruchi Agarwal -Signed-off-by: Suruchi Agarwal -Alex G: use "ppe_config.h" header instead of "ppe_api.h" - add missing definitions and functions from ppe_api: - - enum ppe_queue_class_type {} - - ppe_edma_queue_offset_config() -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/ethernet/qualcomm/ppe/Makefile | 3 + - drivers/net/ethernet/qualcomm/ppe/edma.c | 480 +++++++++++++++++++ - drivers/net/ethernet/qualcomm/ppe/edma.h | 113 +++++ - drivers/net/ethernet/qualcomm/ppe/ppe.c | 10 +- - drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 253 ++++++++++ - 5 files changed, 858 insertions(+), 1 deletion(-) - create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma.c - create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma.h - ---- a/drivers/net/ethernet/qualcomm/ppe/Makefile -+++ b/drivers/net/ethernet/qualcomm/ppe/Makefile -@@ -5,3 +5,6 @@ - - obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o - qcom-ppe-objs := ppe.o ppe_config.o ppe_debugfs.o ppe_port.o -+ -+#EDMA -+qcom-ppe-objs += edma.o ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/edma.c -@@ -0,0 +1,480 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+ /* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+ /* Qualcomm Ethernet DMA driver setup, HW configuration, clocks and -+ * interrupt initializations. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "edma.h" -+#include "ppe_regs.h" -+ -+#define EDMA_IRQ_NAME_SIZE 32 -+ -+/* Global EDMA context. */ -+struct edma_context *edma_ctx; -+ -+/* Priority to multi-queue mapping. */ -+static u8 edma_pri_map[PPE_QUEUE_INTER_PRI_NUM] = { -+ 0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7}; -+ -+enum edma_clk_id { -+ EDMA_CLK, -+ EDMA_CFG_CLK, -+ EDMA_CLK_MAX -+}; -+ -+static const char * const clock_name[EDMA_CLK_MAX] = { -+ [EDMA_CLK] = "edma", -+ [EDMA_CFG_CLK] = "edma-cfg", -+}; -+ -+/* Rx Fill ring info for IPQ9574. */ -+static struct edma_ring_info ipq9574_rxfill_ring_info = { -+ .max_rings = 8, -+ .ring_start = 4, -+ .num_rings = 4, -+}; -+ -+/* Rx ring info for IPQ9574. */ -+static struct edma_ring_info ipq9574_rx_ring_info = { -+ .max_rings = 24, -+ .ring_start = 20, -+ .num_rings = 4, -+}; -+ -+/* Tx ring info for IPQ9574. */ -+static struct edma_ring_info ipq9574_tx_ring_info = { -+ .max_rings = 32, -+ .ring_start = 8, -+ .num_rings = 24, -+}; -+ -+/* Tx complete ring info for IPQ9574. */ -+static struct edma_ring_info ipq9574_txcmpl_ring_info = { -+ .max_rings = 32, -+ .ring_start = 8, -+ .num_rings = 24, -+}; -+ -+/* HW info for IPQ9574. */ -+static struct edma_hw_info ipq9574_hw_info = { -+ .rxfill = &ipq9574_rxfill_ring_info, -+ .rx = &ipq9574_rx_ring_info, -+ .tx = &ipq9574_tx_ring_info, -+ .txcmpl = &ipq9574_txcmpl_ring_info, -+ .max_ports = 6, -+ .napi_budget_rx = 128, -+ .napi_budget_tx = 512, -+}; -+ -+static int edma_clock_set_and_enable(struct device *dev, -+ const char *id, unsigned long rate) -+{ -+ struct device_node *edma_np; -+ struct clk *clk = NULL; -+ int ret; -+ -+ edma_np = of_get_child_by_name(dev->of_node, "edma"); -+ -+ clk = devm_get_clk_from_child(dev, edma_np, id); -+ if (IS_ERR(clk)) { -+ dev_err(dev, "clk %s get failed\n", id); -+ of_node_put(edma_np); -+ return PTR_ERR(clk); -+ } -+ -+ ret = clk_set_rate(clk, rate); -+ if (ret) { -+ dev_err(dev, "set %lu rate for %s failed\n", rate, id); -+ of_node_put(edma_np); -+ return ret; -+ } -+ -+ ret = clk_prepare_enable(clk); -+ if (ret) { -+ dev_err(dev, "clk %s enable failed\n", id); -+ of_node_put(edma_np); -+ return ret; -+ } -+ -+ of_node_put(edma_np); -+ -+ dev_dbg(dev, "set %lu rate for %s\n", rate, id); -+ -+ return 0; -+} -+ -+static int edma_clock_init(void) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct device *dev = ppe_dev->dev; -+ unsigned long ppe_rate; -+ int ret; -+ -+ ppe_rate = ppe_dev->clk_rate; -+ -+ ret = edma_clock_set_and_enable(dev, clock_name[EDMA_CLK], -+ ppe_rate); -+ if (ret) -+ return ret; -+ -+ ret = edma_clock_set_and_enable(dev, clock_name[EDMA_CFG_CLK], -+ ppe_rate); -+ if (ret) -+ return ret; -+ -+ return 0; -+} -+ -+/** -+ * edma_configure_ucast_prio_map_tbl - Configure unicast priority map table. -+ * -+ * Map int_priority values to priority class and initialize -+ * unicast priority map table for default profile_id. -+ */ -+static int edma_configure_ucast_prio_map_tbl(void) -+{ -+ u8 pri_class, int_pri; -+ int ret = 0; -+ -+ /* Set the priority class value for every possible priority. */ -+ for (int_pri = 0; int_pri < PPE_QUEUE_INTER_PRI_NUM; int_pri++) { -+ pri_class = edma_pri_map[int_pri]; -+ -+ /* Priority offset should be less than maximum supported -+ * queue priority. -+ */ -+ if (pri_class > EDMA_PRI_MAX_PER_CORE - 1) { -+ pr_err("Configured incorrect priority offset: %d\n", -+ pri_class); -+ return -EINVAL; -+ } -+ -+ ret = ppe_edma_queue_offset_config(edma_ctx->ppe_dev, -+ PPE_QUEUE_CLASS_PRIORITY, int_pri, pri_class); -+ -+ if (ret) { -+ pr_err("Failed with error: %d to set queue priority class for int_pri: %d for profile_id: %d\n", -+ ret, int_pri, 0); -+ return ret; -+ } -+ -+ pr_debug("profile_id: %d, int_priority: %d, pri_class: %d\n", -+ 0, int_pri, pri_class); -+ } -+ -+ return ret; -+} -+ -+static int edma_irq_init(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *txcmpl = hw_info->txcmpl; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct edma_ring_info *rx = hw_info->rx; -+ char edma_irq_name[EDMA_IRQ_NAME_SIZE]; -+ struct device *dev = ppe_dev->dev; -+ struct platform_device *pdev; -+ struct device_node *edma_np; -+ u32 i; -+ -+ pdev = to_platform_device(dev); -+ edma_np = of_get_child_by_name(dev->of_node, "edma"); -+ edma_ctx->intr_info.intr_txcmpl = kzalloc((sizeof(*edma_ctx->intr_info.intr_txcmpl) * -+ txcmpl->num_rings), GFP_KERNEL); -+ if (!edma_ctx->intr_info.intr_txcmpl) { -+ of_node_put(edma_np); -+ return -ENOMEM; -+ } -+ -+ /* Get TXCMPL rings IRQ numbers. */ -+ for (i = 0; i < txcmpl->num_rings; i++) { -+ snprintf(edma_irq_name, sizeof(edma_irq_name), "edma_txcmpl_%d", -+ txcmpl->ring_start + i); -+ edma_ctx->intr_info.intr_txcmpl[i] = of_irq_get_byname(edma_np, edma_irq_name); -+ if (edma_ctx->intr_info.intr_txcmpl[i] < 0) { -+ dev_err(dev, "%s: txcmpl_info.intr[%u] irq get failed\n", -+ edma_np->name, i); -+ of_node_put(edma_np); -+ kfree(edma_ctx->intr_info.intr_txcmpl); -+ return edma_ctx->intr_info.intr_txcmpl[i]; -+ } -+ -+ dev_dbg(dev, "%s: intr_info.intr_txcmpl[%u] = %u\n", -+ edma_np->name, i, edma_ctx->intr_info.intr_txcmpl[i]); -+ } -+ -+ edma_ctx->intr_info.intr_rx = kzalloc((sizeof(*edma_ctx->intr_info.intr_rx) * -+ rx->num_rings), GFP_KERNEL); -+ if (!edma_ctx->intr_info.intr_rx) { -+ of_node_put(edma_np); -+ kfree(edma_ctx->intr_info.intr_txcmpl); -+ return -ENOMEM; -+ } -+ -+ /* Get RXDESC rings IRQ numbers. */ -+ for (i = 0; i < rx->num_rings; i++) { -+ snprintf(edma_irq_name, sizeof(edma_irq_name), "edma_rxdesc_%d", -+ rx->ring_start + i); -+ edma_ctx->intr_info.intr_rx[i] = of_irq_get_byname(edma_np, edma_irq_name); -+ if (edma_ctx->intr_info.intr_rx[i] < 0) { -+ dev_err(dev, "%s: rx_queue_map_info.intr[%u] irq get failed\n", -+ edma_np->name, i); -+ of_node_put(edma_np); -+ kfree(edma_ctx->intr_info.intr_rx); -+ kfree(edma_ctx->intr_info.intr_txcmpl); -+ return edma_ctx->intr_info.intr_rx[i]; -+ } -+ -+ dev_dbg(dev, "%s: intr_info.intr_rx[%u] = %u\n", -+ edma_np->name, i, edma_ctx->intr_info.intr_rx[i]); -+ } -+ -+ /* Get misc IRQ number. */ -+ edma_ctx->intr_info.intr_misc = of_irq_get_byname(edma_np, "edma_misc"); -+ if (edma_ctx->intr_info.intr_misc < 0) { -+ dev_err(dev, "%s: misc_intr irq get failed\n", edma_np->name); -+ of_node_put(edma_np); -+ kfree(edma_ctx->intr_info.intr_rx); -+ kfree(edma_ctx->intr_info.intr_txcmpl); -+ return edma_ctx->intr_info.intr_misc; -+ } -+ -+ of_node_put(edma_np); -+ -+ dev_dbg(dev, "%s: misc IRQ:%u\n", edma_np->name, -+ edma_ctx->intr_info.intr_misc); -+ -+ return 0; -+} -+ -+static int edma_hw_reset(void) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct device *dev = ppe_dev->dev; -+ struct reset_control *edma_hw_rst; -+ struct device_node *edma_np; -+ const char *reset_string; -+ u32 count, i; -+ int ret; -+ -+ /* Count and parse reset names from DTSI. */ -+ edma_np = of_get_child_by_name(dev->of_node, "edma"); -+ count = of_property_count_strings(edma_np, "reset-names"); -+ if (count < 0) { -+ dev_err(dev, "EDMA reset entry not found\n"); -+ of_node_put(edma_np); -+ return -EINVAL; -+ } -+ -+ for (i = 0; i < count; i++) { -+ ret = of_property_read_string_index(edma_np, "reset-names", -+ i, &reset_string); -+ if (ret) { -+ dev_err(dev, "Error reading reset-names"); -+ of_node_put(edma_np); -+ return -EINVAL; -+ } -+ -+ edma_hw_rst = of_reset_control_get_exclusive(edma_np, reset_string); -+ if (IS_ERR(edma_hw_rst)) { -+ of_node_put(edma_np); -+ return PTR_ERR(edma_hw_rst); -+ } -+ -+ /* 100ms delay is required by hardware to reset EDMA. */ -+ reset_control_assert(edma_hw_rst); -+ fsleep(100); -+ -+ reset_control_deassert(edma_hw_rst); -+ fsleep(100); -+ -+ reset_control_put(edma_hw_rst); -+ dev_dbg(dev, "EDMA HW reset, i:%d reset_string:%s\n", i, reset_string); -+ } -+ -+ of_node_put(edma_np); -+ -+ return 0; -+} -+ -+static int edma_hw_configure(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ u32 data, reg; -+ int ret; -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_MAS_CTRL_ADDR; -+ ret = regmap_read(regmap, reg, &data); -+ if (ret) -+ return ret; -+ -+ pr_debug("EDMA ver %d hw init\n", data); -+ -+ /* Setup private data structure. */ -+ edma_ctx->intr_info.intr_mask_rx = EDMA_RXDESC_INT_MASK_PKT_INT; -+ edma_ctx->intr_info.intr_mask_txcmpl = EDMA_TX_INT_MASK_PKT_INT; -+ -+ /* Reset EDMA. */ -+ ret = edma_hw_reset(); -+ if (ret) { -+ pr_err("Error in resetting the hardware. ret: %d\n", ret); -+ return ret; -+ } -+ -+ /* Allocate memory for netdevices. */ -+ edma_ctx->netdev_arr = kzalloc((sizeof(**edma_ctx->netdev_arr) * -+ hw_info->max_ports), -+ GFP_KERNEL); -+ if (!edma_ctx->netdev_arr) -+ return -ENOMEM; -+ -+ /* Configure DMA request priority, DMA read burst length, -+ * and AXI write size. -+ */ -+ data = FIELD_PREP(EDMA_DMAR_BURST_LEN_MASK, EDMA_BURST_LEN_ENABLE); -+ data |= FIELD_PREP(EDMA_DMAR_REQ_PRI_MASK, 0); -+ data |= FIELD_PREP(EDMA_DMAR_TXDATA_OUTSTANDING_NUM_MASK, 31); -+ data |= FIELD_PREP(EDMA_DMAR_TXDESC_OUTSTANDING_NUM_MASK, 7); -+ data |= FIELD_PREP(EDMA_DMAR_RXFILL_OUTSTANDING_NUM_MASK, 7); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_DMAR_CTRL_ADDR; -+ ret = regmap_write(regmap, reg, data); -+ if (ret) -+ return ret; -+ -+ /* Configure Tx Timeout Threshold. */ -+ data = EDMA_TX_TIMEOUT_THRESH_VAL; -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TX_TIMEOUT_THRESH_ADDR; -+ ret = regmap_write(regmap, reg, data); -+ if (ret) -+ return ret; -+ -+ /* Set Miscellaneous error mask. */ -+ data = EDMA_MISC_AXI_RD_ERR_MASK | -+ EDMA_MISC_AXI_WR_ERR_MASK | -+ EDMA_MISC_RX_DESC_FIFO_FULL_MASK | -+ EDMA_MISC_RX_ERR_BUF_SIZE_MASK | -+ EDMA_MISC_TX_SRAM_FULL_MASK | -+ EDMA_MISC_TX_CMPL_BUF_FULL_MASK | -+ EDMA_MISC_DATA_LEN_ERR_MASK; -+ data |= EDMA_MISC_TX_TIMEOUT_MASK; -+ edma_ctx->intr_info.intr_mask_misc = data; -+ -+ /* Global EDMA enable and padding enable. */ -+ data = EDMA_PORT_PAD_EN | EDMA_PORT_EDMA_EN; -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_PORT_CTRL_ADDR; -+ ret = regmap_write(regmap, reg, data); -+ if (ret) -+ return ret; -+ -+ /* Initialize unicast priority map table. */ -+ ret = (int)edma_configure_ucast_prio_map_tbl(); -+ if (ret) { -+ pr_err("Failed to initialize unicast priority map table: %d\n", -+ ret); -+ kfree(edma_ctx->netdev_arr); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+/** -+ * edma_destroy - EDMA Destroy. -+ * @ppe_dev: PPE device -+ * -+ * Free the memory allocated during setup. -+ */ -+void edma_destroy(struct ppe_device *ppe_dev) -+{ -+ kfree(edma_ctx->intr_info.intr_rx); -+ kfree(edma_ctx->intr_info.intr_txcmpl); -+ kfree(edma_ctx->netdev_arr); -+} -+ -+/** -+ * edma_setup - EDMA Setup. -+ * @ppe_dev: PPE device -+ * -+ * Configure Ethernet global ctx, clocks, hardware and interrupts. -+ * -+ * Return 0 on success, negative error code on failure. -+ */ -+int edma_setup(struct ppe_device *ppe_dev) -+{ -+ struct device *dev = ppe_dev->dev; -+ int ret; -+ -+ edma_ctx = devm_kzalloc(dev, sizeof(*edma_ctx), GFP_KERNEL); -+ if (!edma_ctx) -+ return -ENOMEM; -+ -+ edma_ctx->hw_info = &ipq9574_hw_info; -+ edma_ctx->ppe_dev = ppe_dev; -+ -+ /* Configure the EDMA common clocks. */ -+ ret = edma_clock_init(); -+ if (ret) { -+ dev_err(dev, "Error in configuring the EDMA clocks\n"); -+ return ret; -+ } -+ -+ dev_dbg(dev, "QCOM EDMA common clocks are configured\n"); -+ -+ ret = edma_hw_configure(); -+ if (ret) { -+ dev_err(dev, "Error in edma configuration\n"); -+ return ret; -+ } -+ -+ ret = edma_irq_init(); -+ if (ret) { -+ dev_err(dev, "Error in irq initialization\n"); -+ return ret; -+ } -+ -+ dev_info(dev, "EDMA configuration successful\n"); -+ -+ return 0; -+} -+ -+/** -+ * ppe_edma_queue_offset_config - Configure queue offset for EDMA interface -+ * @ppe_dev: PPE device -+ * @class: The class to configure queue offset -+ * @index: Class index, internal priority or hash value -+ * @queue_offset: Queue offset value -+ * -+ * PPE EDMA queue offset is configured based on the PPE internal priority or -+ * RSS hash value, the profile ID is fixed to 0 for EDMA interface. -+ * -+ * Return 0 on success, negative error code on failure. -+ */ -+int ppe_edma_queue_offset_config(struct ppe_device *ppe_dev, -+ enum ppe_queue_class_type class, -+ int index, int queue_offset) -+{ -+ if (class == PPE_QUEUE_CLASS_PRIORITY) -+ return ppe_queue_ucast_offset_pri_set(ppe_dev, 0, -+ index, queue_offset); -+ -+ return ppe_queue_ucast_offset_hash_set(ppe_dev, 0, -+ index, queue_offset); -+} ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/edma.h -@@ -0,0 +1,113 @@ -+/* SPDX-License-Identifier: GPL-2.0-only -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#ifndef __EDMA_MAIN__ -+#define __EDMA_MAIN__ -+ -+#include "ppe_config.h" -+ -+/* One clock cycle = 1/(EDMA clock frequency in Mhz) micro seconds. -+ * -+ * One timer unit is 128 clock cycles. -+ * -+ * So, therefore the microsecond to timer unit calculation is: -+ * Timer unit = time in microseconds / (one clock cycle in microsecond * cycles in 1 timer unit) -+ * = ('x' microsecond * EDMA clock frequency in MHz ('y') / 128). -+ * -+ */ -+#define EDMA_CYCLE_PER_TIMER_UNIT 128 -+#define EDMA_MICROSEC_TO_TIMER_UNIT(x, y) ((x) * (y) / EDMA_CYCLE_PER_TIMER_UNIT) -+#define MHZ 1000000UL -+ -+/* EDMA profile ID. */ -+#define EDMA_CPU_PORT_PROFILE_ID 0 -+ -+/* Number of PPE queue priorities supported per ARM core. */ -+#define EDMA_PRI_MAX_PER_CORE 8 -+ -+/** -+ * enum ppe_queue_class_type - PPE queue class type -+ * @PPE_QUEUE_CLASS_PRIORITY: Queue offset configured from internal priority -+ * @PPE_QUEUE_CLASS_HASH: Queue offset configured from RSS hash. -+ */ -+enum ppe_queue_class_type { -+ PPE_QUEUE_CLASS_PRIORITY, -+ PPE_QUEUE_CLASS_HASH, -+}; -+ -+/** -+ * struct edma_ring_info - EDMA ring data structure. -+ * @max_rings: Maximum number of rings -+ * @ring_start: Ring start ID -+ * @num_rings: Number of rings -+ */ -+struct edma_ring_info { -+ u32 max_rings; -+ u32 ring_start; -+ u32 num_rings; -+}; -+ -+/** -+ * struct edma_hw_info - EDMA hardware data structure. -+ * @rxfill: Rx Fill ring information -+ * @rx: Rx Desc ring information -+ * @tx: Tx Desc ring information -+ * @txcmpl: Tx complete ring information -+ * @max_ports: Maximum number of ports -+ * @napi_budget_rx: Rx NAPI budget -+ * @napi_budget_tx: Tx NAPI budget -+ */ -+struct edma_hw_info { -+ struct edma_ring_info *rxfill; -+ struct edma_ring_info *rx; -+ struct edma_ring_info *tx; -+ struct edma_ring_info *txcmpl; -+ u32 max_ports; -+ u32 napi_budget_rx; -+ u32 napi_budget_tx; -+}; -+ -+/** -+ * struct edma_intr_info - EDMA interrupt data structure. -+ * @intr_mask_rx: RX interrupt mask -+ * @intr_rx: Rx interrupts -+ * @intr_mask_txcmpl: Tx completion interrupt mask -+ * @intr_txcmpl: Tx completion interrupts -+ * @intr_mask_misc: Miscellaneous interrupt mask -+ * @intr_misc: Miscellaneous interrupts -+ */ -+struct edma_intr_info { -+ u32 intr_mask_rx; -+ u32 *intr_rx; -+ u32 intr_mask_txcmpl; -+ u32 *intr_txcmpl; -+ u32 intr_mask_misc; -+ u32 intr_misc; -+}; -+ -+/** -+ * struct edma_context - EDMA context. -+ * @netdev_arr: Net device for each EDMA port -+ * @ppe_dev: PPE device -+ * @hw_info: EDMA Hardware info -+ * @intr_info: EDMA Interrupt info -+ */ -+struct edma_context { -+ struct net_device **netdev_arr; -+ struct ppe_device *ppe_dev; -+ struct edma_hw_info *hw_info; -+ struct edma_intr_info intr_info; -+}; -+ -+/* Global EDMA context. */ -+extern struct edma_context *edma_ctx; -+ -+void edma_destroy(struct ppe_device *ppe_dev); -+int edma_setup(struct ppe_device *ppe_dev); -+int ppe_edma_queue_offset_config(struct ppe_device *ppe_dev, -+ enum ppe_queue_class_type class, -+ int index, int queue_offset); -+ -+ -+#endif ---- a/drivers/net/ethernet/qualcomm/ppe/ppe.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.c -@@ -14,6 +14,7 @@ - #include - #include - -+#include "edma.h" - #include "ppe.h" - #include "ppe_config.h" - #include "ppe_debugfs.h" -@@ -201,10 +202,16 @@ static int qcom_ppe_probe(struct platfor - if (ret) - return dev_err_probe(dev, ret, "PPE HW config failed\n"); - -- ret = ppe_port_mac_init(ppe_dev); -+ ret = edma_setup(ppe_dev); - if (ret) -+ return dev_err_probe(dev, ret, "EDMA setup failed\n"); -+ -+ ret = ppe_port_mac_init(ppe_dev); -+ if (ret) { -+ edma_destroy(ppe_dev); - return dev_err_probe(dev, ret, - "PPE Port MAC initialization failed\n"); -+ } - - ppe_debugfs_setup(ppe_dev); - platform_set_drvdata(pdev, ppe_dev); -@@ -219,6 +226,7 @@ static void qcom_ppe_remove(struct platf - ppe_dev = platform_get_drvdata(pdev); - ppe_debugfs_teardown(ppe_dev); - ppe_port_mac_deinit(ppe_dev); -+ edma_destroy(ppe_dev); - - platform_set_drvdata(pdev, NULL); - } ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -@@ -800,4 +800,257 @@ - #define XGMAC_RXDISCARD_GB_ADDR 0x9AC - #define XGMAC_RXDISCARDBYTE_GB_ADDR 0x9B4 - -+#define EDMA_BASE_OFFSET 0xb00000 -+ -+/* EDMA register offsets */ -+#define EDMA_REG_MAS_CTRL_ADDR 0x0 -+#define EDMA_REG_PORT_CTRL_ADDR 0x4 -+#define EDMA_REG_VLAN_CTRL_ADDR 0x8 -+#define EDMA_REG_RXDESC2FILL_MAP_0_ADDR 0x14 -+#define EDMA_REG_RXDESC2FILL_MAP_1_ADDR 0x18 -+#define EDMA_REG_RXDESC2FILL_MAP_2_ADDR 0x1c -+#define EDMA_REG_TXQ_CTRL_ADDR 0x20 -+#define EDMA_REG_TXQ_CTRL_2_ADDR 0x24 -+#define EDMA_REG_TXQ_FC_0_ADDR 0x28 -+#define EDMA_REG_TXQ_FC_1_ADDR 0x30 -+#define EDMA_REG_TXQ_FC_2_ADDR 0x34 -+#define EDMA_REG_TXQ_FC_3_ADDR 0x38 -+#define EDMA_REG_RXQ_CTRL_ADDR 0x3c -+#define EDMA_REG_MISC_ERR_QID_ADDR 0x40 -+#define EDMA_REG_RXQ_FC_THRE_ADDR 0x44 -+#define EDMA_REG_DMAR_CTRL_ADDR 0x48 -+#define EDMA_REG_AXIR_CTRL_ADDR 0x4c -+#define EDMA_REG_AXIW_CTRL_ADDR 0x50 -+#define EDMA_REG_MIN_MSS_ADDR 0x54 -+#define EDMA_REG_LOOPBACK_CTRL_ADDR 0x58 -+#define EDMA_REG_MISC_INT_STAT_ADDR 0x5c -+#define EDMA_REG_MISC_INT_MASK_ADDR 0x60 -+#define EDMA_REG_DBG_CTRL_ADDR 0x64 -+#define EDMA_REG_DBG_DATA_ADDR 0x68 -+#define EDMA_REG_TX_TIMEOUT_THRESH_ADDR 0x6c -+#define EDMA_REG_REQ0_FIFO_THRESH_ADDR 0x80 -+#define EDMA_REG_WB_OS_THRESH_ADDR 0x84 -+#define EDMA_REG_MISC_ERR_QID_REG2_ADDR 0x88 -+#define EDMA_REG_TXDESC2CMPL_MAP_0_ADDR 0x8c -+#define EDMA_REG_TXDESC2CMPL_MAP_1_ADDR 0x90 -+#define EDMA_REG_TXDESC2CMPL_MAP_2_ADDR 0x94 -+#define EDMA_REG_TXDESC2CMPL_MAP_3_ADDR 0x98 -+#define EDMA_REG_TXDESC2CMPL_MAP_4_ADDR 0x9c -+#define EDMA_REG_TXDESC2CMPL_MAP_5_ADDR 0xa0 -+ -+/* Tx descriptor ring configuration register addresses */ -+#define EDMA_REG_TXDESC_BA(n) (0x1000 + (0x1000 * (n))) -+#define EDMA_REG_TXDESC_PROD_IDX(n) (0x1004 + (0x1000 * (n))) -+#define EDMA_REG_TXDESC_CONS_IDX(n) (0x1008 + (0x1000 * (n))) -+#define EDMA_REG_TXDESC_RING_SIZE(n) (0x100c + (0x1000 * (n))) -+#define EDMA_REG_TXDESC_CTRL(n) (0x1010 + (0x1000 * (n))) -+#define EDMA_REG_TXDESC_BA2(n) (0x1014 + (0x1000 * (n))) -+ -+/* RxFill ring configuration register addresses */ -+#define EDMA_REG_RXFILL_BA(n) (0x29000 + (0x1000 * (n))) -+#define EDMA_REG_RXFILL_PROD_IDX(n) (0x29004 + (0x1000 * (n))) -+#define EDMA_REG_RXFILL_CONS_IDX(n) (0x29008 + (0x1000 * (n))) -+#define EDMA_REG_RXFILL_RING_SIZE(n) (0x2900c + (0x1000 * (n))) -+#define EDMA_REG_RXFILL_BUFFER1_SIZE(n) (0x29010 + (0x1000 * (n))) -+#define EDMA_REG_RXFILL_FC_THRE(n) (0x29014 + (0x1000 * (n))) -+#define EDMA_REG_RXFILL_UGT_THRE(n) (0x29018 + (0x1000 * (n))) -+#define EDMA_REG_RXFILL_RING_EN(n) (0x2901c + (0x1000 * (n))) -+#define EDMA_REG_RXFILL_DISABLE(n) (0x29020 + (0x1000 * (n))) -+#define EDMA_REG_RXFILL_DISABLE_DONE(n) (0x29024 + (0x1000 * (n))) -+#define EDMA_REG_RXFILL_INT_STAT(n) (0x31000 + (0x1000 * (n))) -+#define EDMA_REG_RXFILL_INT_MASK(n) (0x31004 + (0x1000 * (n))) -+ -+/* Rx descriptor ring configuration register addresses */ -+#define EDMA_REG_RXDESC_BA(n) (0x39000 + (0x1000 * (n))) -+#define EDMA_REG_RXDESC_PROD_IDX(n) (0x39004 + (0x1000 * (n))) -+#define EDMA_REG_RXDESC_CONS_IDX(n) (0x39008 + (0x1000 * (n))) -+#define EDMA_REG_RXDESC_RING_SIZE(n) (0x3900c + (0x1000 * (n))) -+#define EDMA_REG_RXDESC_FC_THRE(n) (0x39010 + (0x1000 * (n))) -+#define EDMA_REG_RXDESC_UGT_THRE(n) (0x39014 + (0x1000 * (n))) -+#define EDMA_REG_RXDESC_CTRL(n) (0x39018 + (0x1000 * (n))) -+#define EDMA_REG_RXDESC_BPC(n) (0x3901c + (0x1000 * (n))) -+#define EDMA_REG_RXDESC_DISABLE(n) (0x39020 + (0x1000 * (n))) -+#define EDMA_REG_RXDESC_DISABLE_DONE(n) (0x39024 + (0x1000 * (n))) -+#define EDMA_REG_RXDESC_PREHEADER_BA(n) (0x39028 + (0x1000 * (n))) -+#define EDMA_REG_RXDESC_INT_STAT(n) (0x59000 + (0x1000 * (n))) -+#define EDMA_REG_RXDESC_INT_MASK(n) (0x59004 + (0x1000 * (n))) -+ -+#define EDMA_REG_RX_MOD_TIMER(n) (0x59008 + (0x1000 * (n))) -+#define EDMA_REG_RX_INT_CTRL(n) (0x5900c + (0x1000 * (n))) -+ -+/* Tx completion ring configuration register addresses */ -+#define EDMA_REG_TXCMPL_BA(n) (0x79000 + (0x1000 * (n))) -+#define EDMA_REG_TXCMPL_PROD_IDX(n) (0x79004 + (0x1000 * (n))) -+#define EDMA_REG_TXCMPL_CONS_IDX(n) (0x79008 + (0x1000 * (n))) -+#define EDMA_REG_TXCMPL_RING_SIZE(n) (0x7900c + (0x1000 * (n))) -+#define EDMA_REG_TXCMPL_UGT_THRE(n) (0x79010 + (0x1000 * (n))) -+#define EDMA_REG_TXCMPL_CTRL(n) (0x79014 + (0x1000 * (n))) -+#define EDMA_REG_TXCMPL_BPC(n) (0x79018 + (0x1000 * (n))) -+ -+#define EDMA_REG_TX_INT_STAT(n) (0x99000 + (0x1000 * (n))) -+#define EDMA_REG_TX_INT_MASK(n) (0x99004 + (0x1000 * (n))) -+#define EDMA_REG_TX_MOD_TIMER(n) (0x99008 + (0x1000 * (n))) -+#define EDMA_REG_TX_INT_CTRL(n) (0x9900c + (0x1000 * (n))) -+ -+/* EDMA_QID2RID_TABLE_MEM register field masks */ -+#define EDMA_RX_RING_ID_QUEUE0_MASK GENMASK(7, 0) -+#define EDMA_RX_RING_ID_QUEUE1_MASK GENMASK(15, 8) -+#define EDMA_RX_RING_ID_QUEUE2_MASK GENMASK(23, 16) -+#define EDMA_RX_RING_ID_QUEUE3_MASK GENMASK(31, 24) -+ -+/* EDMA_REG_PORT_CTRL register bit definitions */ -+#define EDMA_PORT_PAD_EN 0x1 -+#define EDMA_PORT_EDMA_EN 0x2 -+ -+/* EDMA_REG_DMAR_CTRL register field masks */ -+#define EDMA_DMAR_REQ_PRI_MASK GENMASK(2, 0) -+#define EDMA_DMAR_BURST_LEN_MASK BIT(3) -+#define EDMA_DMAR_TXDATA_OUTSTANDING_NUM_MASK GENMASK(8, 4) -+#define EDMA_DMAR_TXDESC_OUTSTANDING_NUM_MASK GENMASK(11, 9) -+#define EDMA_DMAR_RXFILL_OUTSTANDING_NUM_MASK GENMASK(14, 12) -+ -+#define EDMA_BURST_LEN_ENABLE 0 -+ -+/* Tx timeout threshold */ -+#define EDMA_TX_TIMEOUT_THRESH_VAL 0xFFFF -+ -+/* Rx descriptor ring base address mask */ -+#define EDMA_RXDESC_BA_MASK 0xffffffff -+ -+/* Rx Descriptor ring pre-header base address mask */ -+#define EDMA_RXDESC_PREHEADER_BA_MASK 0xffffffff -+ -+/* Tx descriptor prod ring index mask */ -+#define EDMA_TXDESC_PROD_IDX_MASK 0xffff -+ -+/* Tx descriptor consumer ring index mask */ -+#define EDMA_TXDESC_CONS_IDX_MASK 0xffff -+ -+/* Tx descriptor ring size mask */ -+#define EDMA_TXDESC_RING_SIZE_MASK 0xffff -+ -+/* Tx descriptor ring enable */ -+#define EDMA_TXDESC_TX_ENABLE 0x1 -+ -+#define EDMA_TXDESC_CTRL_TXEN_MASK BIT(0) -+#define EDMA_TXDESC_CTRL_FC_GRP_ID_MASK GENMASK(3, 1) -+ -+/* Tx completion ring prod index mask */ -+#define EDMA_TXCMPL_PROD_IDX_MASK 0xffff -+ -+/* Tx completion ring urgent threshold mask */ -+#define EDMA_TXCMPL_LOW_THRE_MASK 0xffff -+#define EDMA_TXCMPL_LOW_THRE_SHIFT 0 -+ -+/* EDMA_REG_TX_MOD_TIMER mask */ -+#define EDMA_TX_MOD_TIMER_INIT_MASK 0xffff -+#define EDMA_TX_MOD_TIMER_INIT_SHIFT 0 -+ -+/* Rx fill ring prod index mask */ -+#define EDMA_RXFILL_PROD_IDX_MASK 0xffff -+ -+/* Rx fill ring consumer index mask */ -+#define EDMA_RXFILL_CONS_IDX_MASK 0xffff -+ -+/* Rx fill ring size mask */ -+#define EDMA_RXFILL_RING_SIZE_MASK 0xffff -+ -+/* Rx fill ring flow control threshold masks */ -+#define EDMA_RXFILL_FC_XON_THRE_MASK 0x7ff -+#define EDMA_RXFILL_FC_XON_THRE_SHIFT 12 -+#define EDMA_RXFILL_FC_XOFF_THRE_MASK 0x7ff -+#define EDMA_RXFILL_FC_XOFF_THRE_SHIFT 0 -+ -+/* Rx fill ring enable bit */ -+#define EDMA_RXFILL_RING_EN 0x1 -+ -+/* Rx desc ring prod index mask */ -+#define EDMA_RXDESC_PROD_IDX_MASK 0xffff -+ -+/* Rx descriptor ring cons index mask */ -+#define EDMA_RXDESC_CONS_IDX_MASK 0xffff -+ -+/* Rx descriptor ring size masks */ -+#define EDMA_RXDESC_RING_SIZE_MASK 0xffff -+#define EDMA_RXDESC_PL_OFFSET_MASK 0x1ff -+#define EDMA_RXDESC_PL_OFFSET_SHIFT 16 -+#define EDMA_RXDESC_PL_DEFAULT_VALUE 0 -+ -+/* Rx descriptor ring flow control threshold masks */ -+#define EDMA_RXDESC_FC_XON_THRE_MASK 0x7ff -+#define EDMA_RXDESC_FC_XON_THRE_SHIFT 12 -+#define EDMA_RXDESC_FC_XOFF_THRE_MASK 0x7ff -+#define EDMA_RXDESC_FC_XOFF_THRE_SHIFT 0 -+ -+/* Rx descriptor ring urgent threshold mask */ -+#define EDMA_RXDESC_LOW_THRE_MASK 0xffff -+#define EDMA_RXDESC_LOW_THRE_SHIFT 0 -+ -+/* Rx descriptor ring enable bit */ -+#define EDMA_RXDESC_RX_EN 0x1 -+ -+/* Tx interrupt status bit */ -+#define EDMA_TX_INT_MASK_PKT_INT 0x1 -+ -+/* Rx interrupt mask */ -+#define EDMA_RXDESC_INT_MASK_PKT_INT 0x1 -+ -+#define EDMA_MASK_INT_DISABLE 0x0 -+#define EDMA_MASK_INT_CLEAR 0x0 -+ -+/* EDMA_REG_RX_MOD_TIMER register field masks */ -+#define EDMA_RX_MOD_TIMER_INIT_MASK 0xffff -+#define EDMA_RX_MOD_TIMER_INIT_SHIFT 0 -+ -+/* EDMA Ring mask */ -+#define EDMA_RING_DMA_MASK 0xffffffff -+ -+/* RXDESC threshold interrupt. */ -+#define EDMA_RXDESC_UGT_INT_STAT 0x2 -+ -+/* RXDESC timer interrupt */ -+#define EDMA_RXDESC_PKT_INT_STAT 0x1 -+ -+/* RXDESC Interrupt status mask */ -+#define EDMA_RXDESC_RING_INT_STATUS_MASK \ -+ (EDMA_RXDESC_UGT_INT_STAT | EDMA_RXDESC_PKT_INT_STAT) -+ -+/* TXCMPL threshold interrupt. */ -+#define EDMA_TXCMPL_UGT_INT_STAT 0x2 -+ -+/* TXCMPL timer interrupt */ -+#define EDMA_TXCMPL_PKT_INT_STAT 0x1 -+ -+/* TXCMPL Interrupt status mask */ -+#define EDMA_TXCMPL_RING_INT_STATUS_MASK \ -+ (EDMA_TXCMPL_UGT_INT_STAT | EDMA_TXCMPL_PKT_INT_STAT) -+ -+#define EDMA_TXCMPL_RETMODE_OPAQUE 0x0 -+ -+#define EDMA_RXDESC_LOW_THRE 0 -+#define EDMA_RX_MOD_TIMER_INIT 1000 -+#define EDMA_RX_NE_INT_EN 0x2 -+ -+#define EDMA_TX_MOD_TIMER 150 -+ -+#define EDMA_TX_INITIAL_PROD_IDX 0x0 -+#define EDMA_TX_NE_INT_EN 0x2 -+ -+/* EDMA misc error mask */ -+#define EDMA_MISC_AXI_RD_ERR_MASK BIT(0) -+#define EDMA_MISC_AXI_WR_ERR_MASK BIT(1) -+#define EDMA_MISC_RX_DESC_FIFO_FULL_MASK BIT(2) -+#define EDMA_MISC_RX_ERR_BUF_SIZE_MASK BIT(3) -+#define EDMA_MISC_TX_SRAM_FULL_MASK BIT(4) -+#define EDMA_MISC_TX_CMPL_BUF_FULL_MASK BIT(5) -+ -+#define EDMA_MISC_DATA_LEN_ERR_MASK BIT(6) -+#define EDMA_MISC_TX_TIMEOUT_MASK BIT(7) -+ -+/* EDMA txdesc2cmpl map */ -+#define EDMA_TXDESC2CMPL_MAP_TXDESC_MASK 0x1F -+ -+/* EDMA rxdesc2fill map */ -+#define EDMA_RXDESC2FILL_MAP_RXDESC_MASK 0x7 -+ - #endif diff --git a/target/linux/qualcommbe/patches-6.12/0343-net-ethernet-qualcomm-Add-netdevice-support-for-QCOM.patch b/target/linux/qualcommbe/patches-6.12/0343-net-ethernet-qualcomm-Add-netdevice-support-for-QCOM.patch deleted file mode 100644 index 55de486ed3..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0343-net-ethernet-qualcomm-Add-netdevice-support-for-QCOM.patch +++ /dev/null @@ -1,397 +0,0 @@ -From 5dc80c468c668d855d76b323f09bbadb95cc3147 Mon Sep 17 00:00:00 2001 -From: Suruchi Agarwal -Date: Thu, 21 Mar 2024 16:14:46 -0700 -Subject: [PATCH] net: ethernet: qualcomm: Add netdevice support for QCOM - IPQ9574 chipset. - -Add EDMA ports and netdevice operations for QCOM IPQ9574 chipset. - -Change-Id: I08b2eff52b4ef0d6d428c1c416f5580ef010973f -Co-developed-by: Pavithra R -Signed-off-by: Pavithra R -Signed-off-by: Suruchi Agarwal ---- - drivers/net/ethernet/qualcomm/ppe/Makefile | 2 +- - drivers/net/ethernet/qualcomm/ppe/edma.h | 3 + - drivers/net/ethernet/qualcomm/ppe/edma_port.c | 270 ++++++++++++++++++ - drivers/net/ethernet/qualcomm/ppe/edma_port.h | 31 ++ - drivers/net/ethernet/qualcomm/ppe/ppe_port.c | 19 ++ - 5 files changed, 324 insertions(+), 1 deletion(-) - create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma_port.c - create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma_port.h - ---- a/drivers/net/ethernet/qualcomm/ppe/Makefile -+++ b/drivers/net/ethernet/qualcomm/ppe/Makefile -@@ -7,4 +7,4 @@ obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o - qcom-ppe-objs := ppe.o ppe_config.o ppe_debugfs.o ppe_port.o - - #EDMA --qcom-ppe-objs += edma.o -+qcom-ppe-objs += edma.o edma_port.o ---- a/drivers/net/ethernet/qualcomm/ppe/edma.h -+++ b/drivers/net/ethernet/qualcomm/ppe/edma.h -@@ -26,6 +26,9 @@ - /* Number of PPE queue priorities supported per ARM core. */ - #define EDMA_PRI_MAX_PER_CORE 8 - -+/* Interface ID start. */ -+#define EDMA_START_IFNUM 1 -+ - /** - * enum ppe_queue_class_type - PPE queue class type - * @PPE_QUEUE_CLASS_PRIORITY: Queue offset configured from internal priority ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_port.c -@@ -0,0 +1,270 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+ /* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+/* EDMA port initialization, configuration and netdevice ops handling */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "edma.h" -+#include "edma_port.h" -+#include "ppe_regs.h" -+ -+/* Number of netdev queues. */ -+#define EDMA_NETDEV_QUEUE_NUM 4 -+ -+static u16 __maybe_unused edma_port_select_queue(__maybe_unused struct net_device *netdev, -+ __maybe_unused struct sk_buff *skb, -+ __maybe_unused struct net_device *sb_dev) -+{ -+ int cpu = get_cpu(); -+ -+ put_cpu(); -+ -+ return cpu; -+} -+ -+static int edma_port_open(struct net_device *netdev) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ struct ppe_port *ppe_port; -+ -+ if (!port_priv) -+ return -EINVAL; -+ -+ /* Inform the Linux Networking stack about the hardware capability of -+ * checksum offloading and other features. Each port is -+ * responsible to maintain the feature set it supports. -+ */ -+ netdev->features |= EDMA_NETDEV_FEATURES; -+ netdev->hw_features |= EDMA_NETDEV_FEATURES; -+ netdev->vlan_features |= EDMA_NETDEV_FEATURES; -+ netdev->wanted_features |= EDMA_NETDEV_FEATURES; -+ -+ ppe_port = port_priv->ppe_port; -+ -+ if (ppe_port->phylink) -+ phylink_start(ppe_port->phylink); -+ -+ netif_start_queue(netdev); -+ -+ return 0; -+} -+ -+static int edma_port_close(struct net_device *netdev) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ struct ppe_port *ppe_port; -+ -+ if (!port_priv) -+ return -EINVAL; -+ -+ netif_stop_queue(netdev); -+ -+ ppe_port = port_priv->ppe_port; -+ -+ /* Phylink close. */ -+ if (ppe_port->phylink) -+ phylink_stop(ppe_port->phylink); -+ -+ return 0; -+} -+ -+static int edma_port_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ struct ppe_port *ppe_port; -+ int ret = -EINVAL; -+ -+ if (!port_priv) -+ return -EINVAL; -+ -+ ppe_port = port_priv->ppe_port; -+ if (ppe_port->phylink) -+ return phylink_mii_ioctl(ppe_port->phylink, ifr, cmd); -+ -+ return ret; -+} -+ -+static int edma_port_change_mtu(struct net_device *netdev, int mtu) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ -+ if (!port_priv) -+ return -EINVAL; -+ -+ netdev->mtu = mtu; -+ -+ return ppe_port_set_maxframe(port_priv->ppe_port, mtu); -+} -+ -+static netdev_features_t edma_port_feature_check(__maybe_unused struct sk_buff *skb, -+ __maybe_unused struct net_device *netdev, -+ netdev_features_t features) -+{ -+ return features; -+} -+ -+static void edma_port_get_stats64(struct net_device *netdev, -+ struct rtnl_link_stats64 *stats) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ -+ if (!port_priv) -+ return; -+ -+ ppe_port_get_stats64(port_priv->ppe_port, stats); -+} -+ -+static int edma_port_set_mac_address(struct net_device *netdev, void *macaddr) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ struct sockaddr *addr = (struct sockaddr *)macaddr; -+ int ret; -+ -+ if (!port_priv) -+ return -EINVAL; -+ -+ netdev_dbg(netdev, "AddrFamily: %d, %0x:%0x:%0x:%0x:%0x:%0x\n", -+ addr->sa_family, addr->sa_data[0], addr->sa_data[1], -+ addr->sa_data[2], addr->sa_data[3], addr->sa_data[4], -+ addr->sa_data[5]); -+ -+ ret = eth_prepare_mac_addr_change(netdev, addr); -+ if (ret) -+ return ret; -+ -+ if (ppe_port_set_mac_address(port_priv->ppe_port, (u8 *)addr)) { -+ netdev_err(netdev, "set mac address failed for dev: %s\n", netdev->name); -+ return -EINVAL; -+ } -+ -+ eth_commit_mac_addr_change(netdev, addr); -+ -+ return 0; -+} -+ -+static const struct net_device_ops edma_port_netdev_ops = { -+ .ndo_open = edma_port_open, -+ .ndo_stop = edma_port_close, -+ .ndo_get_stats64 = edma_port_get_stats64, -+ .ndo_set_mac_address = edma_port_set_mac_address, -+ .ndo_validate_addr = eth_validate_addr, -+ .ndo_change_mtu = edma_port_change_mtu, -+ .ndo_eth_ioctl = edma_port_ioctl, -+ .ndo_features_check = edma_port_feature_check, -+ .ndo_select_queue = edma_port_select_queue, -+}; -+ -+/** -+ * edma_port_destroy - EDMA port destroy. -+ * @port: PPE port -+ * -+ * Unregister and free the netdevice. -+ */ -+void edma_port_destroy(struct ppe_port *port) -+{ -+ int port_id = port->port_id; -+ struct net_device *netdev = edma_ctx->netdev_arr[port_id - 1]; -+ -+ unregister_netdev(netdev); -+ free_netdev(netdev); -+ ppe_port_phylink_destroy(port); -+ edma_ctx->netdev_arr[port_id - 1] = NULL; -+} -+ -+/** -+ * edma_port_setup - EDMA port Setup. -+ * @port: PPE port -+ * -+ * Initialize and register the netdevice. -+ * -+ * Return 0 on success, negative error code on failure. -+ */ -+int edma_port_setup(struct ppe_port *port) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct device_node *np = port->np; -+ struct edma_port_priv *port_priv; -+ int port_id = port->port_id; -+ struct net_device *netdev; -+ u8 mac_addr[ETH_ALEN]; -+ int ret = 0; -+ u8 *maddr; -+ -+ netdev = alloc_etherdev_mqs(sizeof(struct edma_port_priv), -+ EDMA_NETDEV_QUEUE_NUM, EDMA_NETDEV_QUEUE_NUM); -+ if (!netdev) { -+ pr_err("alloc_etherdev() failed\n"); -+ return -ENOMEM; -+ } -+ -+ SET_NETDEV_DEV(netdev, ppe_dev->dev); -+ netdev->dev.of_node = np; -+ -+ /* max_mtu is set to 1500 in ether_setup(). */ -+ netdev->max_mtu = ETH_MAX_MTU; -+ -+ port_priv = netdev_priv(netdev); -+ memset((void *)port_priv, 0, sizeof(struct edma_port_priv)); -+ -+ port_priv->ppe_port = port; -+ port_priv->netdev = netdev; -+ netdev->watchdog_timeo = 5 * HZ; -+ netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE; -+ netdev->netdev_ops = &edma_port_netdev_ops; -+ netdev->gso_max_segs = GSO_MAX_SEGS; -+ -+ maddr = mac_addr; -+ if (of_get_mac_address(np, maddr)) -+ maddr = NULL; -+ -+ if (maddr && is_valid_ether_addr(maddr)) { -+ eth_hw_addr_set(netdev, maddr); -+ } else { -+ eth_hw_addr_random(netdev); -+ netdev_info(netdev, "GMAC%d Using random MAC address - %pM\n", -+ port_id, netdev->dev_addr); -+ } -+ -+ netdev_dbg(netdev, "Configuring the port %s(qcom-id:%d)\n", -+ netdev->name, port_id); -+ -+ /* We expect 'port_id' to correspond to ports numbers on SoC. -+ * These begin from '1' and hence we subtract -+ * one when using it as an array index. -+ */ -+ edma_ctx->netdev_arr[port_id - 1] = netdev; -+ -+ /* Setup phylink. */ -+ ret = ppe_port_phylink_setup(port, netdev); -+ if (ret) { -+ netdev_dbg(netdev, "EDMA port phylink setup for netdevice %s\n", -+ netdev->name); -+ goto port_phylink_setup_fail; -+ } -+ -+ /* Register the network interface. */ -+ ret = register_netdev(netdev); -+ if (ret) { -+ netdev_dbg(netdev, "Error registering netdevice %s\n", -+ netdev->name); -+ goto register_netdev_fail; -+ } -+ -+ netdev_dbg(netdev, "Setup EDMA port GMAC%d done\n", port_id); -+ return ret; -+ -+register_netdev_fail: -+ ppe_port_phylink_destroy(port); -+port_phylink_setup_fail: -+ free_netdev(netdev); -+ edma_ctx->netdev_arr[port_id - 1] = NULL; -+ -+ return ret; -+} ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_port.h -@@ -0,0 +1,31 @@ -+/* SPDX-License-Identifier: GPL-2.0-only -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#ifndef __EDMA_PORTS__ -+#define __EDMA_PORTS__ -+ -+#include "ppe_port.h" -+ -+#define EDMA_NETDEV_FEATURES (NETIF_F_FRAGLIST \ -+ | NETIF_F_SG \ -+ | NETIF_F_RXCSUM \ -+ | NETIF_F_HW_CSUM \ -+ | NETIF_F_TSO \ -+ | NETIF_F_TSO6) -+ -+/** -+ * struct edma_port_priv - EDMA port priv structure. -+ * @ppe_port: Pointer to PPE port -+ * @netdev: Corresponding netdevice -+ * @flags: Feature flags -+ */ -+struct edma_port_priv { -+ struct ppe_port *ppe_port; -+ struct net_device *netdev; -+ unsigned long flags; -+}; -+ -+void edma_port_destroy(struct ppe_port *port); -+int edma_port_setup(struct ppe_port *port); -+#endif ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_port.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_port.c -@@ -13,6 +13,7 @@ - #include - #include - -+#include "edma_port.h" - #include "ppe.h" - #include "ppe_port.h" - #include "ppe_regs.h" -@@ -1277,12 +1278,26 @@ int ppe_port_mac_init(struct ppe_device - goto err_port_node; - } - -+ ret = edma_port_setup(&ppe_ports->port[i]); -+ if (ret) { -+ dev_err(ppe_dev->dev, "QCOM EDMA port setup failed\n"); -+ i--; -+ goto err_port_setup; -+ } -+ - i++; - } - - of_node_put(ports_node); - return 0; - -+err_port_setup: -+ /* Destroy edma ports created till now */ -+ while (i >= 0) { -+ edma_port_destroy(&ppe_ports->port[i]); -+ i--; -+ } -+ - err_port_clk: - for (j = 0; j < i; j++) - ppe_port_clock_deinit(&ppe_ports->port[j]); -@@ -1307,6 +1322,10 @@ void ppe_port_mac_deinit(struct ppe_devi - - for (i = 0; i < ppe_dev->ports->num; i++) { - ppe_port = &ppe_dev->ports->port[i]; -+ -+ /* Destroy all phylinks and edma ports */ -+ edma_port_destroy(ppe_port); -+ - ppe_port_clock_deinit(ppe_port); - } - } diff --git a/target/linux/qualcommbe/patches-6.12/0344-net-ethernet-qualcomm-Add-Rx-Ethernet-DMA-support.patch b/target/linux/qualcommbe/patches-6.12/0344-net-ethernet-qualcomm-Add-Rx-Ethernet-DMA-support.patch deleted file mode 100644 index eb10a00745..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0344-net-ethernet-qualcomm-Add-Rx-Ethernet-DMA-support.patch +++ /dev/null @@ -1,2454 +0,0 @@ -From b5c8c5d3888328321e8be1db50b75dff8f514e51 Mon Sep 17 00:00:00 2001 -From: Suruchi Agarwal -Date: Thu, 21 Mar 2024 16:21:19 -0700 -Subject: [PATCH] net: ethernet: qualcomm: Add Rx Ethernet DMA support - -Add Rx queues, rings, descriptors configurations and -DMA support for the EDMA. - -Change-Id: I612bcd661e74d5bf3ecb33de10fd5298d18ff7e9 -Co-developed-by: Pavithra R -Signed-off-by: Pavithra R -Signed-off-by: Suruchi Agarwal -Alex G: add missing functions that were previously in ppe_api.c: - - ppe_edma_queue_resource_get() - - ppe_edma_ring_to_queues_config() -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/ethernet/qualcomm/ppe/Makefile | 2 +- - drivers/net/ethernet/qualcomm/ppe/edma.c | 214 +++- - drivers/net/ethernet/qualcomm/ppe/edma.h | 22 +- - .../net/ethernet/qualcomm/ppe/edma_cfg_rx.c | 964 ++++++++++++++++++ - .../net/ethernet/qualcomm/ppe/edma_cfg_rx.h | 48 + - drivers/net/ethernet/qualcomm/ppe/edma_port.c | 39 +- - drivers/net/ethernet/qualcomm/ppe/edma_port.h | 31 + - drivers/net/ethernet/qualcomm/ppe/edma_rx.c | 622 +++++++++++ - drivers/net/ethernet/qualcomm/ppe/edma_rx.h | 287 ++++++ - 9 files changed, 2224 insertions(+), 5 deletions(-) - create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma_cfg_rx.c - create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma_cfg_rx.h - create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma_rx.c - create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma_rx.h - ---- a/drivers/net/ethernet/qualcomm/ppe/Makefile -+++ b/drivers/net/ethernet/qualcomm/ppe/Makefile -@@ -7,4 +7,4 @@ obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o - qcom-ppe-objs := ppe.o ppe_config.o ppe_debugfs.o ppe_port.o - - #EDMA --qcom-ppe-objs += edma.o edma_port.o -+qcom-ppe-objs += edma.o edma_cfg_rx.o edma_port.o edma_rx.o ---- a/drivers/net/ethernet/qualcomm/ppe/edma.c -+++ b/drivers/net/ethernet/qualcomm/ppe/edma.c -@@ -18,12 +18,23 @@ - #include - - #include "edma.h" -+#include "edma_cfg_rx.h" - #include "ppe_regs.h" - - #define EDMA_IRQ_NAME_SIZE 32 - - /* Global EDMA context. */ - struct edma_context *edma_ctx; -+static char **edma_rxdesc_irq_name; -+ -+/* Module params. */ -+static int page_mode; -+module_param(page_mode, int, 0); -+MODULE_PARM_DESC(page_mode, "Enable page mode (default:0)"); -+ -+static int rx_buff_size; -+module_param(rx_buff_size, int, 0640); -+MODULE_PARM_DESC(rx_buff_size, "Rx Buffer size for Jumbo MRU value (default:0)"); - - /* Priority to multi-queue mapping. */ - static u8 edma_pri_map[PPE_QUEUE_INTER_PRI_NUM] = { -@@ -178,6 +189,59 @@ static int edma_configure_ucast_prio_map - return ret; - } - -+static int edma_irq_register(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rx = hw_info->rx; -+ int ret; -+ u32 i; -+ -+ /* Request IRQ for RXDESC rings. */ -+ edma_rxdesc_irq_name = kzalloc((sizeof(char *) * rx->num_rings), -+ GFP_KERNEL); -+ if (!edma_rxdesc_irq_name) -+ return -ENOMEM; -+ -+ for (i = 0; i < rx->num_rings; i++) { -+ edma_rxdesc_irq_name[i] = kzalloc((sizeof(char *) * EDMA_IRQ_NAME_SIZE), -+ GFP_KERNEL); -+ if (!edma_rxdesc_irq_name[i]) { -+ ret = -ENOMEM; -+ goto rxdesc_irq_name_alloc_fail; -+ } -+ -+ snprintf(edma_rxdesc_irq_name[i], 20, "edma_rxdesc_%d", -+ rx->ring_start + i); -+ -+ irq_set_status_flags(edma_ctx->intr_info.intr_rx[i], IRQ_DISABLE_UNLAZY); -+ -+ ret = request_irq(edma_ctx->intr_info.intr_rx[i], -+ edma_rx_handle_irq, IRQF_SHARED, -+ edma_rxdesc_irq_name[i], -+ (void *)&edma_ctx->rx_rings[i]); -+ if (ret) { -+ pr_err("RXDESC ring IRQ:%d request failed\n", -+ edma_ctx->intr_info.intr_rx[i]); -+ goto rx_desc_ring_intr_req_fail; -+ } -+ -+ pr_debug("RXDESC ring: %d IRQ:%d request success: %s\n", -+ rx->ring_start + i, -+ edma_ctx->intr_info.intr_rx[i], -+ edma_rxdesc_irq_name[i]); -+ } -+ -+ return 0; -+ -+rx_desc_ring_intr_req_fail: -+ for (i = 0; i < rx->num_rings; i++) -+ kfree(edma_rxdesc_irq_name[i]); -+rxdesc_irq_name_alloc_fail: -+ kfree(edma_rxdesc_irq_name); -+ -+ return ret; -+} -+ - static int edma_irq_init(void) - { - struct edma_hw_info *hw_info = edma_ctx->hw_info; -@@ -260,6 +324,16 @@ static int edma_irq_init(void) - return 0; - } - -+static int edma_alloc_rings(void) -+{ -+ if (edma_cfg_rx_rings_alloc()) { -+ pr_err("Error in allocating Rx rings\n"); -+ return -ENOMEM; -+ } -+ -+ return 0; -+} -+ - static int edma_hw_reset(void) - { - struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -@@ -343,6 +417,40 @@ static int edma_hw_configure(void) - if (!edma_ctx->netdev_arr) - return -ENOMEM; - -+ edma_ctx->dummy_dev = alloc_netdev_dummy(0); -+ if (!edma_ctx->dummy_dev) { -+ ret = -ENOMEM; -+ pr_err("Failed to allocate dummy device. ret: %d\n", ret); -+ goto dummy_dev_alloc_failed; -+ } -+ -+ /* Set EDMA jumbo MRU if enabled or set page mode. */ -+ if (edma_ctx->rx_buf_size) { -+ edma_ctx->rx_page_mode = false; -+ pr_debug("Rx Jumbo mru is enabled: %d\n", edma_ctx->rx_buf_size); -+ } else { -+ edma_ctx->rx_page_mode = page_mode; -+ } -+ -+ ret = edma_alloc_rings(); -+ if (ret) { -+ pr_err("Error in initializaing the rings. ret: %d\n", ret); -+ goto edma_alloc_rings_failed; -+ } -+ -+ /* Disable interrupts. */ -+ edma_cfg_rx_disable_interrupts(); -+ -+ edma_cfg_rx_rings_disable(); -+ -+ edma_cfg_rx_ring_mappings(); -+ -+ ret = edma_cfg_rx_rings(); -+ if (ret) { -+ pr_err("Error in configuring Rx rings. ret: %d\n", ret); -+ goto edma_cfg_rx_rings_failed; -+ } -+ - /* Configure DMA request priority, DMA read burst length, - * and AXI write size. - */ -@@ -376,6 +484,10 @@ static int edma_hw_configure(void) - data |= EDMA_MISC_TX_TIMEOUT_MASK; - edma_ctx->intr_info.intr_mask_misc = data; - -+ edma_cfg_rx_rings_enable(); -+ edma_cfg_rx_napi_add(); -+ edma_cfg_rx_napi_enable(); -+ - /* Global EDMA enable and padding enable. */ - data = EDMA_PORT_PAD_EN | EDMA_PORT_EDMA_EN; - -@@ -389,11 +501,32 @@ static int edma_hw_configure(void) - if (ret) { - pr_err("Failed to initialize unicast priority map table: %d\n", - ret); -- kfree(edma_ctx->netdev_arr); -- return ret; -+ goto configure_ucast_prio_map_tbl_failed; -+ } -+ -+ /* Initialize RPS hash map table. */ -+ ret = edma_cfg_rx_rps_hash_map(); -+ if (ret) { -+ pr_err("Failed to configure rps hash table: %d\n", -+ ret); -+ goto edma_cfg_rx_rps_hash_map_failed; - } - - return 0; -+ -+edma_cfg_rx_rps_hash_map_failed: -+configure_ucast_prio_map_tbl_failed: -+ edma_cfg_rx_napi_disable(); -+ edma_cfg_rx_napi_delete(); -+ edma_cfg_rx_rings_disable(); -+edma_cfg_rx_rings_failed: -+ edma_cfg_rx_rings_cleanup(); -+edma_alloc_rings_failed: -+ free_netdev(edma_ctx->dummy_dev); -+dummy_dev_alloc_failed: -+ kfree(edma_ctx->netdev_arr); -+ -+ return ret; - } - - /** -@@ -404,8 +537,31 @@ static int edma_hw_configure(void) - */ - void edma_destroy(struct ppe_device *ppe_dev) - { -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 i; -+ -+ /* Disable interrupts. */ -+ edma_cfg_rx_disable_interrupts(); -+ -+ /* Free IRQ for RXDESC rings. */ -+ for (i = 0; i < rx->num_rings; i++) { -+ synchronize_irq(edma_ctx->intr_info.intr_rx[i]); -+ free_irq(edma_ctx->intr_info.intr_rx[i], -+ (void *)&edma_ctx->rx_rings[i]); -+ kfree(edma_rxdesc_irq_name[i]); -+ } -+ kfree(edma_rxdesc_irq_name); -+ - kfree(edma_ctx->intr_info.intr_rx); - kfree(edma_ctx->intr_info.intr_txcmpl); -+ -+ edma_cfg_rx_napi_disable(); -+ edma_cfg_rx_napi_delete(); -+ edma_cfg_rx_rings_disable(); -+ edma_cfg_rx_rings_cleanup(); -+ -+ free_netdev(edma_ctx->dummy_dev); - kfree(edma_ctx->netdev_arr); - } - -@@ -428,6 +584,7 @@ int edma_setup(struct ppe_device *ppe_de - - edma_ctx->hw_info = &ipq9574_hw_info; - edma_ctx->ppe_dev = ppe_dev; -+ edma_ctx->rx_buf_size = rx_buff_size; - - /* Configure the EDMA common clocks. */ - ret = edma_clock_init(); -@@ -450,6 +607,16 @@ int edma_setup(struct ppe_device *ppe_de - return ret; - } - -+ ret = edma_irq_register(); -+ if (ret) { -+ dev_err(dev, "Error in irq registration\n"); -+ kfree(edma_ctx->intr_info.intr_rx); -+ kfree(edma_ctx->intr_info.intr_txcmpl); -+ return ret; -+ } -+ -+ edma_cfg_rx_enable_interrupts(); -+ - dev_info(dev, "EDMA configuration successful\n"); - - return 0; -@@ -478,3 +645,46 @@ int ppe_edma_queue_offset_config(struct - return ppe_queue_ucast_offset_hash_set(ppe_dev, 0, - index, queue_offset); - } -+ -+/** -+ * ppe_edma_queue_resource_get - Get EDMA queue resource -+ * @ppe_dev: PPE device -+ * @type: Resource type -+ * @res_start: Resource start ID returned -+ * @res_end: Resource end ID returned -+ * -+ * PPE EDMA queue resource includes unicast queue and multicast queue. -+ * -+ * Return 0 on success, negative error code on failure. -+ */ -+int ppe_edma_queue_resource_get(struct ppe_device *ppe_dev, int type, -+ int *res_start, int *res_end) -+{ -+ if (type != PPE_RES_UCAST && type != PPE_RES_MCAST) -+ return -EINVAL; -+ -+ return ppe_port_resource_get(ppe_dev, 0, type, res_start, res_end); -+}; -+ -+/** -+ * ppe_edma_ring_to_queues_config - Map EDMA ring to PPE queues -+ * @ppe_dev: PPE device -+ * @ring_id: EDMA ring ID -+ * @num: Number of queues mapped to EDMA ring -+ * @queues: PPE queue IDs -+ * -+ * PPE queues are configured to map with the special EDMA ring ID. -+ * -+ * Return 0 on success, negative error code on failure. -+ */ -+int ppe_edma_ring_to_queues_config(struct ppe_device *ppe_dev, int ring_id, -+ int num, int queues[] __counted_by(num)) -+{ -+ u32 queue_bmap[PPE_RING_TO_QUEUE_BITMAP_WORD_CNT] = {}; -+ int index; -+ -+ for (index = 0; index < num; index++) -+ queue_bmap[queues[index] / 32] |= BIT_MASK(queues[index] % 32); -+ -+ return ppe_ring_queue_map_set(ppe_dev, ring_id, queue_bmap); -+} ---- a/drivers/net/ethernet/qualcomm/ppe/edma.h -+++ b/drivers/net/ethernet/qualcomm/ppe/edma.h -@@ -6,6 +6,7 @@ - #define __EDMA_MAIN__ - - #include "ppe_config.h" -+#include "edma_rx.h" - - /* One clock cycle = 1/(EDMA clock frequency in Mhz) micro seconds. - * -@@ -29,6 +30,11 @@ - /* Interface ID start. */ - #define EDMA_START_IFNUM 1 - -+#define EDMA_DESC_AVAIL_COUNT(head, tail, _max) ({ \ -+ typeof(_max) (max) = (_max); \ -+ ((((head) - (tail)) + \ -+ (max)) & ((max) - 1)); }) -+ - /** - * enum ppe_queue_class_type - PPE queue class type - * @PPE_QUEUE_CLASS_PRIORITY: Queue offset configured from internal priority -@@ -92,18 +98,28 @@ struct edma_intr_info { - /** - * struct edma_context - EDMA context. - * @netdev_arr: Net device for each EDMA port -+ * @dummy_dev: Dummy netdevice for RX DMA - * @ppe_dev: PPE device - * @hw_info: EDMA Hardware info - * @intr_info: EDMA Interrupt info -+ * @rxfill_rings: Rx fill Rings, SW is producer -+ * @rx_rings: Rx Desc Rings, SW is consumer -+ * @rx_page_mode: Page mode enabled or disabled -+ * @rx_buf_size: Rx buffer size for Jumbo MRU - */ - struct edma_context { - struct net_device **netdev_arr; -+ struct net_device *dummy_dev; - struct ppe_device *ppe_dev; - struct edma_hw_info *hw_info; - struct edma_intr_info intr_info; -+ struct edma_rxfill_ring *rxfill_rings; -+ struct edma_rxdesc_ring *rx_rings; -+ u32 rx_page_mode; -+ u32 rx_buf_size; - }; - --/* Global EDMA context. */ -+/* Global EDMA context */ - extern struct edma_context *edma_ctx; - - void edma_destroy(struct ppe_device *ppe_dev); -@@ -111,6 +127,10 @@ int edma_setup(struct ppe_device *ppe_de - int ppe_edma_queue_offset_config(struct ppe_device *ppe_dev, - enum ppe_queue_class_type class, - int index, int queue_offset); -+int ppe_edma_queue_resource_get(struct ppe_device *ppe_dev, int type, -+ int *res_start, int *res_end); -+int ppe_edma_ring_to_queues_config(struct ppe_device *ppe_dev, int ring_id, -+ int num, int queues[] __counted_by(num)); - - - #endif ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_cfg_rx.c -@@ -0,0 +1,964 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+/* Configure rings, Buffers and NAPI for receive path along with -+ * providing APIs to enable, disable, clean and map the Rx rings. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "edma.h" -+#include "edma_cfg_rx.h" -+#include "ppe.h" -+#include "ppe_regs.h" -+ -+/* EDMA Queue ID to Ring ID Table. */ -+#define EDMA_QID2RID_TABLE_MEM(q) (0xb9000 + (0x4 * (q))) -+ -+/* Rx ring queue offset. */ -+#define EDMA_QUEUE_OFFSET(q_id) ((q_id) / EDMA_MAX_PRI_PER_CORE) -+ -+/* Rx EDMA maximum queue supported. */ -+#define EDMA_CPU_PORT_QUEUE_MAX(queue_start) \ -+ ((queue_start) + (EDMA_MAX_PRI_PER_CORE * num_possible_cpus()) - 1) -+ -+/* EDMA Queue ID to Ring ID configuration. */ -+#define EDMA_QID2RID_NUM_PER_REG 4 -+ -+int rx_queues[] = {0, 8, 16, 24}; -+ -+static u32 edma_rx_ring_queue_map[][EDMA_MAX_CORE] = {{ 0, 8, 16, 24 }, -+ { 1, 9, 17, 25 }, -+ { 2, 10, 18, 26 }, -+ { 3, 11, 19, 27 }, -+ { 4, 12, 20, 28 }, -+ { 5, 13, 21, 29 }, -+ { 6, 14, 22, 30 }, -+ { 7, 15, 23, 31 }}; -+ -+static int edma_cfg_rx_desc_rings_reset_queue_mapping(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 i, ret; -+ -+ for (i = 0; i < rx->num_rings; i++) { -+ struct edma_rxdesc_ring *rxdesc_ring; -+ -+ rxdesc_ring = &edma_ctx->rx_rings[i]; -+ -+ ret = ppe_edma_ring_to_queues_config(edma_ctx->ppe_dev, rxdesc_ring->ring_id, -+ ARRAY_SIZE(rx_queues), rx_queues); -+ if (ret) { -+ pr_err("Error in unmapping rxdesc ring %d to PPE queue mapping to disable its backpressure configuration\n", -+ i); -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ -+static int edma_cfg_rx_desc_ring_reset_queue_priority(u32 rxdesc_ring_idx) -+{ -+ u32 i, queue_id, ret; -+ -+ for (i = 0; i < EDMA_MAX_PRI_PER_CORE; i++) { -+ queue_id = edma_rx_ring_queue_map[i][rxdesc_ring_idx]; -+ -+ ret = ppe_queue_priority_set(edma_ctx->ppe_dev, queue_id, i); -+ if (ret) { -+ pr_err("Error in resetting %u queue's priority\n", -+ queue_id); -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ -+static int edma_cfg_rx_desc_ring_reset_queue_config(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 i, ret; -+ -+ if (unlikely(rx->num_rings > num_possible_cpus())) { -+ pr_err("Invalid count of rxdesc rings: %d\n", -+ rx->num_rings); -+ return -EINVAL; -+ } -+ -+ /* Unmap Rxdesc ring to PPE queue mapping */ -+ ret = edma_cfg_rx_desc_rings_reset_queue_mapping(); -+ if (ret) { -+ pr_err("Error in resetting Rx desc ring backpressure config\n"); -+ return ret; -+ } -+ -+ /* Reset the priority for PPE queues mapped to Rx rings */ -+ for (i = 0; i < rx->num_rings; i++) { -+ ret = edma_cfg_rx_desc_ring_reset_queue_priority(i); -+ if (ret) { -+ pr_err("Error in resetting ring:%d queue's priority\n", -+ i + rx->ring_start); -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ -+static int edma_cfg_rx_desc_ring_to_queue_mapping(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 i; -+ int ret; -+ -+ /* Rxdesc ring to PPE queue mapping */ -+ for (i = 0; i < rx->num_rings; i++) { -+ struct edma_rxdesc_ring *rxdesc_ring; -+ -+ rxdesc_ring = &edma_ctx->rx_rings[i]; -+ -+ ret = ppe_edma_ring_to_queues_config(edma_ctx->ppe_dev, -+ rxdesc_ring->ring_id, -+ ARRAY_SIZE(rx_queues), rx_queues); -+ if (ret) { -+ pr_err("Error in configuring Rx ring to PPE queue mapping, ret: %d, id: %d\n", -+ ret, rxdesc_ring->ring_id); -+ if (!edma_cfg_rx_desc_rings_reset_queue_mapping()) -+ pr_err("Error in resetting Rx desc ringbackpressure configurations\n"); -+ -+ return ret; -+ } -+ -+ pr_debug("Rx desc ring %d to PPE queue mapping for backpressure:\n", -+ rxdesc_ring->ring_id); -+ } -+ -+ return 0; -+} -+ -+static void edma_cfg_rx_desc_ring_configure(struct edma_rxdesc_ring *rxdesc_ring) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ u32 data, reg; -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_BA(rxdesc_ring->ring_id); -+ regmap_write(regmap, reg, (u32)(rxdesc_ring->pdma & EDMA_RXDESC_BA_MASK)); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_PREHEADER_BA(rxdesc_ring->ring_id); -+ regmap_write(regmap, reg, (u32)(rxdesc_ring->sdma & EDMA_RXDESC_PREHEADER_BA_MASK)); -+ -+ data = rxdesc_ring->count & EDMA_RXDESC_RING_SIZE_MASK; -+ data |= (EDMA_RXDESC_PL_DEFAULT_VALUE & EDMA_RXDESC_PL_OFFSET_MASK) -+ << EDMA_RXDESC_PL_OFFSET_SHIFT; -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_RING_SIZE(rxdesc_ring->ring_id); -+ regmap_write(regmap, reg, data); -+ -+ /* Configure the Mitigation timer */ -+ data = EDMA_MICROSEC_TO_TIMER_UNIT(EDMA_RX_MITIGATION_TIMER_DEF, -+ ppe_dev->clk_rate / MHZ); -+ data = ((data & EDMA_RX_MOD_TIMER_INIT_MASK) -+ << EDMA_RX_MOD_TIMER_INIT_SHIFT); -+ pr_debug("EDMA Rx mitigation timer value: %d\n", data); -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RX_MOD_TIMER(rxdesc_ring->ring_id); -+ regmap_write(regmap, reg, data); -+ -+ /* Configure the Mitigation packet count */ -+ data = (EDMA_RX_MITIGATION_PKT_CNT_DEF & EDMA_RXDESC_LOW_THRE_MASK) -+ << EDMA_RXDESC_LOW_THRE_SHIFT; -+ pr_debug("EDMA Rx mitigation packet count value: %d\n", data); -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_UGT_THRE(rxdesc_ring->ring_id); -+ regmap_write(regmap, reg, data); -+ -+ /* Enable ring. Set ret mode to 'opaque'. */ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RX_INT_CTRL(rxdesc_ring->ring_id); -+ regmap_write(regmap, reg, EDMA_RX_NE_INT_EN); -+} -+ -+static void edma_cfg_rx_qid_to_rx_desc_ring_mapping(void) -+{ -+ u32 desc_index, ring_index, reg_index, data, q_id; -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 mcast_start, mcast_end, reg; -+ int ret; -+ -+ desc_index = (rx->ring_start & EDMA_RX_RING_ID_MASK); -+ -+ /* Here map all the queues to ring. */ -+ for (q_id = EDMA_RX_QUEUE_START; -+ q_id <= EDMA_CPU_PORT_QUEUE_MAX(EDMA_RX_QUEUE_START); -+ q_id += EDMA_QID2RID_NUM_PER_REG) { -+ reg_index = q_id / EDMA_QID2RID_NUM_PER_REG; -+ ring_index = desc_index + EDMA_QUEUE_OFFSET(q_id); -+ -+ data = FIELD_PREP(EDMA_RX_RING_ID_QUEUE0_MASK, ring_index); -+ data |= FIELD_PREP(EDMA_RX_RING_ID_QUEUE1_MASK, ring_index); -+ data |= FIELD_PREP(EDMA_RX_RING_ID_QUEUE2_MASK, ring_index); -+ data |= FIELD_PREP(EDMA_RX_RING_ID_QUEUE3_MASK, ring_index); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_QID2RID_TABLE_MEM(reg_index); -+ regmap_write(regmap, reg, data); -+ pr_debug("Configure QID2RID: %d reg:0x%x to 0x%x, desc_index: %d, reg_index: %d\n", -+ q_id, EDMA_QID2RID_TABLE_MEM(reg_index), data, desc_index, reg_index); -+ } -+ -+ ret = ppe_edma_queue_resource_get(edma_ctx->ppe_dev, PPE_RES_MCAST, -+ &mcast_start, &mcast_end); -+ if (ret < 0) { -+ pr_err("Error in extracting multicast queue values\n"); -+ return; -+ } -+ -+ /* Map multicast queues to the first Rx ring. */ -+ desc_index = (rx->ring_start & EDMA_RX_RING_ID_MASK); -+ for (q_id = mcast_start; q_id <= mcast_end; -+ q_id += EDMA_QID2RID_NUM_PER_REG) { -+ reg_index = q_id / EDMA_QID2RID_NUM_PER_REG; -+ -+ data = FIELD_PREP(EDMA_RX_RING_ID_QUEUE0_MASK, desc_index); -+ data |= FIELD_PREP(EDMA_RX_RING_ID_QUEUE1_MASK, desc_index); -+ data |= FIELD_PREP(EDMA_RX_RING_ID_QUEUE2_MASK, desc_index); -+ data |= FIELD_PREP(EDMA_RX_RING_ID_QUEUE3_MASK, desc_index); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_QID2RID_TABLE_MEM(reg_index); -+ regmap_write(regmap, reg, data); -+ -+ pr_debug("Configure QID2RID: %d reg:0x%x to 0x%x\n", -+ q_id, EDMA_QID2RID_TABLE_MEM(reg_index), data); -+ } -+} -+ -+static void edma_cfg_rx_rings_to_rx_fill_mapping(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 i, data, reg; -+ -+ regmap_write(regmap, EDMA_BASE_OFFSET + EDMA_REG_RXDESC2FILL_MAP_0_ADDR, 0); -+ regmap_write(regmap, EDMA_BASE_OFFSET + EDMA_REG_RXDESC2FILL_MAP_1_ADDR, 0); -+ regmap_write(regmap, EDMA_BASE_OFFSET + EDMA_REG_RXDESC2FILL_MAP_2_ADDR, 0); -+ -+ for (i = 0; i < rx->num_rings; i++) { -+ struct edma_rxdesc_ring *rxdesc_ring = &edma_ctx->rx_rings[i]; -+ u32 data, reg, ring_id; -+ -+ ring_id = rxdesc_ring->ring_id; -+ if (ring_id >= 0 && ring_id <= 9) -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC2FILL_MAP_0_ADDR; -+ else if (ring_id >= 10 && ring_id <= 19) -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC2FILL_MAP_1_ADDR; -+ else -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC2FILL_MAP_2_ADDR; -+ -+ pr_debug("Configure RXDESC:%u to use RXFILL:%u\n", -+ ring_id, -+ rxdesc_ring->rxfill->ring_id); -+ -+ /* Set the Rx fill ring number in the mapping register. */ -+ regmap_read(regmap, reg, &data); -+ data |= (rxdesc_ring->rxfill->ring_id & -+ EDMA_RXDESC2FILL_MAP_RXDESC_MASK) << -+ ((ring_id % 10) * 3); -+ regmap_write(regmap, reg, data); -+ } -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC2FILL_MAP_0_ADDR; -+ regmap_read(regmap, reg, &data); -+ pr_debug("EDMA_REG_RXDESC2FILL_MAP_0_ADDR: 0x%x\n", data); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC2FILL_MAP_1_ADDR; -+ regmap_read(regmap, reg, &data); -+ pr_debug("EDMA_REG_RXDESC2FILL_MAP_1_ADDR: 0x%x\n", data); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC2FILL_MAP_2_ADDR; -+ regmap_read(regmap, reg, &data); -+ pr_debug("EDMA_REG_RXDESC2FILL_MAP_2_ADDR: 0x%x\n", data); -+} -+ -+/** -+ * edma_cfg_rx_rings_enable - Enable Rx and Rxfill rings -+ * -+ * Enable Rx and Rxfill rings. -+ */ -+void edma_cfg_rx_rings_enable(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rxfill = hw_info->rxfill; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 i, reg; -+ -+ /* Enable Rx rings */ -+ for (i = rx->ring_start; i < rx->ring_start + rx->num_rings; i++) { -+ u32 data; -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_CTRL(i); -+ regmap_read(regmap, reg, &data); -+ data |= EDMA_RXDESC_RX_EN; -+ regmap_write(regmap, reg, data); -+ } -+ -+ for (i = rxfill->ring_start; i < rxfill->ring_start + rxfill->num_rings; i++) { -+ u32 data; -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXFILL_RING_EN(i); -+ regmap_read(regmap, reg, &data); -+ data |= EDMA_RXFILL_RING_EN; -+ regmap_write(regmap, reg, data); -+ } -+} -+ -+/** -+ * edma_cfg_rx_rings_disable - Disable Rx and Rxfill rings -+ * -+ * Disable Rx and Rxfill rings. -+ */ -+void edma_cfg_rx_rings_disable(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rxfill = hw_info->rxfill; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 i, reg; -+ -+ /* Disable Rx rings */ -+ for (i = 0; i < rx->num_rings; i++) { -+ struct edma_rxdesc_ring *rxdesc_ring = NULL; -+ u32 data; -+ -+ rxdesc_ring = &edma_ctx->rx_rings[i]; -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_CTRL(rxdesc_ring->ring_id); -+ regmap_read(regmap, reg, &data); -+ data &= ~EDMA_RXDESC_RX_EN; -+ regmap_write(regmap, reg, data); -+ } -+ -+ /* Disable RxFill Rings */ -+ for (i = 0; i < rxfill->num_rings; i++) { -+ struct edma_rxfill_ring *rxfill_ring = NULL; -+ u32 data; -+ -+ rxfill_ring = &edma_ctx->rxfill_rings[i]; -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXFILL_RING_EN(rxfill_ring->ring_id); -+ regmap_read(regmap, reg, &data); -+ data &= ~EDMA_RXFILL_RING_EN; -+ regmap_write(regmap, reg, data); -+ } -+} -+ -+/** -+ * edma_cfg_rx_mappings - Setup RX ring mapping -+ * -+ * Setup queue ID to Rx desc ring mapping. -+ */ -+void edma_cfg_rx_ring_mappings(void) -+{ -+ edma_cfg_rx_qid_to_rx_desc_ring_mapping(); -+ edma_cfg_rx_rings_to_rx_fill_mapping(); -+} -+ -+static void edma_cfg_rx_fill_ring_cleanup(struct edma_rxfill_ring *rxfill_ring) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct device *dev = ppe_dev->dev; -+ u16 cons_idx, curr_idx; -+ u32 data, reg; -+ -+ /* Get RxFill ring producer index */ -+ curr_idx = rxfill_ring->prod_idx & EDMA_RXFILL_PROD_IDX_MASK; -+ -+ /* Get RxFill ring consumer index */ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXFILL_CONS_IDX(rxfill_ring->ring_id); -+ regmap_read(regmap, reg, &data); -+ cons_idx = data & EDMA_RXFILL_CONS_IDX_MASK; -+ -+ while (curr_idx != cons_idx) { -+ struct edma_rxfill_desc *rxfill_desc; -+ struct sk_buff *skb; -+ -+ /* Get RxFill descriptor */ -+ rxfill_desc = EDMA_RXFILL_DESC(rxfill_ring, cons_idx); -+ -+ cons_idx = (cons_idx + 1) & EDMA_RX_RING_SIZE_MASK; -+ -+ /* Get skb from opaque */ -+ skb = (struct sk_buff *)EDMA_RXFILL_OPAQUE_GET(rxfill_desc); -+ if (unlikely(!skb)) { -+ pr_err("Empty skb reference at index:%d\n", -+ cons_idx); -+ continue; -+ } -+ -+ dev_kfree_skb_any(skb); -+ } -+ -+ /* Free RxFill ring descriptors */ -+ dma_free_coherent(dev, (sizeof(struct edma_rxfill_desc) -+ * rxfill_ring->count), -+ rxfill_ring->desc, rxfill_ring->dma); -+ rxfill_ring->desc = NULL; -+ rxfill_ring->dma = (dma_addr_t)0; -+} -+ -+static int edma_cfg_rx_fill_ring_dma_alloc(struct edma_rxfill_ring *rxfill_ring) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct device *dev = ppe_dev->dev; -+ -+ /* Allocate RxFill ring descriptors */ -+ rxfill_ring->desc = dma_alloc_coherent(dev, (sizeof(struct edma_rxfill_desc) -+ * rxfill_ring->count), -+ &rxfill_ring->dma, -+ GFP_KERNEL | __GFP_ZERO); -+ if (unlikely(!rxfill_ring->desc)) -+ return -ENOMEM; -+ -+ return 0; -+} -+ -+static int edma_cfg_rx_desc_ring_dma_alloc(struct edma_rxdesc_ring *rxdesc_ring) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct device *dev = ppe_dev->dev; -+ -+ rxdesc_ring->pdesc = dma_alloc_coherent(dev, (sizeof(struct edma_rxdesc_pri) -+ * rxdesc_ring->count), -+ &rxdesc_ring->pdma, GFP_KERNEL | __GFP_ZERO); -+ if (unlikely(!rxdesc_ring->pdesc)) -+ return -ENOMEM; -+ -+ rxdesc_ring->sdesc = dma_alloc_coherent(dev, (sizeof(struct edma_rxdesc_sec) -+ * rxdesc_ring->count), -+ &rxdesc_ring->sdma, GFP_KERNEL | __GFP_ZERO); -+ if (unlikely(!rxdesc_ring->sdesc)) { -+ dma_free_coherent(dev, (sizeof(struct edma_rxdesc_pri) -+ * rxdesc_ring->count), -+ rxdesc_ring->pdesc, -+ rxdesc_ring->pdma); -+ rxdesc_ring->pdesc = NULL; -+ rxdesc_ring->pdma = (dma_addr_t)0; -+ return -ENOMEM; -+ } -+ -+ return 0; -+} -+ -+static void edma_cfg_rx_desc_ring_cleanup(struct edma_rxdesc_ring *rxdesc_ring) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct device *dev = ppe_dev->dev; -+ u32 prod_idx, cons_idx, reg; -+ -+ /* Get Rxdesc consumer & producer indices */ -+ cons_idx = rxdesc_ring->cons_idx & EDMA_RXDESC_CONS_IDX_MASK; -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_PROD_IDX(rxdesc_ring->ring_id); -+ regmap_read(regmap, reg, &prod_idx); -+ prod_idx = prod_idx & EDMA_RXDESC_PROD_IDX_MASK; -+ -+ /* Free any buffers assigned to any descriptors */ -+ while (cons_idx != prod_idx) { -+ struct edma_rxdesc_pri *rxdesc_pri = -+ EDMA_RXDESC_PRI_DESC(rxdesc_ring, cons_idx); -+ struct sk_buff *skb; -+ -+ /* Update consumer index */ -+ cons_idx = (cons_idx + 1) & EDMA_RX_RING_SIZE_MASK; -+ -+ /* Get opaque from Rxdesc */ -+ skb = (struct sk_buff *)EDMA_RXDESC_OPAQUE_GET(rxdesc_pri); -+ if (unlikely(!skb)) { -+ pr_warn("Empty skb reference at index:%d\n", -+ cons_idx); -+ continue; -+ } -+ -+ dev_kfree_skb_any(skb); -+ } -+ -+ /* Update the consumer index */ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_CONS_IDX(rxdesc_ring->ring_id); -+ regmap_write(regmap, reg, cons_idx); -+ -+ /* Free Rxdesc ring descriptor */ -+ dma_free_coherent(dev, (sizeof(struct edma_rxdesc_pri) -+ * rxdesc_ring->count), rxdesc_ring->pdesc, -+ rxdesc_ring->pdma); -+ rxdesc_ring->pdesc = NULL; -+ rxdesc_ring->pdma = (dma_addr_t)0; -+ -+ /* Free any buffers assigned to any secondary ring descriptors */ -+ dma_free_coherent(dev, (sizeof(struct edma_rxdesc_sec) -+ * rxdesc_ring->count), rxdesc_ring->sdesc, -+ rxdesc_ring->sdma); -+ rxdesc_ring->sdesc = NULL; -+ rxdesc_ring->sdma = (dma_addr_t)0; -+} -+ -+static int edma_cfg_rx_rings_setup(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rxfill = hw_info->rxfill; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 ring_idx, alloc_size, buf_len; -+ -+ /* Set buffer allocation size */ -+ if (edma_ctx->rx_buf_size) { -+ alloc_size = edma_ctx->rx_buf_size + -+ EDMA_RX_SKB_HEADROOM + NET_IP_ALIGN; -+ buf_len = alloc_size - EDMA_RX_SKB_HEADROOM - NET_IP_ALIGN; -+ } else if (edma_ctx->rx_page_mode) { -+ alloc_size = EDMA_RX_PAGE_MODE_SKB_SIZE + -+ EDMA_RX_SKB_HEADROOM + NET_IP_ALIGN; -+ buf_len = PAGE_SIZE; -+ } else { -+ alloc_size = EDMA_RX_BUFFER_SIZE; -+ buf_len = alloc_size - EDMA_RX_SKB_HEADROOM - NET_IP_ALIGN; -+ } -+ -+ pr_debug("EDMA ctx:%p rx_ring alloc_size=%d, buf_len=%d\n", -+ edma_ctx, alloc_size, buf_len); -+ -+ /* Allocate Rx fill ring descriptors */ -+ for (ring_idx = 0; ring_idx < rxfill->num_rings; ring_idx++) { -+ u32 ret; -+ struct edma_rxfill_ring *rxfill_ring = NULL; -+ -+ rxfill_ring = &edma_ctx->rxfill_rings[ring_idx]; -+ rxfill_ring->count = EDMA_RX_RING_SIZE; -+ rxfill_ring->ring_id = rxfill->ring_start + ring_idx; -+ rxfill_ring->alloc_size = alloc_size; -+ rxfill_ring->buf_len = buf_len; -+ rxfill_ring->page_mode = edma_ctx->rx_page_mode; -+ -+ ret = edma_cfg_rx_fill_ring_dma_alloc(rxfill_ring); -+ if (ret) { -+ pr_err("Error in setting up %d rxfill ring. ret: %d", -+ rxfill_ring->ring_id, ret); -+ while (--ring_idx >= 0) -+ edma_cfg_rx_fill_ring_cleanup(&edma_ctx->rxfill_rings[ring_idx]); -+ -+ return -ENOMEM; -+ } -+ } -+ -+ /* Allocate RxDesc ring descriptors */ -+ for (ring_idx = 0; ring_idx < rx->num_rings; ring_idx++) { -+ u32 index, queue_id = EDMA_RX_QUEUE_START; -+ struct edma_rxdesc_ring *rxdesc_ring = NULL; -+ u32 ret; -+ -+ rxdesc_ring = &edma_ctx->rx_rings[ring_idx]; -+ rxdesc_ring->count = EDMA_RX_RING_SIZE; -+ rxdesc_ring->ring_id = rx->ring_start + ring_idx; -+ -+ if (queue_id > EDMA_CPU_PORT_QUEUE_MAX(EDMA_RX_QUEUE_START)) { -+ pr_err("Invalid queue_id: %d\n", queue_id); -+ while (--ring_idx >= 0) -+ edma_cfg_rx_desc_ring_cleanup(&edma_ctx->rx_rings[ring_idx]); -+ -+ goto rxdesc_mem_alloc_fail; -+ } -+ -+ /* Create a mapping between RX Desc ring and Rx fill ring. -+ * Number of fill rings are lesser than the descriptor rings -+ * Share the fill rings across descriptor rings. -+ */ -+ index = rxfill->ring_start + -+ (ring_idx % rxfill->num_rings); -+ rxdesc_ring->rxfill = &edma_ctx->rxfill_rings[index -+ - rxfill->ring_start]; -+ -+ ret = edma_cfg_rx_desc_ring_dma_alloc(rxdesc_ring); -+ if (ret) { -+ pr_err("Error in setting up %d rxdesc ring. ret: %d", -+ rxdesc_ring->ring_id, ret); -+ while (--ring_idx >= 0) -+ edma_cfg_rx_desc_ring_cleanup(&edma_ctx->rx_rings[ring_idx]); -+ -+ goto rxdesc_mem_alloc_fail; -+ } -+ } -+ -+ pr_debug("Rx descriptor count for Rx desc and Rx fill rings : %d\n", -+ EDMA_RX_RING_SIZE); -+ -+ return 0; -+ -+rxdesc_mem_alloc_fail: -+ for (ring_idx = 0; ring_idx < rxfill->num_rings; ring_idx++) -+ edma_cfg_rx_fill_ring_cleanup(&edma_ctx->rxfill_rings[ring_idx]); -+ -+ return -ENOMEM; -+} -+ -+/** -+ * edma_cfg_rx_buff_size_setup - Configure EDMA Rx jumbo buffer -+ * -+ * Configure EDMA Rx jumbo buffer -+ */ -+void edma_cfg_rx_buff_size_setup(void) -+{ -+ if (edma_ctx->rx_buf_size) { -+ edma_ctx->rx_page_mode = false; -+ pr_debug("Rx Jumbo mru is enabled: %d\n", edma_ctx->rx_buf_size); -+ } -+} -+ -+/** -+ * edma_cfg_rx_rings_alloc - Allocate EDMA Rx rings -+ * -+ * Allocate EDMA Rx rings. -+ * -+ * Return 0 on success, negative error code on failure. -+ */ -+int edma_cfg_rx_rings_alloc(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rxfill = hw_info->rxfill; -+ struct edma_ring_info *rx = hw_info->rx; -+ int ret; -+ -+ edma_ctx->rxfill_rings = kzalloc((sizeof(*edma_ctx->rxfill_rings) * -+ rxfill->num_rings), -+ GFP_KERNEL); -+ if (!edma_ctx->rxfill_rings) -+ return -ENOMEM; -+ -+ edma_ctx->rx_rings = kzalloc((sizeof(*edma_ctx->rx_rings) * -+ rx->num_rings), -+ GFP_KERNEL); -+ if (!edma_ctx->rx_rings) -+ goto rxdesc_ring_alloc_fail; -+ -+ pr_debug("RxDesc:%u rx (%u-%u) RxFill:%u (%u-%u)\n", -+ rx->num_rings, rx->ring_start, -+ (rx->ring_start + rx->num_rings - 1), -+ rxfill->num_rings, rxfill->ring_start, -+ (rxfill->ring_start + rxfill->num_rings - 1)); -+ -+ if (edma_cfg_rx_rings_setup()) { -+ pr_err("Error in setting up Rx rings\n"); -+ goto rx_rings_setup_fail; -+ } -+ -+ /* Reset Rx descriptor ring mapped queue's configurations */ -+ ret = edma_cfg_rx_desc_ring_reset_queue_config(); -+ if (ret) { -+ pr_err("Error in resetting the Rx descriptor rings configurations\n"); -+ edma_cfg_rx_rings_cleanup(); -+ return ret; -+ } -+ -+ return 0; -+ -+rx_rings_setup_fail: -+ kfree(edma_ctx->rx_rings); -+ edma_ctx->rx_rings = NULL; -+rxdesc_ring_alloc_fail: -+ kfree(edma_ctx->rxfill_rings); -+ edma_ctx->rxfill_rings = NULL; -+ -+ return -ENOMEM; -+} -+ -+/** -+ * edma_cfg_rx_rings_cleanup - Cleanup EDMA Rx rings -+ * -+ * Cleanup EDMA Rx rings -+ */ -+void edma_cfg_rx_rings_cleanup(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rxfill = hw_info->rxfill; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 i; -+ -+ /* Free RxFill ring descriptors */ -+ for (i = 0; i < rxfill->num_rings; i++) -+ edma_cfg_rx_fill_ring_cleanup(&edma_ctx->rxfill_rings[i]); -+ -+ /* Free Rx completion ring descriptors */ -+ for (i = 0; i < rx->num_rings; i++) -+ edma_cfg_rx_desc_ring_cleanup(&edma_ctx->rx_rings[i]); -+ -+ kfree(edma_ctx->rxfill_rings); -+ kfree(edma_ctx->rx_rings); -+ edma_ctx->rxfill_rings = NULL; -+ edma_ctx->rx_rings = NULL; -+} -+ -+static void edma_cfg_rx_fill_ring_configure(struct edma_rxfill_ring *rxfill_ring) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ u32 ring_sz, reg; -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXFILL_BA(rxfill_ring->ring_id); -+ regmap_write(regmap, reg, (u32)(rxfill_ring->dma & EDMA_RING_DMA_MASK)); -+ -+ ring_sz = rxfill_ring->count & EDMA_RXFILL_RING_SIZE_MASK; -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXFILL_RING_SIZE(rxfill_ring->ring_id); -+ regmap_write(regmap, reg, ring_sz); -+ -+ edma_rx_alloc_buffer(rxfill_ring, rxfill_ring->count - 1); -+} -+ -+static void edma_cfg_rx_desc_ring_flow_control(u32 threshold_xoff, u32 threshold_xon) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 data, i, reg; -+ -+ data = (threshold_xoff & EDMA_RXDESC_FC_XOFF_THRE_MASK) << EDMA_RXDESC_FC_XOFF_THRE_SHIFT; -+ data |= ((threshold_xon & EDMA_RXDESC_FC_XON_THRE_MASK) << EDMA_RXDESC_FC_XON_THRE_SHIFT); -+ -+ for (i = 0; i < rx->num_rings; i++) { -+ struct edma_rxdesc_ring *rxdesc_ring; -+ -+ rxdesc_ring = &edma_ctx->rx_rings[i]; -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_FC_THRE(rxdesc_ring->ring_id); -+ regmap_write(regmap, reg, data); -+ } -+} -+ -+static void edma_cfg_rx_fill_ring_flow_control(int threshold_xoff, int threshold_xon) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rxfill = hw_info->rxfill; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ u32 data, i, reg; -+ -+ data = (threshold_xoff & EDMA_RXFILL_FC_XOFF_THRE_MASK) << EDMA_RXFILL_FC_XOFF_THRE_SHIFT; -+ data |= ((threshold_xon & EDMA_RXFILL_FC_XON_THRE_MASK) << EDMA_RXFILL_FC_XON_THRE_SHIFT); -+ -+ for (i = 0; i < rxfill->num_rings; i++) { -+ struct edma_rxfill_ring *rxfill_ring; -+ -+ rxfill_ring = &edma_ctx->rxfill_rings[i]; -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXFILL_FC_THRE(rxfill_ring->ring_id); -+ regmap_write(regmap, reg, data); -+ } -+} -+ -+/** -+ * edma_cfg_rx_rings - Configure EDMA Rx rings. -+ * -+ * Configure EDMA Rx rings. -+ */ -+int edma_cfg_rx_rings(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rxfill = hw_info->rxfill; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 i; -+ -+ for (i = 0; i < rxfill->num_rings; i++) -+ edma_cfg_rx_fill_ring_configure(&edma_ctx->rxfill_rings[i]); -+ -+ for (i = 0; i < rx->num_rings; i++) -+ edma_cfg_rx_desc_ring_configure(&edma_ctx->rx_rings[i]); -+ -+ /* Configure Rx flow control configurations */ -+ edma_cfg_rx_desc_ring_flow_control(EDMA_RX_FC_XOFF_DEF, EDMA_RX_FC_XON_DEF); -+ edma_cfg_rx_fill_ring_flow_control(EDMA_RX_FC_XOFF_DEF, EDMA_RX_FC_XON_DEF); -+ -+ return edma_cfg_rx_desc_ring_to_queue_mapping(); -+} -+ -+/** -+ * edma_cfg_rx_disable_interrupts - EDMA disable RX interrupts -+ * -+ * Disable RX interrupt masks -+ */ -+void edma_cfg_rx_disable_interrupts(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 i, reg; -+ -+ for (i = 0; i < rx->num_rings; i++) { -+ struct edma_rxdesc_ring *rxdesc_ring = -+ &edma_ctx->rx_rings[i]; -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_INT_MASK(rxdesc_ring->ring_id); -+ regmap_write(regmap, reg, EDMA_MASK_INT_CLEAR); -+ } -+} -+ -+/** -+ * edma_cfg_rx_enable_interrupts - EDMA enable RX interrupts -+ * -+ * Enable RX interrupt masks -+ */ -+void edma_cfg_rx_enable_interrupts(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 i, reg; -+ -+ for (i = 0; i < rx->num_rings; i++) { -+ struct edma_rxdesc_ring *rxdesc_ring = -+ &edma_ctx->rx_rings[i]; -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_INT_MASK(rxdesc_ring->ring_id); -+ regmap_write(regmap, reg, edma_ctx->intr_info.intr_mask_rx); -+ } -+} -+ -+/** -+ * edma_cfg_rx_napi_disable - Disable NAPI for Rx -+ * -+ * Disable NAPI for Rx -+ */ -+void edma_cfg_rx_napi_disable(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 i; -+ -+ for (i = 0; i < rx->num_rings; i++) { -+ struct edma_rxdesc_ring *rxdesc_ring; -+ -+ rxdesc_ring = &edma_ctx->rx_rings[i]; -+ -+ if (!rxdesc_ring->napi_added) -+ continue; -+ -+ napi_disable(&rxdesc_ring->napi); -+ } -+} -+ -+/** -+ * edma_cfg_rx_napi_enable - Enable NAPI for Rx -+ * -+ * Enable NAPI for Rx -+ */ -+void edma_cfg_rx_napi_enable(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 i; -+ -+ for (i = 0; i < rx->num_rings; i++) { -+ struct edma_rxdesc_ring *rxdesc_ring; -+ -+ rxdesc_ring = &edma_ctx->rx_rings[i]; -+ -+ if (!rxdesc_ring->napi_added) -+ continue; -+ -+ napi_enable(&rxdesc_ring->napi); -+ } -+} -+ -+/** -+ * edma_cfg_rx_napi_delete - Delete Rx NAPI -+ * -+ * Delete RX NAPI -+ */ -+void edma_cfg_rx_napi_delete(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 i; -+ -+ for (i = 0; i < rx->num_rings; i++) { -+ struct edma_rxdesc_ring *rxdesc_ring; -+ -+ rxdesc_ring = &edma_ctx->rx_rings[i]; -+ -+ if (!rxdesc_ring->napi_added) -+ continue; -+ -+ netif_napi_del(&rxdesc_ring->napi); -+ rxdesc_ring->napi_added = false; -+ } -+} -+ -+/* Add Rx NAPI */ -+/** -+ * edma_cfg_rx_napi_add - Add Rx NAPI -+ * @netdev: Netdevice -+ * -+ * Add RX NAPI -+ */ -+void edma_cfg_rx_napi_add(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 i; -+ -+ for (i = 0; i < rx->num_rings; i++) { -+ struct edma_rxdesc_ring *rxdesc_ring = &edma_ctx->rx_rings[i]; -+ -+ netif_napi_add_weight(edma_ctx->dummy_dev, &rxdesc_ring->napi, -+ edma_rx_napi_poll, hw_info->napi_budget_rx); -+ rxdesc_ring->napi_added = true; -+ } -+ -+ netdev_dbg(edma_ctx->dummy_dev, "Rx NAPI budget: %d\n", hw_info->napi_budget_rx); -+} -+ -+/** -+ * edma_cfg_rx_rps_hash_map - Configure rx rps hash map. -+ * -+ * Initialize and configure RPS hash map for queues -+ */ -+int edma_cfg_rx_rps_hash_map(void) -+{ -+ cpumask_t edma_rps_cpumask = {{EDMA_RX_DEFAULT_BITMAP}}; -+ int map_len = 0, idx = 0, ret = 0; -+ u32 q_off = EDMA_RX_QUEUE_START; -+ u32 q_map[EDMA_MAX_CORE] = {0}; -+ u32 hash, cpu; -+ -+ /* Map all possible hash values to queues used by the EDMA Rx -+ * rings based on a bitmask, which represents the cores to be mapped. -+ * These queues are expected to be mapped to different Rx rings -+ * which are assigned to different cores using IRQ affinity configuration. -+ */ -+ for_each_cpu(cpu, &edma_rps_cpumask) { -+ q_map[map_len] = q_off + (cpu * EDMA_MAX_PRI_PER_CORE); -+ map_len++; -+ } -+ -+ for (hash = 0; hash < PPE_QUEUE_HASH_NUM; hash++) { -+ ret = ppe_edma_queue_offset_config(edma_ctx->ppe_dev, -+ PPE_QUEUE_CLASS_HASH, hash, q_map[idx]); -+ if (ret) -+ return ret; -+ -+ pr_debug("profile_id: %u, hash: %u, q_off: %u\n", -+ EDMA_CPU_PORT_PROFILE_ID, hash, q_map[idx]); -+ idx = (idx + 1) % map_len; -+ } -+ -+ return 0; -+} ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_cfg_rx.h -@@ -0,0 +1,48 @@ -+/* SPDX-License-Identifier: GPL-2.0-only -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#ifndef __EDMA_CFG_RX__ -+#define __EDMA_CFG_RX__ -+ -+/* SKB payload size used in page mode */ -+#define EDMA_RX_PAGE_MODE_SKB_SIZE 256 -+ -+/* Rx flow control X-OFF default value */ -+#define EDMA_RX_FC_XOFF_DEF 32 -+ -+/* Rx flow control X-ON default value */ -+#define EDMA_RX_FC_XON_DEF 64 -+ -+/* Rx AC flow control original threshold */ -+#define EDMA_RX_AC_FC_THRE_ORIG 0x190 -+ -+/* Rx AC flow control default threshold */ -+#define EDMA_RX_AC_FC_THRES_DEF 0x104 -+/* Rx mitigation timer's default value in microseconds */ -+#define EDMA_RX_MITIGATION_TIMER_DEF 25 -+ -+/* Rx mitigation packet count's default value */ -+#define EDMA_RX_MITIGATION_PKT_CNT_DEF 16 -+ -+/* Default bitmap of cores for RPS to ARM cores */ -+#define EDMA_RX_DEFAULT_BITMAP ((1 << EDMA_MAX_CORE) - 1) -+ -+int edma_cfg_rx_rings(void); -+int edma_cfg_rx_rings_alloc(void); -+void edma_cfg_rx_ring_mappings(void); -+void edma_cfg_rx_rings_cleanup(void); -+void edma_cfg_rx_disable_interrupts(void); -+void edma_cfg_rx_enable_interrupts(void); -+void edma_cfg_rx_napi_disable(void); -+void edma_cfg_rx_napi_enable(void); -+void edma_cfg_rx_napi_delete(void); -+void edma_cfg_rx_napi_add(void); -+void edma_cfg_rx_mapping(void); -+void edma_cfg_rx_rings_enable(void); -+void edma_cfg_rx_rings_disable(void); -+void edma_cfg_rx_buff_size_setup(void); -+int edma_cfg_rx_rps_hash_map(void); -+int edma_cfg_rx_rps(struct ctl_table *table, int write, -+ void *buffer, size_t *lenp, loff_t *ppos); -+#endif ---- a/drivers/net/ethernet/qualcomm/ppe/edma_port.c -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_port.c -@@ -12,12 +12,39 @@ - #include - - #include "edma.h" -+#include "edma_cfg_rx.h" - #include "edma_port.h" - #include "ppe_regs.h" - - /* Number of netdev queues. */ - #define EDMA_NETDEV_QUEUE_NUM 4 - -+static int edma_port_stats_alloc(struct net_device *netdev) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ -+ if (!port_priv) -+ return -EINVAL; -+ -+ /* Allocate per-cpu stats memory. */ -+ port_priv->pcpu_stats.rx_stats = -+ netdev_alloc_pcpu_stats(struct edma_port_rx_stats); -+ if (!port_priv->pcpu_stats.rx_stats) { -+ netdev_err(netdev, "Per-cpu EDMA Rx stats alloc failed for %s\n", -+ netdev->name); -+ return -ENOMEM; -+ } -+ -+ return 0; -+} -+ -+static void edma_port_stats_free(struct net_device *netdev) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ -+ free_percpu(port_priv->pcpu_stats.rx_stats); -+} -+ - static u16 __maybe_unused edma_port_select_queue(__maybe_unused struct net_device *netdev, - __maybe_unused struct sk_buff *skb, - __maybe_unused struct net_device *sb_dev) -@@ -172,6 +199,7 @@ void edma_port_destroy(struct ppe_port * - int port_id = port->port_id; - struct net_device *netdev = edma_ctx->netdev_arr[port_id - 1]; - -+ edma_port_stats_free(netdev); - unregister_netdev(netdev); - free_netdev(netdev); - ppe_port_phylink_destroy(port); -@@ -232,6 +260,13 @@ int edma_port_setup(struct ppe_port *por - port_id, netdev->dev_addr); - } - -+ /* Allocate memory for EDMA port statistics. */ -+ ret = edma_port_stats_alloc(netdev); -+ if (ret) { -+ netdev_dbg(netdev, "EDMA port stats alloc failed\n"); -+ goto stats_alloc_fail; -+ } -+ - netdev_dbg(netdev, "Configuring the port %s(qcom-id:%d)\n", - netdev->name, port_id); - -@@ -263,8 +298,10 @@ int edma_port_setup(struct ppe_port *por - register_netdev_fail: - ppe_port_phylink_destroy(port); - port_phylink_setup_fail: -- free_netdev(netdev); - edma_ctx->netdev_arr[port_id - 1] = NULL; -+ edma_port_stats_free(netdev); -+stats_alloc_fail: -+ free_netdev(netdev); - - return ret; - } ---- a/drivers/net/ethernet/qualcomm/ppe/edma_port.h -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_port.h -@@ -15,14 +15,45 @@ - | NETIF_F_TSO6) - - /** -+ * struct edma_port_rx_stats - EDMA RX per CPU stats for the port. -+ * @rx_pkts: Number of Rx packets -+ * @rx_bytes: Number of Rx bytes -+ * @rx_drops: Number of Rx drops -+ * @rx_nr_frag_pkts: Number of Rx nr_frags packets -+ * @rx_fraglist_pkts: Number of Rx fraglist packets -+ * @rx_nr_frag_headroom_err: nr_frags headroom error packets -+ * @syncp: Synchronization pointer -+ */ -+struct edma_port_rx_stats { -+ u64 rx_pkts; -+ u64 rx_bytes; -+ u64 rx_drops; -+ u64 rx_nr_frag_pkts; -+ u64 rx_fraglist_pkts; -+ u64 rx_nr_frag_headroom_err; -+ struct u64_stats_sync syncp; -+}; -+ -+/** -+ * struct edma_port_pcpu_stats - EDMA per cpu stats data structure for the port. -+ * @rx_stats: Per CPU Rx statistics -+ */ -+struct edma_port_pcpu_stats { -+ struct edma_port_rx_stats __percpu *rx_stats; -+}; -+ -+/** - * struct edma_port_priv - EDMA port priv structure. - * @ppe_port: Pointer to PPE port - * @netdev: Corresponding netdevice -+ * @pcpu_stats: Per CPU netdev statistics -+ * @txr_map: Tx ring per-core mapping - * @flags: Feature flags - */ - struct edma_port_priv { - struct ppe_port *ppe_port; - struct net_device *netdev; -+ struct edma_port_pcpu_stats pcpu_stats; - unsigned long flags; - }; - ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_rx.c -@@ -0,0 +1,622 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+/* Provides APIs to alloc Rx Buffers, reap the buffers, receive and -+ * process linear and Scatter Gather packets. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "edma.h" -+#include "edma_cfg_rx.h" -+#include "edma_port.h" -+#include "ppe.h" -+#include "ppe_regs.h" -+ -+static int edma_rx_alloc_buffer_list(struct edma_rxfill_ring *rxfill_ring, int alloc_count) -+{ -+ struct edma_rxfill_stats *rxfill_stats = &rxfill_ring->rxfill_stats; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ u32 rx_alloc_size = rxfill_ring->alloc_size; -+ struct regmap *regmap = ppe_dev->regmap; -+ bool page_mode = rxfill_ring->page_mode; -+ struct edma_rxfill_desc *rxfill_desc; -+ u32 buf_len = rxfill_ring->buf_len; -+ struct device *dev = ppe_dev->dev; -+ u16 prod_idx, start_idx; -+ u16 num_alloc = 0; -+ u32 reg; -+ -+ prod_idx = rxfill_ring->prod_idx; -+ start_idx = prod_idx; -+ -+ while (likely(alloc_count--)) { -+ dma_addr_t buff_addr; -+ struct sk_buff *skb; -+ struct page *pg; -+ -+ rxfill_desc = EDMA_RXFILL_DESC(rxfill_ring, prod_idx); -+ -+ skb = dev_alloc_skb(rx_alloc_size); -+ if (unlikely(!skb)) { -+ u64_stats_update_begin(&rxfill_stats->syncp); -+ ++rxfill_stats->alloc_failed; -+ u64_stats_update_end(&rxfill_stats->syncp); -+ break; -+ } -+ -+ skb_reserve(skb, EDMA_RX_SKB_HEADROOM + NET_IP_ALIGN); -+ -+ if (likely(!page_mode)) { -+ buff_addr = dma_map_single(dev, skb->data, rx_alloc_size, DMA_FROM_DEVICE); -+ if (dma_mapping_error(dev, buff_addr)) { -+ dev_dbg(dev, "edma_context:%p Unable to dma for non page mode", -+ edma_ctx); -+ dev_kfree_skb_any(skb); -+ break; -+ } -+ } else { -+ pg = alloc_page(GFP_ATOMIC); -+ if (unlikely(!pg)) { -+ u64_stats_update_begin(&rxfill_stats->syncp); -+ ++rxfill_stats->page_alloc_failed; -+ u64_stats_update_end(&rxfill_stats->syncp); -+ dev_kfree_skb_any(skb); -+ dev_dbg(dev, "edma_context:%p Unable to allocate page", -+ edma_ctx); -+ break; -+ } -+ -+ buff_addr = dma_map_page(dev, pg, 0, PAGE_SIZE, DMA_FROM_DEVICE); -+ if (dma_mapping_error(dev, buff_addr)) { -+ dev_dbg(dev, "edma_context:%p Mapping error for page mode", -+ edma_ctx); -+ __free_page(pg); -+ dev_kfree_skb_any(skb); -+ break; -+ } -+ -+ skb_fill_page_desc(skb, 0, pg, 0, PAGE_SIZE); -+ } -+ -+ EDMA_RXFILL_BUFFER_ADDR_SET(rxfill_desc, buff_addr); -+ -+ EDMA_RXFILL_OPAQUE_LO_SET(rxfill_desc, skb); -+#ifdef __LP64__ -+ EDMA_RXFILL_OPAQUE_HI_SET(rxfill_desc, skb); -+#endif -+ EDMA_RXFILL_PACKET_LEN_SET(rxfill_desc, -+ (u32)(buf_len) & EDMA_RXFILL_BUF_SIZE_MASK); -+ prod_idx = (prod_idx + 1) & EDMA_RX_RING_SIZE_MASK; -+ num_alloc++; -+ } -+ -+ if (likely(num_alloc)) { -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXFILL_PROD_IDX(rxfill_ring->ring_id); -+ regmap_write(regmap, reg, prod_idx); -+ rxfill_ring->prod_idx = prod_idx; -+ } -+ -+ return num_alloc; -+} -+ -+/** -+ * edma_rx_alloc_buffer - EDMA Rx alloc buffer. -+ * @rxfill_ring: EDMA Rxfill ring -+ * @alloc_count: Number of rings to alloc -+ * -+ * Alloc Rx buffers for RxFill ring. -+ * -+ * Return the number of rings allocated. -+ */ -+int edma_rx_alloc_buffer(struct edma_rxfill_ring *rxfill_ring, int alloc_count) -+{ -+ return edma_rx_alloc_buffer_list(rxfill_ring, alloc_count); -+} -+ -+/* Mark ip_summed appropriately in the skb as per the L3/L4 checksum -+ * status in descriptor. -+ */ -+static void edma_rx_checksum_verify(struct edma_rxdesc_pri *rxdesc_pri, -+ struct sk_buff *skb) -+{ -+ u8 pid = EDMA_RXDESC_PID_GET(rxdesc_pri); -+ -+ skb_checksum_none_assert(skb); -+ -+ if (likely(EDMA_RX_PID_IS_IPV4(pid))) { -+ if (likely(EDMA_RXDESC_L3CSUM_STATUS_GET(rxdesc_pri)) && -+ likely(EDMA_RXDESC_L4CSUM_STATUS_GET(rxdesc_pri))) -+ skb->ip_summed = CHECKSUM_UNNECESSARY; -+ } else if (likely(EDMA_RX_PID_IS_IPV6(pid))) { -+ if (likely(EDMA_RXDESC_L4CSUM_STATUS_GET(rxdesc_pri))) -+ skb->ip_summed = CHECKSUM_UNNECESSARY; -+ } -+} -+ -+static void edma_rx_process_last_segment(struct edma_rxdesc_ring *rxdesc_ring, -+ struct edma_rxdesc_pri *rxdesc_pri, -+ struct sk_buff *skb) -+{ -+ bool page_mode = rxdesc_ring->rxfill->page_mode; -+ struct edma_port_pcpu_stats *pcpu_stats; -+ struct edma_port_rx_stats *rx_stats; -+ struct edma_port_priv *port_dev; -+ struct sk_buff *skb_head; -+ struct net_device *dev; -+ u32 pkt_length; -+ -+ /* Get packet length. */ -+ pkt_length = EDMA_RXDESC_PACKET_LEN_GET(rxdesc_pri); -+ -+ skb_head = rxdesc_ring->head; -+ dev = skb_head->dev; -+ -+ /* Check Rx checksum offload status. */ -+ if (likely(dev->features & NETIF_F_RXCSUM)) -+ edma_rx_checksum_verify(rxdesc_pri, skb_head); -+ -+ /* Get stats for the netdevice. */ -+ port_dev = netdev_priv(dev); -+ pcpu_stats = &port_dev->pcpu_stats; -+ rx_stats = this_cpu_ptr(pcpu_stats->rx_stats); -+ -+ if (unlikely(page_mode)) { -+ if (unlikely(!pskb_may_pull(skb_head, ETH_HLEN))) { -+ /* Discard the SKB that we have been building, -+ * in addition to the SKB linked to current descriptor. -+ */ -+ dev_kfree_skb_any(skb_head); -+ rxdesc_ring->head = NULL; -+ rxdesc_ring->last = NULL; -+ rxdesc_ring->pdesc_head = NULL; -+ -+ u64_stats_update_begin(&rx_stats->syncp); -+ rx_stats->rx_nr_frag_headroom_err++; -+ u64_stats_update_end(&rx_stats->syncp); -+ -+ return; -+ } -+ } -+ -+ if (unlikely(!pskb_pull(skb_head, EDMA_RXDESC_DATA_OFFSET_GET(rxdesc_ring->pdesc_head)))) { -+ dev_kfree_skb_any(skb_head); -+ rxdesc_ring->head = NULL; -+ rxdesc_ring->last = NULL; -+ rxdesc_ring->pdesc_head = NULL; -+ -+ u64_stats_update_begin(&rx_stats->syncp); -+ rx_stats->rx_nr_frag_headroom_err++; -+ u64_stats_update_end(&rx_stats->syncp); -+ -+ return; -+ } -+ -+ u64_stats_update_begin(&rx_stats->syncp); -+ rx_stats->rx_pkts++; -+ rx_stats->rx_bytes += skb_head->len; -+ rx_stats->rx_nr_frag_pkts += (u64)page_mode; -+ rx_stats->rx_fraglist_pkts += (u64)(!page_mode); -+ u64_stats_update_end(&rx_stats->syncp); -+ -+ pr_debug("edma_context:%p skb:%p Jumbo pkt_length:%u\n", -+ edma_ctx, skb_head, skb_head->len); -+ -+ skb_head->protocol = eth_type_trans(skb_head, dev); -+ -+ /* Send packet up the stack. */ -+ if (dev->features & NETIF_F_GRO) -+ napi_gro_receive(&rxdesc_ring->napi, skb_head); -+ else -+ netif_receive_skb(skb_head); -+ -+ rxdesc_ring->head = NULL; -+ rxdesc_ring->last = NULL; -+ rxdesc_ring->pdesc_head = NULL; -+} -+ -+static void edma_rx_handle_frag_list(struct edma_rxdesc_ring *rxdesc_ring, -+ struct edma_rxdesc_pri *rxdesc_pri, -+ struct sk_buff *skb) -+{ -+ u32 pkt_length; -+ -+ /* Get packet length. */ -+ pkt_length = EDMA_RXDESC_PACKET_LEN_GET(rxdesc_pri); -+ pr_debug("edma_context:%p skb:%p fragment pkt_length:%u\n", -+ edma_ctx, skb, pkt_length); -+ -+ if (!(rxdesc_ring->head)) { -+ skb_put(skb, pkt_length); -+ rxdesc_ring->head = skb; -+ rxdesc_ring->last = NULL; -+ rxdesc_ring->pdesc_head = rxdesc_pri; -+ -+ return; -+ } -+ -+ /* Append it to the fraglist of head if this is second frame -+ * If not second frame append to tail. -+ */ -+ skb_put(skb, pkt_length); -+ if (!skb_has_frag_list(rxdesc_ring->head)) -+ skb_shinfo(rxdesc_ring->head)->frag_list = skb; -+ else -+ rxdesc_ring->last->next = skb; -+ -+ rxdesc_ring->last = skb; -+ rxdesc_ring->last->next = NULL; -+ rxdesc_ring->head->len += pkt_length; -+ rxdesc_ring->head->data_len += pkt_length; -+ rxdesc_ring->head->truesize += skb->truesize; -+ -+ /* If there are more segments for this packet, -+ * then we have nothing to do. Otherwise process -+ * last segment and send packet to stack. -+ */ -+ if (EDMA_RXDESC_MORE_BIT_GET(rxdesc_pri)) -+ return; -+ -+ edma_rx_process_last_segment(rxdesc_ring, rxdesc_pri, skb); -+} -+ -+static void edma_rx_handle_nr_frags(struct edma_rxdesc_ring *rxdesc_ring, -+ struct edma_rxdesc_pri *rxdesc_pri, -+ struct sk_buff *skb) -+{ -+ skb_frag_t *frag = NULL; -+ u32 pkt_length; -+ -+ /* Get packet length. */ -+ pkt_length = EDMA_RXDESC_PACKET_LEN_GET(rxdesc_pri); -+ pr_debug("edma_context:%p skb:%p fragment pkt_length:%u\n", -+ edma_ctx, skb, pkt_length); -+ -+ if (!(rxdesc_ring->head)) { -+ skb->len = pkt_length; -+ skb->data_len = pkt_length; -+ skb->truesize = SKB_TRUESIZE(PAGE_SIZE); -+ rxdesc_ring->head = skb; -+ rxdesc_ring->last = NULL; -+ rxdesc_ring->pdesc_head = rxdesc_pri; -+ -+ return; -+ } -+ -+ frag = &skb_shinfo(skb)->frags[0]; -+ -+ /* Append current frag at correct index as nr_frag of parent. */ -+ skb_add_rx_frag(rxdesc_ring->head, skb_shinfo(rxdesc_ring->head)->nr_frags, -+ skb_frag_page(frag), 0, pkt_length, PAGE_SIZE); -+ skb_shinfo(skb)->nr_frags = 0; -+ -+ /* Free the SKB after we have appended its frag page to the head skb. */ -+ dev_kfree_skb_any(skb); -+ -+ /* If there are more segments for this packet, -+ * then we have nothing to do. Otherwise process -+ * last segment and send packet to stack. -+ */ -+ if (EDMA_RXDESC_MORE_BIT_GET(rxdesc_pri)) -+ return; -+ -+ edma_rx_process_last_segment(rxdesc_ring, rxdesc_pri, skb); -+} -+ -+static bool edma_rx_handle_linear_packets(struct edma_rxdesc_ring *rxdesc_ring, -+ struct edma_rxdesc_pri *rxdesc_pri, -+ struct sk_buff *skb) -+{ -+ bool page_mode = rxdesc_ring->rxfill->page_mode; -+ struct edma_port_pcpu_stats *pcpu_stats; -+ struct edma_port_rx_stats *rx_stats; -+ struct edma_port_priv *port_dev; -+ skb_frag_t *frag = NULL; -+ u32 pkt_length; -+ -+ /* Get stats for the netdevice. */ -+ port_dev = netdev_priv(skb->dev); -+ pcpu_stats = &port_dev->pcpu_stats; -+ rx_stats = this_cpu_ptr(pcpu_stats->rx_stats); -+ -+ /* Get packet length. */ -+ pkt_length = EDMA_RXDESC_PACKET_LEN_GET(rxdesc_pri); -+ -+ if (likely(!page_mode)) { -+ skb_put(skb, pkt_length); -+ goto send_to_stack; -+ } -+ -+ /* Handle linear packet in page mode. */ -+ frag = &skb_shinfo(skb)->frags[0]; -+ skb_add_rx_frag(skb, 0, skb_frag_page(frag), 0, pkt_length, PAGE_SIZE); -+ -+ /* Pull ethernet header into SKB data area for header processing. */ -+ if (unlikely(!pskb_may_pull(skb, ETH_HLEN))) { -+ u64_stats_update_begin(&rx_stats->syncp); -+ rx_stats->rx_nr_frag_headroom_err++; -+ u64_stats_update_end(&rx_stats->syncp); -+ dev_kfree_skb_any(skb); -+ -+ return false; -+ } -+ -+send_to_stack: -+ -+ __skb_pull(skb, EDMA_RXDESC_DATA_OFFSET_GET(rxdesc_pri)); -+ -+ /* Check Rx checksum offload status. */ -+ if (likely(skb->dev->features & NETIF_F_RXCSUM)) -+ edma_rx_checksum_verify(rxdesc_pri, skb); -+ -+ u64_stats_update_begin(&rx_stats->syncp); -+ rx_stats->rx_pkts++; -+ rx_stats->rx_bytes += pkt_length; -+ rx_stats->rx_nr_frag_pkts += (u64)page_mode; -+ u64_stats_update_end(&rx_stats->syncp); -+ -+ skb->protocol = eth_type_trans(skb, skb->dev); -+ if (skb->dev->features & NETIF_F_GRO) -+ napi_gro_receive(&rxdesc_ring->napi, skb); -+ else -+ netif_receive_skb(skb); -+ -+ netdev_dbg(skb->dev, "edma_context:%p, skb:%p pkt_length:%u\n", -+ edma_ctx, skb, skb->len); -+ -+ return true; -+} -+ -+static struct net_device *edma_rx_get_src_dev(struct edma_rxdesc_stats *rxdesc_stats, -+ struct edma_rxdesc_pri *rxdesc_pri, -+ struct sk_buff *skb) -+{ -+ u32 src_info = EDMA_RXDESC_SRC_INFO_GET(rxdesc_pri); -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct net_device *ndev = NULL; -+ u8 src_port_num; -+ -+ /* Check src_info. */ -+ if (likely((src_info & EDMA_RXDESC_SRCINFO_TYPE_MASK) -+ == EDMA_RXDESC_SRCINFO_TYPE_PORTID)) { -+ src_port_num = src_info & EDMA_RXDESC_PORTNUM_BITS; -+ } else { -+ if (net_ratelimit()) { -+ pr_warn("Invalid src info_type:0x%x. Drop skb:%p\n", -+ (src_info & EDMA_RXDESC_SRCINFO_TYPE_MASK), skb); -+ } -+ -+ u64_stats_update_begin(&rxdesc_stats->syncp); -+ ++rxdesc_stats->src_port_inval_type; -+ u64_stats_update_end(&rxdesc_stats->syncp); -+ -+ return NULL; -+ } -+ -+ /* Packet with PP source. */ -+ if (likely(src_port_num <= hw_info->max_ports)) { -+ if (unlikely(src_port_num < EDMA_START_IFNUM)) { -+ if (net_ratelimit()) -+ pr_warn("Port number error :%d. Drop skb:%p\n", -+ src_port_num, skb); -+ -+ u64_stats_update_begin(&rxdesc_stats->syncp); -+ ++rxdesc_stats->src_port_inval; -+ u64_stats_update_end(&rxdesc_stats->syncp); -+ -+ return NULL; -+ } -+ -+ /* Get netdev for this port using the source port -+ * number as index into the netdev array. We need to -+ * subtract one since the indices start form '0' and -+ * port numbers start from '1'. -+ */ -+ ndev = edma_ctx->netdev_arr[src_port_num - 1]; -+ } -+ -+ if (likely(ndev)) -+ return ndev; -+ -+ if (net_ratelimit()) -+ pr_warn("Netdev Null src_info_type:0x%x src port num:%d Drop skb:%p\n", -+ (src_info & EDMA_RXDESC_SRCINFO_TYPE_MASK), -+ src_port_num, skb); -+ -+ u64_stats_update_begin(&rxdesc_stats->syncp); -+ ++rxdesc_stats->src_port_inval_netdev; -+ u64_stats_update_end(&rxdesc_stats->syncp); -+ -+ return NULL; -+} -+ -+static int edma_rx_reap(struct edma_rxdesc_ring *rxdesc_ring, int budget) -+{ -+ struct edma_rxdesc_stats *rxdesc_stats = &rxdesc_ring->rxdesc_stats; -+ u32 alloc_size = rxdesc_ring->rxfill->alloc_size; -+ bool page_mode = rxdesc_ring->rxfill->page_mode; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct edma_rxdesc_pri *next_rxdesc_pri; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct device *dev = ppe_dev->dev; -+ u32 prod_idx, cons_idx, end_idx; -+ u32 work_to_do, work_done = 0; -+ struct sk_buff *next_skb; -+ u32 work_leftover, reg; -+ -+ /* Get Rx ring producer and consumer indices. */ -+ cons_idx = rxdesc_ring->cons_idx; -+ -+ if (likely(rxdesc_ring->work_leftover > EDMA_RX_MAX_PROCESS)) { -+ work_to_do = rxdesc_ring->work_leftover; -+ } else { -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_PROD_IDX(rxdesc_ring->ring_id); -+ regmap_read(regmap, reg, &prod_idx); -+ prod_idx = prod_idx & EDMA_RXDESC_PROD_IDX_MASK; -+ work_to_do = EDMA_DESC_AVAIL_COUNT(prod_idx, -+ cons_idx, EDMA_RX_RING_SIZE); -+ rxdesc_ring->work_leftover = work_to_do; -+ } -+ -+ if (work_to_do > budget) -+ work_to_do = budget; -+ -+ rxdesc_ring->work_leftover -= work_to_do; -+ end_idx = (cons_idx + work_to_do) & EDMA_RX_RING_SIZE_MASK; -+ next_rxdesc_pri = EDMA_RXDESC_PRI_DESC(rxdesc_ring, cons_idx); -+ -+ /* Get opaque from RXDESC. */ -+ next_skb = (struct sk_buff *)EDMA_RXDESC_OPAQUE_GET(next_rxdesc_pri); -+ -+ work_leftover = work_to_do & (EDMA_RX_MAX_PROCESS - 1); -+ while (likely(work_to_do--)) { -+ struct edma_rxdesc_pri *rxdesc_pri; -+ struct net_device *ndev; -+ struct sk_buff *skb; -+ dma_addr_t dma_addr; -+ -+ skb = next_skb; -+ rxdesc_pri = next_rxdesc_pri; -+ dma_addr = EDMA_RXDESC_BUFFER_ADDR_GET(rxdesc_pri); -+ -+ if (!page_mode) -+ dma_unmap_single(dev, dma_addr, alloc_size, -+ DMA_TO_DEVICE); -+ else -+ dma_unmap_page(dev, dma_addr, PAGE_SIZE, DMA_TO_DEVICE); -+ -+ /* Update consumer index. */ -+ cons_idx = (cons_idx + 1) & EDMA_RX_RING_SIZE_MASK; -+ -+ /* Get the next Rx descriptor. */ -+ next_rxdesc_pri = EDMA_RXDESC_PRI_DESC(rxdesc_ring, cons_idx); -+ -+ /* Handle linear packets or initial segments first. */ -+ if (likely(!(rxdesc_ring->head))) { -+ ndev = edma_rx_get_src_dev(rxdesc_stats, rxdesc_pri, skb); -+ if (unlikely(!ndev)) { -+ dev_kfree_skb_any(skb); -+ goto next_rx_desc; -+ } -+ -+ /* Update skb fields for head skb. */ -+ skb->dev = ndev; -+ skb->skb_iif = ndev->ifindex; -+ -+ /* Handle linear packets. */ -+ if (likely(!EDMA_RXDESC_MORE_BIT_GET(rxdesc_pri))) { -+ next_skb = -+ (struct sk_buff *)EDMA_RXDESC_OPAQUE_GET(next_rxdesc_pri); -+ -+ if (unlikely(! -+ edma_rx_handle_linear_packets(rxdesc_ring, -+ rxdesc_pri, skb))) -+ dev_kfree_skb_any(skb); -+ -+ goto next_rx_desc; -+ } -+ } -+ -+ next_skb = (struct sk_buff *)EDMA_RXDESC_OPAQUE_GET(next_rxdesc_pri); -+ -+ /* Handle scatter frame processing for first/middle/last segments. */ -+ page_mode ? edma_rx_handle_nr_frags(rxdesc_ring, rxdesc_pri, skb) : -+ edma_rx_handle_frag_list(rxdesc_ring, rxdesc_pri, skb); -+ -+next_rx_desc: -+ /* Update work done. */ -+ work_done++; -+ -+ /* Check if we can refill EDMA_RX_MAX_PROCESS worth buffers, -+ * if yes, refill and update index before continuing. -+ */ -+ if (unlikely(!(work_done & (EDMA_RX_MAX_PROCESS - 1)))) { -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_CONS_IDX(rxdesc_ring->ring_id); -+ regmap_write(regmap, reg, cons_idx); -+ rxdesc_ring->cons_idx = cons_idx; -+ edma_rx_alloc_buffer_list(rxdesc_ring->rxfill, EDMA_RX_MAX_PROCESS); -+ } -+ } -+ -+ /* Check if we need to refill and update -+ * index for any buffers before exit. -+ */ -+ if (unlikely(work_leftover)) { -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_CONS_IDX(rxdesc_ring->ring_id); -+ regmap_write(regmap, reg, cons_idx); -+ rxdesc_ring->cons_idx = cons_idx; -+ edma_rx_alloc_buffer_list(rxdesc_ring->rxfill, work_leftover); -+ } -+ -+ return work_done; -+} -+ -+/** -+ * edma_rx_napi_poll - EDMA Rx napi poll. -+ * @napi: NAPI structure -+ * @budget: Rx NAPI budget -+ * -+ * EDMA RX NAPI handler to handle the NAPI poll. -+ * -+ * Return the number of packets processed. -+ */ -+int edma_rx_napi_poll(struct napi_struct *napi, int budget) -+{ -+ struct edma_rxdesc_ring *rxdesc_ring = (struct edma_rxdesc_ring *)napi; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ int work_done = 0; -+ u32 status, reg; -+ -+ do { -+ work_done += edma_rx_reap(rxdesc_ring, budget - work_done); -+ if (likely(work_done >= budget)) -+ return work_done; -+ -+ /* Check if there are more packets to process. */ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_INT_STAT(rxdesc_ring->ring_id); -+ regmap_read(regmap, reg, &status); -+ status = status & EDMA_RXDESC_RING_INT_STATUS_MASK; -+ } while (likely(status)); -+ -+ napi_complete(napi); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_INT_MASK(rxdesc_ring->ring_id); -+ regmap_write(regmap, reg, edma_ctx->intr_info.intr_mask_rx); -+ -+ return work_done; -+} -+ -+/** -+ * edma_rx_handle_irq - EDMA Rx handle irq. -+ * @irq: Interrupt to handle -+ * @ctx: Context -+ * -+ * Process RX IRQ and schedule NAPI. -+ * -+ * Return IRQ_HANDLED(1) on success. -+ */ -+irqreturn_t edma_rx_handle_irq(int irq, void *ctx) -+{ -+ struct edma_rxdesc_ring *rxdesc_ring = (struct edma_rxdesc_ring *)ctx; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ u32 reg; -+ -+ if (likely(napi_schedule_prep(&rxdesc_ring->napi))) { -+ /* Disable RxDesc interrupt. */ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_INT_MASK(rxdesc_ring->ring_id); -+ regmap_write(regmap, reg, EDMA_MASK_INT_DISABLE); -+ __napi_schedule(&rxdesc_ring->napi); -+ } -+ -+ return IRQ_HANDLED; -+} ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_rx.h -@@ -0,0 +1,287 @@ -+/* SPDX-License-Identifier: GPL-2.0-only -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#ifndef __EDMA_RX__ -+#define __EDMA_RX__ -+ -+#include -+ -+#define EDMA_RXFILL_RING_PER_CORE_MAX 1 -+#define EDMA_RXDESC_RING_PER_CORE_MAX 1 -+ -+/* Max Rx processing without replenishing RxFill ring. */ -+#define EDMA_RX_MAX_PROCESS 32 -+ -+#define EDMA_RX_SKB_HEADROOM 128 -+#define EDMA_RX_QUEUE_START 0 -+#define EDMA_RX_BUFFER_SIZE 1984 -+#define EDMA_MAX_CORE 4 -+ -+#define EDMA_GET_DESC(R, i, type) (&(((type *)((R)->desc))[(i)])) -+#define EDMA_GET_PDESC(R, i, type) (&(((type *)((R)->pdesc))[(i)])) -+#define EDMA_GET_SDESC(R, i, type) (&(((type *)((R)->sdesc))[(i)])) -+#define EDMA_RXFILL_DESC(R, i) EDMA_GET_DESC(R, i, \ -+ struct edma_rxfill_desc) -+#define EDMA_RXDESC_PRI_DESC(R, i) EDMA_GET_PDESC(R, i, \ -+ struct edma_rxdesc_pri) -+#define EDMA_RXDESC_SEC_DESC(R, i) EDMA_GET_SDESC(R, i, \ -+ struct edma_rxdesc_sec) -+ -+#define EDMA_RX_RING_SIZE 2048 -+ -+#define EDMA_RX_RING_SIZE_MASK (EDMA_RX_RING_SIZE - 1) -+#define EDMA_RX_RING_ID_MASK 0x1F -+ -+#define EDMA_MAX_PRI_PER_CORE 8 -+#define EDMA_RX_PID_IPV4_MAX 0x3 -+#define EDMA_RX_PID_IPV6 0x4 -+#define EDMA_RX_PID_IS_IPV4(pid) (!((pid) & (~EDMA_RX_PID_IPV4_MAX))) -+#define EDMA_RX_PID_IS_IPV6(pid) (!(!((pid) & EDMA_RX_PID_IPV6))) -+ -+#define EDMA_RXDESC_BUFFER_ADDR_GET(desc) \ -+ ((u32)(le32_to_cpu((__force __le32)((desc)->word0)))) -+#define EDMA_RXDESC_OPAQUE_GET(_desc) ({ \ -+ typeof(_desc) (desc) = (_desc); \ -+ ((uintptr_t)((u64)((desc)->word2) | \ -+ ((u64)((desc)->word3) << 0x20))); }) -+ -+#define EDMA_RXDESC_SRCINFO_TYPE_PORTID 0x2000 -+#define EDMA_RXDESC_SRCINFO_TYPE_MASK 0xF000 -+#define EDMA_RXDESC_L3CSUM_STATUS_MASK BIT(13) -+#define EDMA_RXDESC_L4CSUM_STATUS_MASK BIT(12) -+#define EDMA_RXDESC_PORTNUM_BITS 0x0FFF -+ -+#define EDMA_RXDESC_PACKET_LEN_MASK 0x3FFFF -+#define EDMA_RXDESC_PACKET_LEN_GET(_desc) ({ \ -+ typeof(_desc) (desc) = (_desc); \ -+ ((le32_to_cpu((__force __le32)((desc)->word5))) & \ -+ EDMA_RXDESC_PACKET_LEN_MASK); }) -+ -+#define EDMA_RXDESC_MORE_BIT_MASK 0x40000000 -+#define EDMA_RXDESC_MORE_BIT_GET(desc) ((le32_to_cpu((__force __le32)((desc)->word1))) & \ -+ EDMA_RXDESC_MORE_BIT_MASK) -+#define EDMA_RXDESC_SRC_DST_INFO_GET(desc) \ -+ ((u32)((le32_to_cpu((__force __le32)((desc)->word4))))) -+ -+#define EDMA_RXDESC_L3_OFFSET_MASK GENMASK(23, 16) -+#define EDMA_RXDESC_L3_OFFSET_GET(desc) FIELD_GET(EDMA_RXDESC_L3_OFFSET_MASK, \ -+ le32_to_cpu((__force __le32)((desc)->word7))) -+ -+#define EDMA_RXDESC_PID_MASK GENMASK(15, 12) -+#define EDMA_RXDESC_PID_GET(desc) FIELD_GET(EDMA_RXDESC_PID_MASK, \ -+ le32_to_cpu((__force __le32)((desc)->word7))) -+ -+#define EDMA_RXDESC_DST_INFO_MASK GENMASK(31, 16) -+#define EDMA_RXDESC_DST_INFO_GET(desc) FIELD_GET(EDMA_RXDESC_DST_INFO_MASK, \ -+ le32_to_cpu((__force __le32)((desc)->word4))) -+ -+#define EDMA_RXDESC_SRC_INFO_MASK GENMASK(15, 0) -+#define EDMA_RXDESC_SRC_INFO_GET(desc) FIELD_GET(EDMA_RXDESC_SRC_INFO_MASK, \ -+ le32_to_cpu((__force __le32)((desc)->word4))) -+ -+#define EDMA_RXDESC_PORT_ID_MASK GENMASK(11, 0) -+#define EDMA_RXDESC_PORT_ID_GET(x) FIELD_GET(EDMA_RXDESC_PORT_ID_MASK, x) -+ -+#define EDMA_RXDESC_SRC_PORT_ID_GET(desc) (EDMA_RXDESC_PORT_ID_GET \ -+ (EDMA_RXDESC_SRC_INFO_GET(desc))) -+#define EDMA_RXDESC_DST_PORT_ID_GET(desc) (EDMA_RXDESC_PORT_ID_GET \ -+ (EDMA_RXDESC_DST_INFO_GET(desc))) -+ -+#define EDMA_RXDESC_DST_PORT (0x2 << EDMA_RXDESC_PID_SHIFT) -+ -+#define EDMA_RXDESC_L3CSUM_STATUS_GET(desc) FIELD_GET(EDMA_RXDESC_L3CSUM_STATUS_MASK, \ -+ le32_to_cpu((__force __le32)(desc)->word6)) -+#define EDMA_RXDESC_L4CSUM_STATUS_GET(desc) FIELD_GET(EDMA_RXDESC_L4CSUM_STATUS_MASK, \ -+ le32_to_cpu((__force __le32)(desc)->word6)) -+ -+#define EDMA_RXDESC_DATA_OFFSET_MASK GENMASK(11, 0) -+#define EDMA_RXDESC_DATA_OFFSET_GET(desc) FIELD_GET(EDMA_RXDESC_DATA_OFFSET_MASK, \ -+ le32_to_cpu((__force __le32)(desc)->word6)) -+ -+#define EDMA_RXFILL_BUF_SIZE_MASK 0xFFFF -+#define EDMA_RXFILL_BUF_SIZE_SHIFT 16 -+ -+/* Opaque values are not accessed by the EDMA HW, -+ * so endianness conversion is not needed. -+ */ -+ -+#define EDMA_RXFILL_OPAQUE_LO_SET(desc, ptr) (((desc)->word2) = \ -+ (u32)(uintptr_t)(ptr)) -+#ifdef __LP64__ -+#define EDMA_RXFILL_OPAQUE_HI_SET(desc, ptr) (((desc)->word3) = \ -+ (u32)((u64)(ptr) >> 0x20)) -+#endif -+ -+#define EDMA_RXFILL_OPAQUE_GET(_desc) ({ \ -+ typeof(_desc) (desc) = (_desc); \ -+ ((uintptr_t)((u64)((desc)->word2) | \ -+ ((u64)((desc)->word3) << 0x20))); }) -+ -+#define EDMA_RXFILL_PACKET_LEN_SET(desc, len) { \ -+ (((desc)->word1) = (u32)((((u32)len) << EDMA_RXFILL_BUF_SIZE_SHIFT) & \ -+ 0xFFFF0000)); \ -+} -+ -+#define EDMA_RXFILL_BUFFER_ADDR_SET(desc, addr) (((desc)->word0) = (u32)(addr)) -+ -+/* Opaque values are set in word2 and word3, they are not accessed by the EDMA HW, -+ * so endianness conversion is not needed. -+ */ -+#define EDMA_RXFILL_ENDIAN_SET(_desc) ({ \ -+ typeof(_desc) (desc) = (_desc); \ -+ cpu_to_le32s(&((desc)->word0)); \ -+ cpu_to_le32s(&((desc)->word1)); \ -+}) -+ -+/* RX DESC size shift to obtain index from descriptor pointer. */ -+#define EDMA_RXDESC_SIZE_SHIFT 5 -+ -+/** -+ * struct edma_rxdesc_stats - RX descriptor ring stats. -+ * @src_port_inval: Invalid source port number -+ * @src_port_inval_type: Source type is not PORT ID -+ * @src_port_inval_netdev: Invalid net device for the source port -+ * @syncp: Synchronization pointer -+ */ -+struct edma_rxdesc_stats { -+ u64 src_port_inval; -+ u64 src_port_inval_type; -+ u64 src_port_inval_netdev; -+ struct u64_stats_sync syncp; -+}; -+ -+/** -+ * struct edma_rxfill_stats - Rx fill descriptor ring stats. -+ * @alloc_failed: Buffer allocation failure count -+ * @page_alloc_failed: Page allocation failure count for page mode -+ * @syncp: Synchronization pointer -+ */ -+struct edma_rxfill_stats { -+ u64 alloc_failed; -+ u64 page_alloc_failed; -+ struct u64_stats_sync syncp; -+}; -+ -+/** -+ * struct edma_rxdesc_pri - Rx descriptor. -+ * @word0: Buffer address -+ * @word1: More bit, priority bit, service code -+ * @word2: Opaque low bits -+ * @word3: Opaque high bits -+ * @word4: Destination and source information -+ * @word5: WiFi QoS, data length -+ * @word6: Hash value, check sum status -+ * @word7: DSCP, packet offsets -+ */ -+struct edma_rxdesc_pri { -+ u32 word0; -+ u32 word1; -+ u32 word2; -+ u32 word3; -+ u32 word4; -+ u32 word5; -+ u32 word6; -+ u32 word7; -+}; -+ -+ /** -+ * struct edma_rxdesc_sec - Rx secondary descriptor. -+ * @word0: Timestamp -+ * @word1: Secondary checksum status -+ * @word2: QoS tag -+ * @word3: Flow index details -+ * @word4: Secondary packet offsets -+ * @word5: Multicast bit, checksum -+ * @word6: SVLAN, CVLAN -+ * @word7: Secondary SVLAN, CVLAN -+ */ -+struct edma_rxdesc_sec { -+ u32 word0; -+ u32 word1; -+ u32 word2; -+ u32 word3; -+ u32 word4; -+ u32 word5; -+ u32 word6; -+ u32 word7; -+}; -+ -+/** -+ * struct edma_rxfill_desc - RxFill descriptor. -+ * @word0: Buffer address -+ * @word1: Buffer size -+ * @word2: Opaque low bits -+ * @word3: Opaque high bits -+ */ -+struct edma_rxfill_desc { -+ u32 word0; -+ u32 word1; -+ u32 word2; -+ u32 word3; -+}; -+ -+/** -+ * struct edma_rxfill_ring - RxFill ring -+ * @ring_id: RxFill ring number -+ * @count: Number of descriptors in the ring -+ * @prod_idx: Ring producer index -+ * @alloc_size: Buffer size to allocate -+ * @desc: Descriptor ring virtual address -+ * @dma: Descriptor ring physical address -+ * @buf_len: Buffer length for rxfill descriptor -+ * @page_mode: Page mode for Rx processing -+ * @rx_fill_stats: Rx fill ring statistics -+ */ -+struct edma_rxfill_ring { -+ u32 ring_id; -+ u32 count; -+ u32 prod_idx; -+ u32 alloc_size; -+ struct edma_rxfill_desc *desc; -+ dma_addr_t dma; -+ u32 buf_len; -+ bool page_mode; -+ struct edma_rxfill_stats rxfill_stats; -+}; -+ -+/** -+ * struct edma_rxdesc_ring - RxDesc ring -+ * @napi: Pointer to napi -+ * @ring_id: Rxdesc ring number -+ * @count: Number of descriptors in the ring -+ * @work_leftover: Leftover descriptors to be processed -+ * @cons_idx: Ring consumer index -+ * @pdesc: Primary descriptor ring virtual address -+ * @pdesc_head: Primary descriptor head in case of scatter-gather frame -+ * @sdesc: Secondary descriptor ring virtual address -+ * @rxdesc_stats: Rx descriptor ring statistics -+ * @rxfill: RxFill ring used -+ * @napi_added: Flag to indicate NAPI add status -+ * @pdma: Primary descriptor ring physical address -+ * @sdma: Secondary descriptor ring physical address -+ * @head: Head of the skb list in case of scatter-gather frame -+ * @last: Last skb of the skb list in case of scatter-gather frame -+ */ -+struct edma_rxdesc_ring { -+ struct napi_struct napi; -+ u32 ring_id; -+ u32 count; -+ u32 work_leftover; -+ u32 cons_idx; -+ struct edma_rxdesc_pri *pdesc; -+ struct edma_rxdesc_pri *pdesc_head; -+ struct edma_rxdesc_sec *sdesc; -+ struct edma_rxdesc_stats rxdesc_stats; -+ struct edma_rxfill_ring *rxfill; -+ bool napi_added; -+ dma_addr_t pdma; -+ dma_addr_t sdma; -+ struct sk_buff *head; -+ struct sk_buff *last; -+}; -+ -+irqreturn_t edma_rx_handle_irq(int irq, void *ctx); -+int edma_rx_alloc_buffer(struct edma_rxfill_ring *rxfill_ring, int alloc_count); -+int edma_rx_napi_poll(struct napi_struct *napi, int budget); -+#endif diff --git a/target/linux/qualcommbe/patches-6.12/0345-net-ethernet-qualcomm-Add-Tx-Ethernet-DMA-support.patch b/target/linux/qualcommbe/patches-6.12/0345-net-ethernet-qualcomm-Add-Tx-Ethernet-DMA-support.patch deleted file mode 100644 index 39d300de80..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0345-net-ethernet-qualcomm-Add-Tx-Ethernet-DMA-support.patch +++ /dev/null @@ -1,2363 +0,0 @@ -From 339d3a5365f150a78ed405684e379fee3acdbe90 Mon Sep 17 00:00:00 2001 -From: Suruchi Agarwal -Date: Thu, 21 Mar 2024 16:26:29 -0700 -Subject: [PATCH] net: ethernet: qualcomm: Add Tx Ethernet DMA support - -Add Tx queues, rings, descriptors configurations and -DMA support for the EDMA. - -Change-Id: Idfb0e1fe5ac494d614097d6c97dd15d63bbce8e6 -Co-developed-by: Pavithra R -Signed-off-by: Pavithra R -Signed-off-by: Suruchi Agarwal ---- - drivers/net/ethernet/qualcomm/ppe/Makefile | 2 +- - drivers/net/ethernet/qualcomm/ppe/edma.c | 97 ++- - drivers/net/ethernet/qualcomm/ppe/edma.h | 7 + - .../net/ethernet/qualcomm/ppe/edma_cfg_tx.c | 648 ++++++++++++++ - .../net/ethernet/qualcomm/ppe/edma_cfg_tx.h | 28 + - drivers/net/ethernet/qualcomm/ppe/edma_port.c | 136 +++ - drivers/net/ethernet/qualcomm/ppe/edma_port.h | 35 + - drivers/net/ethernet/qualcomm/ppe/edma_tx.c | 808 ++++++++++++++++++ - drivers/net/ethernet/qualcomm/ppe/edma_tx.h | 302 +++++++ - 9 files changed, 2055 insertions(+), 8 deletions(-) - create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma_cfg_tx.c - create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma_cfg_tx.h - create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma_tx.c - create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma_tx.h - ---- a/drivers/net/ethernet/qualcomm/ppe/Makefile -+++ b/drivers/net/ethernet/qualcomm/ppe/Makefile -@@ -7,4 +7,4 @@ obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o - qcom-ppe-objs := ppe.o ppe_config.o ppe_debugfs.o ppe_port.o - - #EDMA --qcom-ppe-objs += edma.o edma_cfg_rx.o edma_port.o edma_rx.o -+qcom-ppe-objs += edma.o edma_cfg_rx.o edma_cfg_tx.o edma_port.o edma_rx.o edma_tx.o ---- a/drivers/net/ethernet/qualcomm/ppe/edma.c -+++ b/drivers/net/ethernet/qualcomm/ppe/edma.c -@@ -18,6 +18,7 @@ - #include - - #include "edma.h" -+#include "edma_cfg_tx.h" - #include "edma_cfg_rx.h" - #include "ppe_regs.h" - -@@ -25,6 +26,7 @@ - - /* Global EDMA context. */ - struct edma_context *edma_ctx; -+static char **edma_txcmpl_irq_name; - static char **edma_rxdesc_irq_name; - - /* Module params. */ -@@ -192,22 +194,59 @@ static int edma_configure_ucast_prio_map - static int edma_irq_register(void) - { - struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *txcmpl = hw_info->txcmpl; - struct edma_ring_info *rx = hw_info->rx; - int ret; - u32 i; - -+ /* Request IRQ for TXCMPL rings. */ -+ edma_txcmpl_irq_name = kzalloc((sizeof(char *) * txcmpl->num_rings), GFP_KERNEL); -+ if (!edma_txcmpl_irq_name) -+ return -ENOMEM; -+ -+ for (i = 0; i < txcmpl->num_rings; i++) { -+ edma_txcmpl_irq_name[i] = kzalloc((sizeof(char *) * EDMA_IRQ_NAME_SIZE), -+ GFP_KERNEL); -+ if (!edma_txcmpl_irq_name[i]) { -+ ret = -ENOMEM; -+ goto txcmpl_ring_irq_name_alloc_fail; -+ } -+ -+ snprintf(edma_txcmpl_irq_name[i], EDMA_IRQ_NAME_SIZE, "edma_txcmpl_%d", -+ txcmpl->ring_start + i); -+ -+ irq_set_status_flags(edma_ctx->intr_info.intr_txcmpl[i], IRQ_DISABLE_UNLAZY); -+ -+ ret = request_irq(edma_ctx->intr_info.intr_txcmpl[i], -+ edma_tx_handle_irq, IRQF_SHARED, -+ edma_txcmpl_irq_name[i], -+ (void *)&edma_ctx->txcmpl_rings[i]); -+ if (ret) { -+ pr_err("TXCMPL ring IRQ:%d request %d failed\n", -+ edma_ctx->intr_info.intr_txcmpl[i], i); -+ goto txcmpl_ring_intr_req_fail; -+ } -+ -+ pr_debug("TXCMPL ring: %d IRQ:%d request success: %s\n", -+ txcmpl->ring_start + i, -+ edma_ctx->intr_info.intr_txcmpl[i], -+ edma_txcmpl_irq_name[i]); -+ } -+ - /* Request IRQ for RXDESC rings. */ - edma_rxdesc_irq_name = kzalloc((sizeof(char *) * rx->num_rings), - GFP_KERNEL); -- if (!edma_rxdesc_irq_name) -- return -ENOMEM; -+ if (!edma_rxdesc_irq_name) { -+ ret = -ENOMEM; -+ goto rxdesc_irq_name_alloc_fail; -+ } - - for (i = 0; i < rx->num_rings; i++) { - edma_rxdesc_irq_name[i] = kzalloc((sizeof(char *) * EDMA_IRQ_NAME_SIZE), - GFP_KERNEL); - if (!edma_rxdesc_irq_name[i]) { - ret = -ENOMEM; -- goto rxdesc_irq_name_alloc_fail; -+ goto rxdesc_ring_irq_name_alloc_fail; - } - - snprintf(edma_rxdesc_irq_name[i], 20, "edma_rxdesc_%d", -@@ -236,8 +275,19 @@ static int edma_irq_register(void) - rx_desc_ring_intr_req_fail: - for (i = 0; i < rx->num_rings; i++) - kfree(edma_rxdesc_irq_name[i]); --rxdesc_irq_name_alloc_fail: -+rxdesc_ring_irq_name_alloc_fail: - kfree(edma_rxdesc_irq_name); -+rxdesc_irq_name_alloc_fail: -+ for (i = 0; i < txcmpl->num_rings; i++) { -+ synchronize_irq(edma_ctx->intr_info.intr_txcmpl[i]); -+ free_irq(edma_ctx->intr_info.intr_txcmpl[i], -+ (void *)&edma_ctx->txcmpl_rings[i]); -+ } -+txcmpl_ring_intr_req_fail: -+ for (i = 0; i < txcmpl->num_rings; i++) -+ kfree(edma_txcmpl_irq_name[i]); -+txcmpl_ring_irq_name_alloc_fail: -+ kfree(edma_txcmpl_irq_name); - - return ret; - } -@@ -326,12 +376,22 @@ static int edma_irq_init(void) - - static int edma_alloc_rings(void) - { -+ if (edma_cfg_tx_rings_alloc()) { -+ pr_err("Error in allocating Tx rings\n"); -+ return -ENOMEM; -+ } -+ - if (edma_cfg_rx_rings_alloc()) { - pr_err("Error in allocating Rx rings\n"); -- return -ENOMEM; -+ goto rx_rings_alloc_fail; - } - - return 0; -+ -+rx_rings_alloc_fail: -+ edma_cfg_tx_rings_cleanup(); -+ -+ return -ENOMEM; - } - - static int edma_hw_reset(void) -@@ -389,7 +449,7 @@ static int edma_hw_configure(void) - struct edma_hw_info *hw_info = edma_ctx->hw_info; - struct ppe_device *ppe_dev = edma_ctx->ppe_dev; - struct regmap *regmap = ppe_dev->regmap; -- u32 data, reg; -+ u32 data, reg, i; - int ret; - - reg = EDMA_BASE_OFFSET + EDMA_REG_MAS_CTRL_ADDR; -@@ -439,11 +499,17 @@ static int edma_hw_configure(void) - } - - /* Disable interrupts. */ -+ for (i = 1; i <= hw_info->max_ports; i++) -+ edma_cfg_tx_disable_interrupts(i); -+ - edma_cfg_rx_disable_interrupts(); - - edma_cfg_rx_rings_disable(); - - edma_cfg_rx_ring_mappings(); -+ edma_cfg_tx_ring_mappings(); -+ -+ edma_cfg_tx_rings(); - - ret = edma_cfg_rx_rings(); - if (ret) { -@@ -520,6 +586,7 @@ configure_ucast_prio_map_tbl_failed: - edma_cfg_rx_napi_delete(); - edma_cfg_rx_rings_disable(); - edma_cfg_rx_rings_failed: -+ edma_cfg_tx_rings_cleanup(); - edma_cfg_rx_rings_cleanup(); - edma_alloc_rings_failed: - free_netdev(edma_ctx->dummy_dev); -@@ -538,13 +605,27 @@ dummy_dev_alloc_failed: - void edma_destroy(struct ppe_device *ppe_dev) - { - struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *txcmpl = hw_info->txcmpl; - struct edma_ring_info *rx = hw_info->rx; - u32 i; - - /* Disable interrupts. */ -+ for (i = 1; i <= hw_info->max_ports; i++) -+ edma_cfg_tx_disable_interrupts(i); -+ - edma_cfg_rx_disable_interrupts(); - -- /* Free IRQ for RXDESC rings. */ -+ /* Free IRQ for TXCMPL rings. */ -+ for (i = 0; i < txcmpl->num_rings; i++) { -+ synchronize_irq(edma_ctx->intr_info.intr_txcmpl[i]); -+ -+ free_irq(edma_ctx->intr_info.intr_txcmpl[i], -+ (void *)&edma_ctx->txcmpl_rings[i]); -+ kfree(edma_txcmpl_irq_name[i]); -+ } -+ kfree(edma_txcmpl_irq_name); -+ -+ /* Free IRQ for RXDESC rings */ - for (i = 0; i < rx->num_rings; i++) { - synchronize_irq(edma_ctx->intr_info.intr_rx[i]); - free_irq(edma_ctx->intr_info.intr_rx[i], -@@ -560,6 +641,7 @@ void edma_destroy(struct ppe_device *ppe - edma_cfg_rx_napi_delete(); - edma_cfg_rx_rings_disable(); - edma_cfg_rx_rings_cleanup(); -+ edma_cfg_tx_rings_cleanup(); - - free_netdev(edma_ctx->dummy_dev); - kfree(edma_ctx->netdev_arr); -@@ -585,6 +667,7 @@ int edma_setup(struct ppe_device *ppe_de - edma_ctx->hw_info = &ipq9574_hw_info; - edma_ctx->ppe_dev = ppe_dev; - edma_ctx->rx_buf_size = rx_buff_size; -+ edma_ctx->tx_requeue_stop = false; - - /* Configure the EDMA common clocks. */ - ret = edma_clock_init(); ---- a/drivers/net/ethernet/qualcomm/ppe/edma.h -+++ b/drivers/net/ethernet/qualcomm/ppe/edma.h -@@ -7,6 +7,7 @@ - - #include "ppe_config.h" - #include "edma_rx.h" -+#include "edma_tx.h" - - /* One clock cycle = 1/(EDMA clock frequency in Mhz) micro seconds. - * -@@ -104,8 +105,11 @@ struct edma_intr_info { - * @intr_info: EDMA Interrupt info - * @rxfill_rings: Rx fill Rings, SW is producer - * @rx_rings: Rx Desc Rings, SW is consumer -+ * @tx_rings: Tx Descriptor Ring, SW is producer -+ * @txcmpl_rings: Tx complete Ring, SW is consumer - * @rx_page_mode: Page mode enabled or disabled - * @rx_buf_size: Rx buffer size for Jumbo MRU -+ * @tx_requeue_stop: Tx requeue stop enabled or disabled - */ - struct edma_context { - struct net_device **netdev_arr; -@@ -115,8 +119,11 @@ struct edma_context { - struct edma_intr_info intr_info; - struct edma_rxfill_ring *rxfill_rings; - struct edma_rxdesc_ring *rx_rings; -+ struct edma_txdesc_ring *tx_rings; -+ struct edma_txcmpl_ring *txcmpl_rings; - u32 rx_page_mode; - u32 rx_buf_size; -+ bool tx_requeue_stop; - }; - - /* Global EDMA context */ ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_cfg_tx.c -@@ -0,0 +1,648 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+/* Configure rings, Buffers and NAPI for transmit path along with -+ * providing APIs to enable, disable, clean and map the Tx rings. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "edma.h" -+#include "edma_cfg_tx.h" -+#include "edma_port.h" -+#include "ppe.h" -+#include "ppe_regs.h" -+ -+static void edma_cfg_txcmpl_ring_cleanup(struct edma_txcmpl_ring *txcmpl_ring) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct device *dev = ppe_dev->dev; -+ -+ /* Free any buffers assigned to any descriptors. */ -+ edma_tx_complete(EDMA_TX_RING_SIZE - 1, txcmpl_ring); -+ -+ /* Free TxCmpl ring descriptors. */ -+ dma_free_coherent(dev, sizeof(struct edma_txcmpl_desc) -+ * txcmpl_ring->count, txcmpl_ring->desc, -+ txcmpl_ring->dma); -+ txcmpl_ring->desc = NULL; -+ txcmpl_ring->dma = (dma_addr_t)0; -+} -+ -+static int edma_cfg_txcmpl_ring_setup(struct edma_txcmpl_ring *txcmpl_ring) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct device *dev = ppe_dev->dev; -+ -+ /* Allocate RxFill ring descriptors. */ -+ txcmpl_ring->desc = dma_alloc_coherent(dev, sizeof(struct edma_txcmpl_desc) -+ * txcmpl_ring->count, -+ &txcmpl_ring->dma, -+ GFP_KERNEL | __GFP_ZERO); -+ -+ if (unlikely(!txcmpl_ring->desc)) -+ return -ENOMEM; -+ -+ return 0; -+} -+ -+static void edma_cfg_tx_desc_ring_cleanup(struct edma_txdesc_ring *txdesc_ring) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct edma_txdesc_pri *txdesc = NULL; -+ struct device *dev = ppe_dev->dev; -+ u32 prod_idx, cons_idx, data, reg; -+ struct sk_buff *skb = NULL; -+ -+ /* Free any buffers assigned to any descriptors. */ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC_PROD_IDX(txdesc_ring->id); -+ regmap_read(regmap, reg, &data); -+ prod_idx = data & EDMA_TXDESC_PROD_IDX_MASK; -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC_CONS_IDX(txdesc_ring->id); -+ regmap_read(regmap, reg, &data); -+ cons_idx = data & EDMA_TXDESC_CONS_IDX_MASK; -+ -+ /* Walk active list, obtain skb from descriptor and free it. */ -+ while (cons_idx != prod_idx) { -+ txdesc = EDMA_TXDESC_PRI_DESC(txdesc_ring, cons_idx); -+ skb = (struct sk_buff *)EDMA_TXDESC_OPAQUE_GET(txdesc); -+ dev_kfree_skb_any(skb); -+ -+ cons_idx = ((cons_idx + 1) & EDMA_TX_RING_SIZE_MASK); -+ } -+ -+ /* Free Tx ring descriptors. */ -+ dma_free_coherent(dev, (sizeof(struct edma_txdesc_pri) -+ * txdesc_ring->count), -+ txdesc_ring->pdesc, -+ txdesc_ring->pdma); -+ txdesc_ring->pdesc = NULL; -+ txdesc_ring->pdma = (dma_addr_t)0; -+ -+ /* Free any buffers assigned to any secondary descriptors. */ -+ dma_free_coherent(dev, (sizeof(struct edma_txdesc_sec) -+ * txdesc_ring->count), -+ txdesc_ring->sdesc, -+ txdesc_ring->sdma); -+ txdesc_ring->sdesc = NULL; -+ txdesc_ring->sdma = (dma_addr_t)0; -+} -+ -+static int edma_cfg_tx_desc_ring_setup(struct edma_txdesc_ring *txdesc_ring) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct device *dev = ppe_dev->dev; -+ -+ /* Allocate RxFill ring descriptors. */ -+ txdesc_ring->pdesc = dma_alloc_coherent(dev, sizeof(struct edma_txdesc_pri) -+ * txdesc_ring->count, -+ &txdesc_ring->pdma, -+ GFP_KERNEL | __GFP_ZERO); -+ -+ if (unlikely(!txdesc_ring->pdesc)) -+ return -ENOMEM; -+ -+ txdesc_ring->sdesc = dma_alloc_coherent(dev, sizeof(struct edma_txdesc_sec) -+ * txdesc_ring->count, -+ &txdesc_ring->sdma, -+ GFP_KERNEL | __GFP_ZERO); -+ -+ if (unlikely(!txdesc_ring->sdesc)) { -+ dma_free_coherent(dev, (sizeof(struct edma_txdesc_pri) -+ * txdesc_ring->count), -+ txdesc_ring->pdesc, -+ txdesc_ring->pdma); -+ txdesc_ring->pdesc = NULL; -+ txdesc_ring->pdma = (dma_addr_t)0; -+ return -ENOMEM; -+ } -+ -+ return 0; -+} -+ -+static void edma_cfg_tx_desc_ring_configure(struct edma_txdesc_ring *txdesc_ring) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ u32 data, reg; -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC_BA(txdesc_ring->id); -+ regmap_write(regmap, reg, (u32)(txdesc_ring->pdma & EDMA_RING_DMA_MASK)); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC_BA2(txdesc_ring->id); -+ regmap_write(regmap, reg, (u32)(txdesc_ring->sdma & EDMA_RING_DMA_MASK)); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC_RING_SIZE(txdesc_ring->id); -+ regmap_write(regmap, reg, (u32)(txdesc_ring->count & EDMA_TXDESC_RING_SIZE_MASK)); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC_PROD_IDX(txdesc_ring->id); -+ regmap_write(regmap, reg, (u32)EDMA_TX_INITIAL_PROD_IDX); -+ -+ data = FIELD_PREP(EDMA_TXDESC_CTRL_FC_GRP_ID_MASK, txdesc_ring->fc_grp_id); -+ -+ /* Configure group ID for flow control for this Tx ring. */ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC_CTRL(txdesc_ring->id); -+ regmap_write(regmap, reg, data); -+} -+ -+static void edma_cfg_txcmpl_ring_configure(struct edma_txcmpl_ring *txcmpl_ring) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ u32 data, reg; -+ -+ /* Configure TxCmpl ring base address. */ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXCMPL_BA(txcmpl_ring->id); -+ regmap_write(regmap, reg, (u32)(txcmpl_ring->dma & EDMA_RING_DMA_MASK)); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXCMPL_RING_SIZE(txcmpl_ring->id); -+ regmap_write(regmap, reg, (u32)(txcmpl_ring->count & EDMA_TXDESC_RING_SIZE_MASK)); -+ -+ /* Set TxCmpl ret mode to opaque. */ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXCMPL_CTRL(txcmpl_ring->id); -+ regmap_write(regmap, reg, EDMA_TXCMPL_RETMODE_OPAQUE); -+ -+ /* Configure the Mitigation timer. */ -+ data = EDMA_MICROSEC_TO_TIMER_UNIT(EDMA_TX_MITIGATION_TIMER_DEF, -+ ppe_dev->clk_rate / MHZ); -+ data = ((data & EDMA_TX_MOD_TIMER_INIT_MASK) -+ << EDMA_TX_MOD_TIMER_INIT_SHIFT); -+ pr_debug("EDMA Tx mitigation timer value: %d\n", data); -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TX_MOD_TIMER(txcmpl_ring->id); -+ regmap_write(regmap, reg, data); -+ -+ /* Configure the Mitigation packet count. */ -+ data = (EDMA_TX_MITIGATION_PKT_CNT_DEF & EDMA_TXCMPL_LOW_THRE_MASK) -+ << EDMA_TXCMPL_LOW_THRE_SHIFT; -+ pr_debug("EDMA Tx mitigation packet count value: %d\n", data); -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXCMPL_UGT_THRE(txcmpl_ring->id); -+ regmap_write(regmap, reg, data); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TX_INT_CTRL(txcmpl_ring->id); -+ regmap_write(regmap, reg, EDMA_TX_NE_INT_EN); -+} -+ -+/** -+ * edma_cfg_tx_fill_per_port_tx_map - Fill Tx ring mapping. -+ * @netdev: Netdevice. -+ * @port_id: Port ID. -+ * -+ * Fill per-port Tx ring mapping in net device private area. -+ */ -+void edma_cfg_tx_fill_per_port_tx_map(struct net_device *netdev, u32 port_id) -+{ -+ u32 i; -+ -+ /* Ring to core mapping is done in order starting from 0 for port 1. */ -+ for_each_possible_cpu(i) { -+ struct edma_port_priv *port_dev = (struct edma_port_priv *)netdev_priv(netdev); -+ struct edma_txdesc_ring *txdesc_ring; -+ u32 txdesc_ring_id; -+ -+ txdesc_ring_id = ((port_id - 1) * num_possible_cpus()) + i; -+ txdesc_ring = &edma_ctx->tx_rings[txdesc_ring_id]; -+ port_dev->txr_map[i] = txdesc_ring; -+ } -+} -+ -+/** -+ * edma_cfg_tx_rings_enable - Enable Tx rings. -+ * -+ * Enable Tx rings. -+ */ -+void edma_cfg_tx_rings_enable(u32 port_id) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct edma_txdesc_ring *txdesc_ring; -+ u32 i, ring_idx, reg; -+ -+ for_each_possible_cpu(i) { -+ ring_idx = ((port_id - 1) * num_possible_cpus()) + i; -+ txdesc_ring = &edma_ctx->tx_rings[ring_idx]; -+ u32 data; -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC_CTRL(txdesc_ring->id); -+ regmap_read(regmap, reg, &data); -+ data |= FIELD_PREP(EDMA_TXDESC_CTRL_TXEN_MASK, EDMA_TXDESC_TX_ENABLE); -+ -+ regmap_write(regmap, reg, data); -+ } -+} -+ -+/** -+ * edma_cfg_tx_rings_disable - Disable Tx rings. -+ * -+ * Disable Tx rings. -+ */ -+void edma_cfg_tx_rings_disable(u32 port_id) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct edma_txdesc_ring *txdesc_ring; -+ u32 i, ring_idx, reg; -+ -+ for_each_possible_cpu(i) { -+ ring_idx = ((port_id - 1) * num_possible_cpus()) + i; -+ txdesc_ring = &edma_ctx->tx_rings[ring_idx]; -+ u32 data; -+ -+ txdesc_ring = &edma_ctx->tx_rings[i]; -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC_CTRL(txdesc_ring->id); -+ regmap_read(regmap, reg, &data); -+ data &= ~EDMA_TXDESC_TX_ENABLE; -+ regmap_write(regmap, reg, data); -+ } -+} -+ -+/** -+ * edma_cfg_tx_ring_mappings - Map Tx to Tx complete rings. -+ * -+ * Map Tx to Tx complete rings. -+ */ -+void edma_cfg_tx_ring_mappings(void) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *txcmpl = hw_info->txcmpl; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct edma_ring_info *tx = hw_info->tx; -+ u32 desc_index, i, data, reg; -+ -+ /* Clear the TXDESC2CMPL_MAP_xx reg before setting up -+ * the mapping. This register holds TXDESC to TXFILL ring -+ * mapping. -+ */ -+ regmap_write(regmap, EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_0_ADDR, 0); -+ regmap_write(regmap, EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_1_ADDR, 0); -+ regmap_write(regmap, EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_2_ADDR, 0); -+ regmap_write(regmap, EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_3_ADDR, 0); -+ regmap_write(regmap, EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_4_ADDR, 0); -+ regmap_write(regmap, EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_5_ADDR, 0); -+ desc_index = txcmpl->ring_start; -+ -+ /* 6 registers to hold the completion mapping for total 32 -+ * TX desc rings (0-5, 6-11, 12-17, 18-23, 24-29 and rest). -+ * In each entry 5 bits hold the mapping for a particular TX desc ring. -+ */ -+ for (i = tx->ring_start; i < tx->ring_start + tx->num_rings; i++) { -+ u32 reg, data; -+ -+ if (i >= 0 && i <= 5) -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_0_ADDR; -+ else if (i >= 6 && i <= 11) -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_1_ADDR; -+ else if (i >= 12 && i <= 17) -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_2_ADDR; -+ else if (i >= 18 && i <= 23) -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_3_ADDR; -+ else if (i >= 24 && i <= 29) -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_4_ADDR; -+ else -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_5_ADDR; -+ -+ pr_debug("Configure Tx desc:%u to use TxCmpl:%u\n", i, desc_index); -+ -+ /* Set the Tx complete descriptor ring number in the mapping register. -+ * E.g. If (txcmpl ring)desc_index = 31, (txdesc ring)i = 28. -+ * reg = EDMA_REG_TXDESC2CMPL_MAP_4_ADDR -+ * data |= (desc_index & 0x1F) << ((i % 6) * 5); -+ * data |= (0x1F << 20); - -+ * This sets 11111 at 20th bit of register EDMA_REG_TXDESC2CMPL_MAP_4_ADDR. -+ */ -+ regmap_read(regmap, reg, &data); -+ data |= (desc_index & EDMA_TXDESC2CMPL_MAP_TXDESC_MASK) << ((i % 6) * 5); -+ regmap_write(regmap, reg, data); -+ -+ desc_index++; -+ if (desc_index == txcmpl->ring_start + txcmpl->num_rings) -+ desc_index = txcmpl->ring_start; -+ } -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_0_ADDR; -+ regmap_read(regmap, reg, &data); -+ pr_debug("EDMA_REG_TXDESC2CMPL_MAP_0_ADDR: 0x%x\n", data); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_1_ADDR; -+ regmap_read(regmap, reg, &data); -+ pr_debug("EDMA_REG_TXDESC2CMPL_MAP_1_ADDR: 0x%x\n", data); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_2_ADDR; -+ regmap_read(regmap, reg, &data); -+ pr_debug("EDMA_REG_TXDESC2CMPL_MAP_2_ADDR: 0x%x\n", data); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_3_ADDR; -+ regmap_read(regmap, reg, &data); -+ pr_debug("EDMA_REG_TXDESC2CMPL_MAP_3_ADDR: 0x%x\n", data); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_4_ADDR; -+ regmap_read(regmap, reg, &data); -+ pr_debug("EDMA_REG_TXDESC2CMPL_MAP_4_ADDR: 0x%x\n", data); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_5_ADDR; -+ regmap_read(regmap, reg, &data); -+ pr_debug("EDMA_REG_TXDESC2CMPL_MAP_5_ADDR: 0x%x\n", data); -+} -+ -+static int edma_cfg_tx_rings_setup(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *txcmpl = hw_info->txcmpl; -+ struct edma_ring_info *tx = hw_info->tx; -+ u32 i, j = 0; -+ -+ /* Set Txdesc flow control group id, same as port number. */ -+ for (i = 0; i < hw_info->max_ports; i++) { -+ for_each_possible_cpu(j) { -+ struct edma_txdesc_ring *txdesc_ring = NULL; -+ u32 txdesc_idx = (i * num_possible_cpus()) + j; -+ -+ txdesc_ring = &edma_ctx->tx_rings[txdesc_idx]; -+ txdesc_ring->fc_grp_id = i + 1; -+ } -+ } -+ -+ /* Allocate TxDesc ring descriptors. */ -+ for (i = 0; i < tx->num_rings; i++) { -+ struct edma_txdesc_ring *txdesc_ring = NULL; -+ int ret; -+ -+ txdesc_ring = &edma_ctx->tx_rings[i]; -+ txdesc_ring->count = EDMA_TX_RING_SIZE; -+ txdesc_ring->id = tx->ring_start + i; -+ -+ ret = edma_cfg_tx_desc_ring_setup(txdesc_ring); -+ if (ret) { -+ pr_err("Error in setting up %d txdesc ring. ret: %d", -+ txdesc_ring->id, ret); -+ while (i-- >= 0) -+ edma_cfg_tx_desc_ring_cleanup(&edma_ctx->tx_rings[i]); -+ -+ return -ENOMEM; -+ } -+ } -+ -+ /* Allocate TxCmpl ring descriptors. */ -+ for (i = 0; i < txcmpl->num_rings; i++) { -+ struct edma_txcmpl_ring *txcmpl_ring = NULL; -+ int ret; -+ -+ txcmpl_ring = &edma_ctx->txcmpl_rings[i]; -+ txcmpl_ring->count = EDMA_TX_RING_SIZE; -+ txcmpl_ring->id = txcmpl->ring_start + i; -+ -+ ret = edma_cfg_txcmpl_ring_setup(txcmpl_ring); -+ if (ret != 0) { -+ pr_err("Error in setting up %d TxCmpl ring. ret: %d", -+ txcmpl_ring->id, ret); -+ while (i-- >= 0) -+ edma_cfg_txcmpl_ring_cleanup(&edma_ctx->txcmpl_rings[i]); -+ -+ goto txcmpl_mem_alloc_fail; -+ } -+ } -+ -+ pr_debug("Tx descriptor count for Tx desc and Tx complete rings: %d\n", -+ EDMA_TX_RING_SIZE); -+ -+ return 0; -+ -+txcmpl_mem_alloc_fail: -+ for (i = 0; i < tx->num_rings; i++) -+ edma_cfg_tx_desc_ring_cleanup(&edma_ctx->tx_rings[i]); -+ -+ return -ENOMEM; -+} -+ -+/** -+ * edma_cfg_tx_rings_alloc - Allocate EDMA Tx rings. -+ * -+ * Allocate EDMA Tx rings. -+ */ -+int edma_cfg_tx_rings_alloc(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *txcmpl = hw_info->txcmpl; -+ struct edma_ring_info *tx = hw_info->tx; -+ -+ edma_ctx->tx_rings = kzalloc((sizeof(*edma_ctx->tx_rings) * tx->num_rings), -+ GFP_KERNEL); -+ if (!edma_ctx->tx_rings) -+ return -ENOMEM; -+ -+ edma_ctx->txcmpl_rings = kzalloc((sizeof(*edma_ctx->txcmpl_rings) * txcmpl->num_rings), -+ GFP_KERNEL); -+ if (!edma_ctx->txcmpl_rings) -+ goto txcmpl_ring_alloc_fail; -+ -+ pr_debug("Num rings - TxDesc:%u (%u-%u) TxCmpl:%u (%u-%u)\n", -+ tx->num_rings, tx->ring_start, -+ (tx->ring_start + tx->num_rings - 1), -+ txcmpl->num_rings, txcmpl->ring_start, -+ (txcmpl->ring_start + txcmpl->num_rings - 1)); -+ -+ if (edma_cfg_tx_rings_setup()) { -+ pr_err("Error in setting up tx rings\n"); -+ goto tx_rings_setup_fail; -+ } -+ -+ return 0; -+ -+tx_rings_setup_fail: -+ kfree(edma_ctx->txcmpl_rings); -+ edma_ctx->txcmpl_rings = NULL; -+ -+txcmpl_ring_alloc_fail: -+ kfree(edma_ctx->tx_rings); -+ edma_ctx->tx_rings = NULL; -+ -+ return -ENOMEM; -+} -+ -+/** -+ * edma_cfg_tx_rings_cleanup - Cleanup EDMA Tx rings. -+ * -+ * Cleanup EDMA Tx rings. -+ */ -+void edma_cfg_tx_rings_cleanup(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *txcmpl = hw_info->txcmpl; -+ struct edma_ring_info *tx = hw_info->tx; -+ u32 i; -+ -+ /* Free any buffers assigned to any descriptors. */ -+ for (i = 0; i < tx->num_rings; i++) -+ edma_cfg_tx_desc_ring_cleanup(&edma_ctx->tx_rings[i]); -+ -+ /* Free Tx completion descriptors. */ -+ for (i = 0; i < txcmpl->num_rings; i++) -+ edma_cfg_txcmpl_ring_cleanup(&edma_ctx->txcmpl_rings[i]); -+ -+ kfree(edma_ctx->tx_rings); -+ kfree(edma_ctx->txcmpl_rings); -+ edma_ctx->tx_rings = NULL; -+ edma_ctx->txcmpl_rings = NULL; -+} -+ -+/** -+ * edma_cfg_tx_rings - Configure EDMA Tx rings. -+ * -+ * Configure EDMA Tx rings. -+ */ -+void edma_cfg_tx_rings(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *txcmpl = hw_info->txcmpl; -+ struct edma_ring_info *tx = hw_info->tx; -+ u32 i; -+ -+ /* Configure Tx desc ring. */ -+ for (i = 0; i < tx->num_rings; i++) -+ edma_cfg_tx_desc_ring_configure(&edma_ctx->tx_rings[i]); -+ -+ /* Configure TxCmpl ring. */ -+ for (i = 0; i < txcmpl->num_rings; i++) -+ edma_cfg_txcmpl_ring_configure(&edma_ctx->txcmpl_rings[i]); -+} -+ -+/** -+ * edma_cfg_tx_disable_interrupts - EDMA disable TX interrupts. -+ * -+ * Disable TX interrupt masks. -+ */ -+void edma_cfg_tx_disable_interrupts(u32 port_id) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct edma_txcmpl_ring *txcmpl_ring; -+ u32 i, ring_idx, reg; -+ -+ for_each_possible_cpu(i) { -+ ring_idx = ((port_id - 1) * num_possible_cpus()) + i; -+ txcmpl_ring = &edma_ctx->txcmpl_rings[ring_idx]; -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TX_INT_MASK(txcmpl_ring->id); -+ regmap_write(regmap, reg, EDMA_MASK_INT_CLEAR); -+ } -+} -+ -+/** -+ * edma_cfg_tx_enable_interrupts - EDMA enable TX interrupts. -+ * -+ * Enable TX interrupt masks. -+ */ -+void edma_cfg_tx_enable_interrupts(u32 port_id) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct edma_txcmpl_ring *txcmpl_ring; -+ u32 i, ring_idx, reg; -+ -+ for_each_possible_cpu(i) { -+ ring_idx = ((port_id - 1) * num_possible_cpus()) + i; -+ txcmpl_ring = &edma_ctx->txcmpl_rings[ring_idx]; -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TX_INT_MASK(txcmpl_ring->id); -+ regmap_write(regmap, reg, edma_ctx->intr_info.intr_mask_txcmpl); -+ } -+} -+ -+/** -+ * edma_cfg_tx_napi_enable - EDMA Tx NAPI. -+ * @port_id: Port ID. -+ * -+ * Enable Tx NAPI. -+ */ -+void edma_cfg_tx_napi_enable(u32 port_id) -+{ -+ struct edma_txcmpl_ring *txcmpl_ring; -+ u32 i, ring_idx; -+ -+ /* Enabling Tx napi for a interface with each queue. */ -+ for_each_possible_cpu(i) { -+ ring_idx = ((port_id - 1) * num_possible_cpus()) + i; -+ txcmpl_ring = &edma_ctx->txcmpl_rings[ring_idx]; -+ if (!txcmpl_ring->napi_added) -+ continue; -+ -+ napi_enable(&txcmpl_ring->napi); -+ } -+} -+ -+/** -+ * edma_cfg_tx_napi_disable - Disable Tx NAPI. -+ * @port_id: Port ID. -+ * -+ * Disable Tx NAPI. -+ */ -+void edma_cfg_tx_napi_disable(u32 port_id) -+{ -+ struct edma_txcmpl_ring *txcmpl_ring; -+ u32 i, ring_idx; -+ -+ /* Disabling Tx napi for a interface with each queue. */ -+ for_each_possible_cpu(i) { -+ ring_idx = ((port_id - 1) * num_possible_cpus()) + i; -+ txcmpl_ring = &edma_ctx->txcmpl_rings[ring_idx]; -+ if (!txcmpl_ring->napi_added) -+ continue; -+ -+ napi_disable(&txcmpl_ring->napi); -+ } -+} -+ -+/** -+ * edma_cfg_tx_napi_delete - Delete Tx NAPI. -+ * @port_id: Port ID. -+ * -+ * Delete Tx NAPI. -+ */ -+void edma_cfg_tx_napi_delete(u32 port_id) -+{ -+ struct edma_txcmpl_ring *txcmpl_ring; -+ u32 i, ring_idx; -+ -+ /* Disabling Tx napi for a interface with each queue. */ -+ for_each_possible_cpu(i) { -+ ring_idx = ((port_id - 1) * num_possible_cpus()) + i; -+ txcmpl_ring = &edma_ctx->txcmpl_rings[ring_idx]; -+ if (!txcmpl_ring->napi_added) -+ continue; -+ -+ netif_napi_del(&txcmpl_ring->napi); -+ txcmpl_ring->napi_added = false; -+ } -+} -+ -+/** -+ * edma_cfg_tx_napi_add - TX NAPI add. -+ * @netdev: Netdevice. -+ * @port_id: Port ID. -+ * -+ * TX NAPI add. -+ */ -+void edma_cfg_tx_napi_add(struct net_device *netdev, u32 port_id) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_txcmpl_ring *txcmpl_ring; -+ u32 i, ring_idx; -+ -+ /* Adding tx napi for a interface with each queue. */ -+ for_each_possible_cpu(i) { -+ ring_idx = ((port_id - 1) * num_possible_cpus()) + i; -+ txcmpl_ring = &edma_ctx->txcmpl_rings[ring_idx]; -+ netif_napi_add_weight(netdev, &txcmpl_ring->napi, -+ edma_tx_napi_poll, hw_info->napi_budget_tx); -+ txcmpl_ring->napi_added = true; -+ netdev_dbg(netdev, "Napi added for txcmpl ring: %u\n", txcmpl_ring->id); -+ } -+ -+ netdev_dbg(netdev, "Tx NAPI budget: %d\n", hw_info->napi_budget_tx); -+} ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_cfg_tx.h -@@ -0,0 +1,28 @@ -+/* SPDX-License-Identifier: GPL-2.0-only -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#ifndef __EDMA_CFG_TX__ -+#define __EDMA_CFG_TX__ -+ -+/* Tx mitigation timer's default value. */ -+#define EDMA_TX_MITIGATION_TIMER_DEF 250 -+ -+/* Tx mitigation packet count default value. */ -+#define EDMA_TX_MITIGATION_PKT_CNT_DEF 16 -+ -+void edma_cfg_tx_rings(void); -+int edma_cfg_tx_rings_alloc(void); -+void edma_cfg_tx_rings_cleanup(void); -+void edma_cfg_tx_disable_interrupts(u32 port_id); -+void edma_cfg_tx_enable_interrupts(u32 port_id); -+void edma_cfg_tx_napi_enable(u32 port_id); -+void edma_cfg_tx_napi_disable(u32 port_id); -+void edma_cfg_tx_napi_delete(u32 port_id); -+void edma_cfg_tx_napi_add(struct net_device *netdevice, u32 macid); -+void edma_cfg_tx_ring_mappings(void); -+void edma_cfg_txcmpl_mapping_fill(void); -+void edma_cfg_tx_rings_enable(u32 port_id); -+void edma_cfg_tx_rings_disable(u32 port_id); -+void edma_cfg_tx_fill_per_port_tx_map(struct net_device *netdev, u32 macid); -+#endif ---- a/drivers/net/ethernet/qualcomm/ppe/edma_port.c -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_port.c -@@ -13,6 +13,7 @@ - - #include "edma.h" - #include "edma_cfg_rx.h" -+#include "edma_cfg_tx.h" - #include "edma_port.h" - #include "ppe_regs.h" - -@@ -35,6 +36,15 @@ static int edma_port_stats_alloc(struct - return -ENOMEM; - } - -+ port_priv->pcpu_stats.tx_stats = -+ netdev_alloc_pcpu_stats(struct edma_port_tx_stats); -+ if (!port_priv->pcpu_stats.tx_stats) { -+ netdev_err(netdev, "Per-cpu EDMA Tx stats alloc failed for %s\n", -+ netdev->name); -+ free_percpu(port_priv->pcpu_stats.rx_stats); -+ return -ENOMEM; -+ } -+ - return 0; - } - -@@ -43,6 +53,28 @@ static void edma_port_stats_free(struct - struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); - - free_percpu(port_priv->pcpu_stats.rx_stats); -+ free_percpu(port_priv->pcpu_stats.tx_stats); -+} -+ -+static void edma_port_configure(struct net_device *netdev) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ struct ppe_port *port = port_priv->ppe_port; -+ int port_id = port->port_id; -+ -+ edma_cfg_tx_fill_per_port_tx_map(netdev, port_id); -+ edma_cfg_tx_rings_enable(port_id); -+ edma_cfg_tx_napi_add(netdev, port_id); -+} -+ -+static void edma_port_deconfigure(struct net_device *netdev) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ struct ppe_port *port = port_priv->ppe_port; -+ int port_id = port->port_id; -+ -+ edma_cfg_tx_napi_delete(port_id); -+ edma_cfg_tx_rings_disable(port_id); - } - - static u16 __maybe_unused edma_port_select_queue(__maybe_unused struct net_device *netdev, -@@ -60,6 +92,7 @@ static int edma_port_open(struct net_dev - { - struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); - struct ppe_port *ppe_port; -+ int port_id; - - if (!port_priv) - return -EINVAL; -@@ -74,10 +107,14 @@ static int edma_port_open(struct net_dev - netdev->wanted_features |= EDMA_NETDEV_FEATURES; - - ppe_port = port_priv->ppe_port; -+ port_id = ppe_port->port_id; - - if (ppe_port->phylink) - phylink_start(ppe_port->phylink); - -+ edma_cfg_tx_napi_enable(port_id); -+ edma_cfg_tx_enable_interrupts(port_id); -+ - netif_start_queue(netdev); - - return 0; -@@ -87,13 +124,21 @@ static int edma_port_close(struct net_de - { - struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); - struct ppe_port *ppe_port; -+ int port_id; - - if (!port_priv) - return -EINVAL; - - netif_stop_queue(netdev); - -+ /* 20ms delay would provide a plenty of margin to take care of in-flight packets. */ -+ msleep(20); -+ - ppe_port = port_priv->ppe_port; -+ port_id = ppe_port->port_id; -+ -+ edma_cfg_tx_disable_interrupts(port_id); -+ edma_cfg_tx_napi_disable(port_id); - - /* Phylink close. */ - if (ppe_port->phylink) -@@ -137,6 +182,92 @@ static netdev_features_t edma_port_featu - return features; - } - -+static netdev_tx_t edma_port_xmit(struct sk_buff *skb, -+ struct net_device *dev) -+{ -+ struct edma_port_priv *port_priv = NULL; -+ struct edma_port_pcpu_stats *pcpu_stats; -+ struct edma_txdesc_ring *txdesc_ring; -+ struct edma_port_tx_stats *stats; -+ enum edma_tx_gso_status result; -+ struct sk_buff *segs = NULL; -+ u8 cpu_id; -+ u32 skbq; -+ int ret; -+ -+ if (!skb || !dev) -+ return NETDEV_TX_OK; -+ -+ port_priv = netdev_priv(dev); -+ -+ /* Select a TX ring. */ -+ skbq = (skb_get_queue_mapping(skb) & (num_possible_cpus() - 1)); -+ -+ txdesc_ring = (struct edma_txdesc_ring *)port_priv->txr_map[skbq]; -+ -+ pcpu_stats = &port_priv->pcpu_stats; -+ stats = this_cpu_ptr(pcpu_stats->tx_stats); -+ -+ /* HW does not support TSO for packets with more than or equal to -+ * 32 segments. Perform SW GSO for such packets. -+ */ -+ result = edma_tx_gso_segment(skb, dev, &segs); -+ if (likely(result == EDMA_TX_GSO_NOT_NEEDED)) { -+ /* Transmit the packet. */ -+ ret = edma_tx_ring_xmit(dev, skb, txdesc_ring, stats); -+ -+ if (unlikely(ret == EDMA_TX_FAIL_NO_DESC)) { -+ if (likely(!edma_ctx->tx_requeue_stop)) { -+ cpu_id = smp_processor_id(); -+ netdev_dbg(dev, "Stopping tx queue due to lack oftx descriptors\n"); -+ u64_stats_update_begin(&stats->syncp); -+ ++stats->tx_queue_stopped[cpu_id]; -+ u64_stats_update_end(&stats->syncp); -+ netif_tx_stop_queue(netdev_get_tx_queue(dev, skbq)); -+ return NETDEV_TX_BUSY; -+ } -+ } -+ -+ if (unlikely(ret != EDMA_TX_OK)) { -+ dev_kfree_skb_any(skb); -+ u64_stats_update_begin(&stats->syncp); -+ ++stats->tx_drops; -+ u64_stats_update_end(&stats->syncp); -+ } -+ -+ return NETDEV_TX_OK; -+ } else if (unlikely(result == EDMA_TX_GSO_FAIL)) { -+ netdev_dbg(dev, "%p: SW GSO failed for segment size: %d\n", -+ skb, skb_shinfo(skb)->gso_segs); -+ dev_kfree_skb_any(skb); -+ u64_stats_update_begin(&stats->syncp); -+ ++stats->tx_gso_drop_pkts; -+ u64_stats_update_end(&stats->syncp); -+ return NETDEV_TX_OK; -+ } -+ -+ u64_stats_update_begin(&stats->syncp); -+ ++stats->tx_gso_pkts; -+ u64_stats_update_end(&stats->syncp); -+ -+ dev_kfree_skb_any(skb); -+ while (segs) { -+ skb = segs; -+ segs = segs->next; -+ -+ /* Transmit the packet. */ -+ ret = edma_tx_ring_xmit(dev, skb, txdesc_ring, stats); -+ if (unlikely(ret != EDMA_TX_OK)) { -+ dev_kfree_skb_any(skb); -+ u64_stats_update_begin(&stats->syncp); -+ ++stats->tx_drops; -+ u64_stats_update_end(&stats->syncp); -+ } -+ } -+ -+ return NETDEV_TX_OK; -+} -+ - static void edma_port_get_stats64(struct net_device *netdev, - struct rtnl_link_stats64 *stats) - { -@@ -179,6 +310,7 @@ static int edma_port_set_mac_address(str - static const struct net_device_ops edma_port_netdev_ops = { - .ndo_open = edma_port_open, - .ndo_stop = edma_port_close, -+ .ndo_start_xmit = edma_port_xmit, - .ndo_get_stats64 = edma_port_get_stats64, - .ndo_set_mac_address = edma_port_set_mac_address, - .ndo_validate_addr = eth_validate_addr, -@@ -199,6 +331,7 @@ void edma_port_destroy(struct ppe_port * - int port_id = port->port_id; - struct net_device *netdev = edma_ctx->netdev_arr[port_id - 1]; - -+ edma_port_deconfigure(netdev); - edma_port_stats_free(netdev); - unregister_netdev(netdev); - free_netdev(netdev); -@@ -276,6 +409,8 @@ int edma_port_setup(struct ppe_port *por - */ - edma_ctx->netdev_arr[port_id - 1] = netdev; - -+ edma_port_configure(netdev); -+ - /* Setup phylink. */ - ret = ppe_port_phylink_setup(port, netdev); - if (ret) { -@@ -298,6 +433,7 @@ int edma_port_setup(struct ppe_port *por - register_netdev_fail: - ppe_port_phylink_destroy(port); - port_phylink_setup_fail: -+ edma_port_deconfigure(netdev); - edma_ctx->netdev_arr[port_id - 1] = NULL; - edma_port_stats_free(netdev); - stats_alloc_fail: ---- a/drivers/net/ethernet/qualcomm/ppe/edma_port.h -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_port.h -@@ -7,6 +7,8 @@ - - #include "ppe_port.h" - -+#define EDMA_PORT_MAX_CORE 4 -+ - #define EDMA_NETDEV_FEATURES (NETIF_F_FRAGLIST \ - | NETIF_F_SG \ - | NETIF_F_RXCSUM \ -@@ -35,11 +37,43 @@ struct edma_port_rx_stats { - }; - - /** -+ * struct edma_port_tx_stats - EDMA TX port per CPU stats for the port. -+ * @tx_pkts: Number of Tx packets -+ * @tx_bytes: Number of Tx bytes -+ * @tx_drops: Number of Tx drops -+ * @tx_nr_frag_pkts: Number of Tx nr_frag packets -+ * @tx_fraglist_pkts: Number of Tx fraglist packets -+ * @tx_fraglist_with_nr_frags_pkts: Number of Tx packets with fraglist and nr_frags -+ * @tx_tso_pkts: Number of Tx TSO packets -+ * @tx_tso_drop_pkts: Number of Tx TSO drop packets -+ * @tx_gso_pkts: Number of Tx GSO packets -+ * @tx_gso_drop_pkts: Number of Tx GSO drop packets -+ * @tx_queue_stopped: Number of Tx queue stopped packets -+ * @syncp: Synchronization pointer -+ */ -+struct edma_port_tx_stats { -+ u64 tx_pkts; -+ u64 tx_bytes; -+ u64 tx_drops; -+ u64 tx_nr_frag_pkts; -+ u64 tx_fraglist_pkts; -+ u64 tx_fraglist_with_nr_frags_pkts; -+ u64 tx_tso_pkts; -+ u64 tx_tso_drop_pkts; -+ u64 tx_gso_pkts; -+ u64 tx_gso_drop_pkts; -+ u64 tx_queue_stopped[EDMA_PORT_MAX_CORE]; -+ struct u64_stats_sync syncp; -+}; -+ -+/** - * struct edma_port_pcpu_stats - EDMA per cpu stats data structure for the port. - * @rx_stats: Per CPU Rx statistics -+ * @tx_stats: Per CPU Tx statistics - */ - struct edma_port_pcpu_stats { - struct edma_port_rx_stats __percpu *rx_stats; -+ struct edma_port_tx_stats __percpu *tx_stats; - }; - - /** -@@ -54,6 +88,7 @@ struct edma_port_priv { - struct ppe_port *ppe_port; - struct net_device *netdev; - struct edma_port_pcpu_stats pcpu_stats; -+ struct edma_txdesc_ring *txr_map[EDMA_PORT_MAX_CORE]; - unsigned long flags; - }; - ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_tx.c -@@ -0,0 +1,808 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+/* Provide APIs to alloc Tx Buffers, fill the Tx descriptors and transmit -+ * Scatter Gather and linear packets, Tx complete to free the skb after transmit. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "edma.h" -+#include "edma_cfg_tx.h" -+#include "edma_port.h" -+#include "ppe.h" -+#include "ppe_regs.h" -+ -+static u32 edma_tx_num_descs_for_sg(struct sk_buff *skb) -+{ -+ u32 nr_frags_first = 0, num_tx_desc_needed = 0; -+ -+ /* Check if we have enough Tx descriptors for SG. */ -+ if (unlikely(skb_shinfo(skb)->nr_frags)) { -+ nr_frags_first = skb_shinfo(skb)->nr_frags; -+ WARN_ON_ONCE(nr_frags_first > MAX_SKB_FRAGS); -+ num_tx_desc_needed += nr_frags_first; -+ } -+ -+ /* Walk through fraglist skbs making a note of nr_frags -+ * One Tx desc for fraglist skb. Fraglist skb may have -+ * further nr_frags. -+ */ -+ if (unlikely(skb_has_frag_list(skb))) { -+ struct sk_buff *iter_skb; -+ -+ skb_walk_frags(skb, iter_skb) { -+ u32 nr_frags = skb_shinfo(iter_skb)->nr_frags; -+ -+ WARN_ON_ONCE(nr_frags > MAX_SKB_FRAGS); -+ num_tx_desc_needed += (1 + nr_frags); -+ } -+ } -+ -+ return (num_tx_desc_needed + 1); -+} -+ -+/** -+ * edma_tx_gso_segment - Tx GSO. -+ * @skb: Socket Buffer. -+ * @netdev: Netdevice. -+ * @segs: SKB segments from GSO. -+ * -+ * Format skbs into GSOs. -+ * -+ * Return 1 on success, error code on failure. -+ */ -+enum edma_tx_gso_status edma_tx_gso_segment(struct sk_buff *skb, -+ struct net_device *netdev, struct sk_buff **segs) -+{ -+ u32 num_tx_desc_needed; -+ -+ /* Check is skb is non-linear to proceed. */ -+ if (likely(!skb_is_nonlinear(skb))) -+ return EDMA_TX_GSO_NOT_NEEDED; -+ -+ /* Check if TSO is enabled. If so, return as skb doesn't -+ * need to be segmented by linux. -+ */ -+ if (netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) { -+ num_tx_desc_needed = edma_tx_num_descs_for_sg(skb); -+ if (likely(num_tx_desc_needed <= EDMA_TX_TSO_SEG_MAX)) -+ return EDMA_TX_GSO_NOT_NEEDED; -+ } -+ -+ /* GSO segmentation of the skb into multiple segments. */ -+ *segs = skb_gso_segment(skb, netdev->features -+ & ~(NETIF_F_TSO | NETIF_F_TSO6)); -+ -+ /* Check for error in GSO segmentation. */ -+ if (IS_ERR_OR_NULL(*segs)) { -+ netdev_info(netdev, "Tx gso fail\n"); -+ return EDMA_TX_GSO_FAIL; -+ } -+ -+ return EDMA_TX_GSO_SUCCEED; -+} -+ -+/** -+ * edma_tx_complete - Reap Tx completion descriptors. -+ * @work_to_do: Work to do. -+ * @txcmpl_ring: Tx Completion ring. -+ * -+ * Reap Tx completion descriptors of the transmitted -+ * packets and free the corresponding SKBs. -+ * -+ * Return the number descriptors for which Tx complete is done. -+ */ -+u32 edma_tx_complete(u32 work_to_do, struct edma_txcmpl_ring *txcmpl_ring) -+{ -+ struct edma_txcmpl_stats *txcmpl_stats = &txcmpl_ring->txcmpl_stats; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ u32 cons_idx, end_idx, data, cpu_id; -+ struct device *dev = ppe_dev->dev; -+ u32 avail, count, txcmpl_errors; -+ struct edma_txcmpl_desc *txcmpl; -+ u32 prod_idx = 0, more_bit = 0; -+ struct netdev_queue *nq; -+ struct sk_buff *skb; -+ u32 reg; -+ -+ cons_idx = txcmpl_ring->cons_idx; -+ -+ if (likely(txcmpl_ring->avail_pkt >= work_to_do)) { -+ avail = work_to_do; -+ } else { -+ /* Get TXCMPL ring producer index. */ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXCMPL_PROD_IDX(txcmpl_ring->id); -+ regmap_read(regmap, reg, &data); -+ prod_idx = data & EDMA_TXCMPL_PROD_IDX_MASK; -+ -+ avail = EDMA_DESC_AVAIL_COUNT(prod_idx, cons_idx, EDMA_TX_RING_SIZE); -+ txcmpl_ring->avail_pkt = avail; -+ -+ if (unlikely(!avail)) { -+ dev_dbg(dev, "No available descriptors are pending for %d txcmpl ring\n", -+ txcmpl_ring->id); -+ u64_stats_update_begin(&txcmpl_stats->syncp); -+ ++txcmpl_stats->no_pending_desc; -+ u64_stats_update_end(&txcmpl_stats->syncp); -+ return 0; -+ } -+ -+ avail = min(avail, work_to_do); -+ } -+ -+ count = avail; -+ -+ end_idx = (cons_idx + avail) & EDMA_TX_RING_SIZE_MASK; -+ txcmpl = EDMA_TXCMPL_DESC(txcmpl_ring, cons_idx); -+ -+ /* Instead of freeing the skb, it might be better to save and use -+ * for Rxfill. -+ */ -+ while (likely(avail--)) { -+ /* The last descriptor holds the SKB pointer for scattered frames. -+ * So skip the descriptors with more bit set. -+ */ -+ more_bit = EDMA_TXCMPL_MORE_BIT_GET(txcmpl); -+ if (unlikely(more_bit)) { -+ u64_stats_update_begin(&txcmpl_stats->syncp); -+ ++txcmpl_stats->desc_with_more_bit; -+ u64_stats_update_end(&txcmpl_stats->syncp); -+ cons_idx = ((cons_idx + 1) & EDMA_TX_RING_SIZE_MASK); -+ txcmpl = EDMA_TXCMPL_DESC(txcmpl_ring, cons_idx); -+ continue; -+ } -+ -+ /* Find and free the skb for Tx completion. */ -+ skb = (struct sk_buff *)EDMA_TXCMPL_OPAQUE_GET(txcmpl); -+ if (unlikely(!skb)) { -+ if (net_ratelimit()) -+ dev_warn(dev, "Invalid cons_idx:%u prod_idx:%u word2:%x word3:%x\n", -+ cons_idx, prod_idx, txcmpl->word2, txcmpl->word3); -+ -+ u64_stats_update_begin(&txcmpl_stats->syncp); -+ ++txcmpl_stats->invalid_buffer; -+ u64_stats_update_end(&txcmpl_stats->syncp); -+ } else { -+ dev_dbg(dev, "TXCMPL: skb:%p, skb->len %d, skb->data_len %d, cons_idx:%d prod_idx:%d word2:0x%x word3:0x%x\n", -+ skb, skb->len, skb->data_len, cons_idx, prod_idx, -+ txcmpl->word2, txcmpl->word3); -+ -+ txcmpl_errors = EDMA_TXCOMP_RING_ERROR_GET(txcmpl->word3); -+ if (unlikely(txcmpl_errors)) { -+ if (net_ratelimit()) -+ dev_err(dev, "Error 0x%0x observed in tx complete %d ring\n", -+ txcmpl_errors, txcmpl_ring->id); -+ -+ u64_stats_update_begin(&txcmpl_stats->syncp); -+ ++txcmpl_stats->errors; -+ u64_stats_update_end(&txcmpl_stats->syncp); -+ } -+ -+ /* Retrieve pool id for unmapping. -+ * 0 for linear skb and (pool id - 1) represents nr_frag index. -+ */ -+ if (!EDMA_TXCOMP_POOL_ID_GET(txcmpl)) { -+ dma_unmap_single(dev, virt_to_phys(skb->data), -+ skb->len, DMA_TO_DEVICE); -+ } else { -+ u8 frag_index = (EDMA_TXCOMP_POOL_ID_GET(txcmpl) - 1); -+ skb_frag_t *frag = &skb_shinfo(skb)->frags[frag_index]; -+ -+ dma_unmap_page(dev, virt_to_phys(frag), -+ PAGE_SIZE, DMA_TO_DEVICE); -+ } -+ -+ dev_kfree_skb(skb); -+ } -+ -+ cons_idx = ((cons_idx + 1) & EDMA_TX_RING_SIZE_MASK); -+ txcmpl = EDMA_TXCMPL_DESC(txcmpl_ring, cons_idx); -+ } -+ -+ txcmpl_ring->cons_idx = cons_idx; -+ txcmpl_ring->avail_pkt -= count; -+ -+ dev_dbg(dev, "TXCMPL:%u count:%u prod_idx:%u cons_idx:%u\n", -+ txcmpl_ring->id, count, prod_idx, cons_idx); -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXCMPL_CONS_IDX(txcmpl_ring->id); -+ regmap_write(regmap, reg, cons_idx); -+ -+ /* If tx_requeue_stop disabled (tx_requeue_stop = 0) -+ * Fetch the tx queue of interface and check if it is stopped. -+ * if queue is stopped and interface is up, wake up this queue. -+ */ -+ if (unlikely(!edma_ctx->tx_requeue_stop)) { -+ cpu_id = smp_processor_id(); -+ nq = netdev_get_tx_queue(txcmpl_ring->napi.dev, cpu_id); -+ if (unlikely(netif_tx_queue_stopped(nq)) && -+ netif_carrier_ok(txcmpl_ring->napi.dev)) { -+ dev_dbg(dev, "Waking queue number %d, for interface %s\n", -+ cpu_id, txcmpl_ring->napi.dev->name); -+ __netif_tx_lock(nq, cpu_id); -+ netif_tx_wake_queue(nq); -+ __netif_tx_unlock(nq); -+ } -+ } -+ -+ return count; -+} -+ -+/** -+ * edma_tx_napi_poll - EDMA TX NAPI handler. -+ * @napi: NAPI structure. -+ * @budget: Tx NAPI Budget. -+ * -+ * EDMA TX NAPI handler. -+ */ -+int edma_tx_napi_poll(struct napi_struct *napi, int budget) -+{ -+ struct edma_txcmpl_ring *txcmpl_ring = (struct edma_txcmpl_ring *)napi; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ u32 txcmpl_intr_status; -+ int work_done = 0; -+ u32 data, reg; -+ -+ do { -+ work_done += edma_tx_complete(budget - work_done, txcmpl_ring); -+ if (work_done >= budget) -+ return work_done; -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TX_INT_STAT(txcmpl_ring->id); -+ regmap_read(regmap, reg, &data); -+ txcmpl_intr_status = data & EDMA_TXCMPL_RING_INT_STATUS_MASK; -+ } while (txcmpl_intr_status); -+ -+ /* No more packets to process. Finish NAPI processing. */ -+ napi_complete(napi); -+ -+ /* Set TXCMPL ring interrupt mask. */ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TX_INT_MASK(txcmpl_ring->id); -+ regmap_write(regmap, reg, edma_ctx->intr_info.intr_mask_txcmpl); -+ -+ return work_done; -+} -+ -+/** -+ * edma_tx_handle_irq - Tx IRQ Handler. -+ * @irq: Interrupt request. -+ * @ctx: Context. -+ * -+ * Process TX IRQ and schedule NAPI. -+ * -+ * Return IRQ handler code. -+ */ -+irqreturn_t edma_tx_handle_irq(int irq, void *ctx) -+{ -+ struct edma_txcmpl_ring *txcmpl_ring = (struct edma_txcmpl_ring *)ctx; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ u32 reg; -+ -+ pr_debug("irq: irq=%d txcmpl_ring_id=%u\n", irq, txcmpl_ring->id); -+ if (likely(napi_schedule_prep(&txcmpl_ring->napi))) { -+ /* Disable TxCmpl intr. */ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TX_INT_MASK(txcmpl_ring->id); -+ regmap_write(regmap, reg, EDMA_MASK_INT_DISABLE); -+ __napi_schedule(&txcmpl_ring->napi); -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+static void edma_tx_dma_unmap_frags(struct sk_buff *skb, u32 nr_frags) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct device *dev = ppe_dev->dev; -+ u32 buf_len = 0; -+ u8 i = 0; -+ -+ for (i = 0; i < skb_shinfo(skb)->nr_frags - nr_frags; i++) { -+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; -+ -+ /* DMA mapping was not done for zero size segments. */ -+ buf_len = skb_frag_size(frag); -+ if (unlikely(buf_len == 0)) -+ continue; -+ -+ dma_unmap_page(dev, virt_to_phys(frag), PAGE_SIZE, -+ DMA_TO_DEVICE); -+ } -+} -+ -+static u32 edma_tx_skb_nr_frags(struct edma_txdesc_ring *txdesc_ring, -+ struct edma_txdesc_pri **txdesc, struct sk_buff *skb, -+ u32 *hw_next_to_use, u32 *invalid_frag) -+{ -+ u32 nr_frags = 0, buf_len = 0, num_descs = 0, start_idx = 0, end_idx = 0; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ u32 start_hw_next_to_use = *hw_next_to_use; -+ struct edma_txdesc_pri *txd = *txdesc; -+ struct device *dev = ppe_dev->dev; -+ u8 i = 0; -+ -+ /* Hold onto the index mapped to *txdesc. -+ * This will be the index previous to that of current *hw_next_to_use. -+ */ -+ start_idx = (((*hw_next_to_use) + EDMA_TX_RING_SIZE_MASK) -+ & EDMA_TX_RING_SIZE_MASK); -+ -+ /* Handle if the skb has nr_frags. */ -+ nr_frags = skb_shinfo(skb)->nr_frags; -+ num_descs = nr_frags; -+ i = 0; -+ -+ while (nr_frags--) { -+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; -+ dma_addr_t buff_addr; -+ -+ buf_len = skb_frag_size(frag); -+ -+ /* Zero size segment can lead EDMA HW to hang so, we don't want to -+ * process them. Zero size segment can happen during TSO operation -+ * if there is nothing but header in the primary segment. -+ */ -+ if (unlikely(buf_len == 0)) { -+ num_descs--; -+ i++; -+ continue; -+ } -+ -+ /* Setting the MORE bit on the previous Tx descriptor. -+ * Note: We will flush this descriptor as well later. -+ */ -+ EDMA_TXDESC_MORE_BIT_SET(txd, 1); -+ EDMA_TXDESC_ENDIAN_SET(txd); -+ -+ txd = EDMA_TXDESC_PRI_DESC(txdesc_ring, *hw_next_to_use); -+ memset(txd, 0, sizeof(struct edma_txdesc_pri)); -+ buff_addr = skb_frag_dma_map(dev, frag, 0, buf_len, -+ DMA_TO_DEVICE); -+ if (dma_mapping_error(dev, buff_addr)) { -+ dev_dbg(dev, "Unable to dma first descriptor for nr_frags tx\n"); -+ *hw_next_to_use = start_hw_next_to_use; -+ *invalid_frag = nr_frags; -+ return 0; -+ } -+ -+ EDMA_TXDESC_BUFFER_ADDR_SET(txd, buff_addr); -+ EDMA_TXDESC_DATA_LEN_SET(txd, buf_len); -+ EDMA_TXDESC_POOL_ID_SET(txd, (i + 1)); -+ -+ *hw_next_to_use = ((*hw_next_to_use + 1) & EDMA_TX_RING_SIZE_MASK); -+ i++; -+ } -+ -+ EDMA_TXDESC_ENDIAN_SET(txd); -+ -+ /* This will be the index previous to that of current *hw_next_to_use. */ -+ end_idx = (((*hw_next_to_use) + EDMA_TX_RING_SIZE_MASK) & EDMA_TX_RING_SIZE_MASK); -+ -+ *txdesc = txd; -+ -+ return num_descs; -+} -+ -+static void edma_tx_fill_pp_desc(struct edma_port_priv *port_priv, -+ struct edma_txdesc_pri *txd, struct sk_buff *skb, -+ struct edma_port_tx_stats *stats) -+{ -+ struct ppe_port *port = port_priv->ppe_port; -+ int port_id = port->port_id; -+ -+ /* Offload L3/L4 checksum computation. */ -+ if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { -+ EDMA_TXDESC_ADV_OFFLOAD_SET(txd); -+ EDMA_TXDESC_IP_CSUM_SET(txd); -+ EDMA_TXDESC_L4_CSUM_SET(txd); -+ } -+ -+ /* Check if the packet needs TSO -+ * This will be mostly true for SG packets. -+ */ -+ if (unlikely(skb_is_gso(skb))) { -+ if ((skb_shinfo(skb)->gso_type == SKB_GSO_TCPV4) || -+ (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6)) { -+ u32 mss = skb_shinfo(skb)->gso_size; -+ -+ /* If MSS<256, HW will do TSO using MSS=256, -+ * if MSS>10K, HW will do TSO using MSS=10K, -+ * else HW will report error 0x200000 in Tx Cmpl. -+ */ -+ if (mss < EDMA_TX_TSO_MSS_MIN) -+ mss = EDMA_TX_TSO_MSS_MIN; -+ else if (mss > EDMA_TX_TSO_MSS_MAX) -+ mss = EDMA_TX_TSO_MSS_MAX; -+ -+ EDMA_TXDESC_TSO_ENABLE_SET(txd, 1); -+ EDMA_TXDESC_MSS_SET(txd, mss); -+ -+ /* Update tso stats. */ -+ u64_stats_update_begin(&stats->syncp); -+ stats->tx_tso_pkts++; -+ u64_stats_update_end(&stats->syncp); -+ } -+ } -+ -+ /* Set destination information in the descriptor. */ -+ EDMA_TXDESC_SERVICE_CODE_SET(txd, PPE_EDMA_SC_BYPASS_ID); -+ EDMA_DST_INFO_SET(txd, port_id); -+} -+ -+static struct edma_txdesc_pri *edma_tx_skb_first_desc(struct edma_port_priv *port_priv, -+ struct edma_txdesc_ring *txdesc_ring, -+ struct sk_buff *skb, u32 *hw_next_to_use, -+ struct edma_port_tx_stats *stats) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct edma_txdesc_pri *txd = NULL; -+ struct device *dev = ppe_dev->dev; -+ dma_addr_t buff_addr; -+ u32 buf_len = 0; -+ -+ /* Get the packet length. */ -+ buf_len = skb_headlen(skb); -+ txd = EDMA_TXDESC_PRI_DESC(txdesc_ring, *hw_next_to_use); -+ memset(txd, 0, sizeof(struct edma_txdesc_pri)); -+ -+ /* Set the data pointer as the buffer address in the descriptor. */ -+ buff_addr = dma_map_single(dev, skb->data, buf_len, DMA_TO_DEVICE); -+ if (dma_mapping_error(dev, buff_addr)) { -+ dev_dbg(dev, "Unable to dma first descriptor for tx\n"); -+ return NULL; -+ } -+ -+ EDMA_TXDESC_BUFFER_ADDR_SET(txd, buff_addr); -+ EDMA_TXDESC_POOL_ID_SET(txd, 0); -+ edma_tx_fill_pp_desc(port_priv, txd, skb, stats); -+ -+ /* Set packet length in the descriptor. */ -+ EDMA_TXDESC_DATA_LEN_SET(txd, buf_len); -+ *hw_next_to_use = (*hw_next_to_use + 1) & EDMA_TX_RING_SIZE_MASK; -+ -+ return txd; -+} -+ -+static void edma_tx_handle_dma_err(struct sk_buff *skb, u32 num_sg_frag_list) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct device *dev = ppe_dev->dev; -+ struct sk_buff *iter_skb = NULL; -+ u32 cnt_sg_frag_list = 0; -+ -+ /* Walk through all fraglist skbs. */ -+ skb_walk_frags(skb, iter_skb) { -+ if (skb_headlen(iter_skb)) { -+ dma_unmap_single(dev, virt_to_phys(iter_skb->data), -+ skb_headlen(iter_skb), DMA_TO_DEVICE); -+ cnt_sg_frag_list += 1; -+ } -+ -+ if (cnt_sg_frag_list == num_sg_frag_list) -+ return; -+ -+ /* skb fraglist skb had nr_frags, unmap that memory. */ -+ u32 nr_frags = skb_shinfo(iter_skb)->nr_frags; -+ -+ if (nr_frags == 0) -+ continue; -+ -+ for (int i = 0; i < nr_frags; i++) { -+ skb_frag_t *frag = &skb_shinfo(iter_skb)->frags[i]; -+ -+ /* DMA mapping was not done for zero size segments. */ -+ if (unlikely(skb_frag_size(frag) == 0)) -+ continue; -+ -+ dma_unmap_page(dev, virt_to_phys(frag), -+ PAGE_SIZE, DMA_TO_DEVICE); -+ cnt_sg_frag_list += 1; -+ if (cnt_sg_frag_list == num_sg_frag_list) -+ return; -+ } -+ } -+} -+ -+static u32 edma_tx_skb_sg_fill_desc(struct edma_txdesc_ring *txdesc_ring, -+ struct edma_txdesc_pri **txdesc, -+ struct sk_buff *skb, u32 *hw_next_to_use, -+ struct edma_port_tx_stats *stats) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ u32 start_hw_next_to_use = 0, invalid_frag = 0; -+ struct edma_txdesc_pri *txd = *txdesc; -+ struct device *dev = ppe_dev->dev; -+ struct sk_buff *iter_skb = NULL; -+ u32 buf_len = 0, num_descs = 0; -+ u32 num_sg_frag_list = 0; -+ -+ /* Head skb processed already. */ -+ num_descs++; -+ -+ if (unlikely(skb_has_frag_list(skb))) { -+ struct edma_txdesc_pri *start_desc = NULL; -+ u32 start_idx = 0, end_idx = 0; -+ -+ /* Hold onto the index mapped to txd. -+ * This will be the index previous to that of current *hw_next_to_use. -+ */ -+ start_idx = (((*hw_next_to_use) + EDMA_TX_RING_SIZE_MASK) -+ & EDMA_TX_RING_SIZE_MASK); -+ start_desc = txd; -+ start_hw_next_to_use = *hw_next_to_use; -+ -+ /* Walk through all fraglist skbs. */ -+ skb_walk_frags(skb, iter_skb) { -+ dma_addr_t buff_addr; -+ u32 num_nr_frag = 0; -+ -+ /* This case could happen during the packet decapsulation. -+ * All header content might be removed. -+ */ -+ buf_len = skb_headlen(iter_skb); -+ if (unlikely(buf_len == 0)) -+ goto skip_primary; -+ -+ /* We make sure to flush this descriptor later. */ -+ EDMA_TXDESC_MORE_BIT_SET(txd, 1); -+ EDMA_TXDESC_ENDIAN_SET(txd); -+ -+ txd = EDMA_TXDESC_PRI_DESC(txdesc_ring, *hw_next_to_use); -+ memset(txd, 0, sizeof(struct edma_txdesc_pri)); -+ buff_addr = dma_map_single(dev, iter_skb->data, -+ buf_len, DMA_TO_DEVICE); -+ if (dma_mapping_error(dev, buff_addr)) { -+ dev_dbg(dev, "Unable to dma for fraglist\n"); -+ goto dma_err; -+ } -+ -+ EDMA_TXDESC_BUFFER_ADDR_SET(txd, buff_addr); -+ EDMA_TXDESC_DATA_LEN_SET(txd, buf_len); -+ EDMA_TXDESC_POOL_ID_SET(txd, 0); -+ -+ *hw_next_to_use = (*hw_next_to_use + 1) & EDMA_TX_RING_SIZE_MASK; -+ num_descs += 1; -+ num_sg_frag_list += 1; -+ -+ /* skb fraglist skb can have nr_frags. */ -+skip_primary: -+ if (unlikely(skb_shinfo(iter_skb)->nr_frags)) { -+ num_nr_frag = edma_tx_skb_nr_frags(txdesc_ring, &txd, -+ iter_skb, hw_next_to_use, -+ &invalid_frag); -+ if (unlikely(!num_nr_frag)) { -+ dev_dbg(dev, "No descriptor available for ring %d\n", -+ txdesc_ring->id); -+ edma_tx_dma_unmap_frags(iter_skb, invalid_frag); -+ goto dma_err; -+ } -+ -+ num_descs += num_nr_frag; -+ num_sg_frag_list += num_nr_frag; -+ -+ /* Update fraglist with nr_frag stats. */ -+ u64_stats_update_begin(&stats->syncp); -+ stats->tx_fraglist_with_nr_frags_pkts++; -+ u64_stats_update_end(&stats->syncp); -+ } -+ } -+ -+ EDMA_TXDESC_ENDIAN_SET(txd); -+ -+ /* This will be the index previous to -+ * that of current *hw_next_to_use. -+ */ -+ end_idx = (((*hw_next_to_use) + EDMA_TX_RING_SIZE_MASK) & -+ EDMA_TX_RING_SIZE_MASK); -+ -+ /* Update frag_list stats. */ -+ u64_stats_update_begin(&stats->syncp); -+ stats->tx_fraglist_pkts++; -+ u64_stats_update_end(&stats->syncp); -+ } else { -+ /* Process skb with nr_frags. */ -+ num_descs += edma_tx_skb_nr_frags(txdesc_ring, &txd, skb, -+ hw_next_to_use, &invalid_frag); -+ if (unlikely(!num_descs)) { -+ dev_dbg(dev, "No descriptor available for ring %d\n", txdesc_ring->id); -+ edma_tx_dma_unmap_frags(skb, invalid_frag); -+ *txdesc = NULL; -+ return num_descs; -+ } -+ -+ u64_stats_update_begin(&stats->syncp); -+ stats->tx_nr_frag_pkts++; -+ u64_stats_update_end(&stats->syncp); -+ } -+ -+ dev_dbg(dev, "skb:%p num_descs_filled: %u, nr_frags %u, frag_list fragments %u\n", -+ skb, num_descs, skb_shinfo(skb)->nr_frags, num_sg_frag_list); -+ -+ *txdesc = txd; -+ -+ return num_descs; -+ -+dma_err: -+ if (!num_sg_frag_list) -+ goto reset_state; -+ -+ edma_tx_handle_dma_err(skb, num_sg_frag_list); -+ -+reset_state: -+ *hw_next_to_use = start_hw_next_to_use; -+ *txdesc = NULL; -+ -+ return 0; -+} -+ -+static u32 edma_tx_avail_desc(struct edma_txdesc_ring *txdesc_ring, -+ u32 hw_next_to_use) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ u32 data = 0, avail = 0, hw_next_to_clean = 0; -+ struct regmap *regmap = ppe_dev->regmap; -+ u32 reg; -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC_CONS_IDX(txdesc_ring->id); -+ regmap_read(regmap, reg, &data); -+ hw_next_to_clean = data & EDMA_TXDESC_CONS_IDX_MASK; -+ -+ avail = EDMA_DESC_AVAIL_COUNT(hw_next_to_clean - 1, -+ hw_next_to_use, EDMA_TX_RING_SIZE); -+ -+ return avail; -+} -+ -+/** -+ * edma_tx_ring_xmit - Transmit a packet. -+ * @netdev: Netdevice. -+ * @skb: Socket Buffer. -+ * @txdesc_ring: Tx Descriptor ring. -+ * @stats: EDMA Tx Statistics. -+ * -+ * Check for available descriptors, fill the descriptors -+ * and transmit both linear and non linear packets. -+ * -+ * Return 0 on success, negative error code on failure. -+ */ -+enum edma_tx_status edma_tx_ring_xmit(struct net_device *netdev, -+ struct sk_buff *skb, struct edma_txdesc_ring *txdesc_ring, -+ struct edma_port_tx_stats *stats) -+{ -+ struct edma_txdesc_stats *txdesc_stats = &txdesc_ring->txdesc_stats; -+ struct edma_port_priv *port_priv = netdev_priv(netdev); -+ u32 num_tx_desc_needed = 0, num_desc_filled = 0; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct ppe_port *port = port_priv->ppe_port; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct edma_txdesc_pri *txdesc = NULL; -+ struct device *dev = ppe_dev->dev; -+ int port_id = port->port_id; -+ u32 hw_next_to_use = 0; -+ u32 reg; -+ -+ hw_next_to_use = txdesc_ring->prod_idx; -+ -+ if (unlikely(!(txdesc_ring->avail_desc))) { -+ txdesc_ring->avail_desc = edma_tx_avail_desc(txdesc_ring, -+ hw_next_to_use); -+ if (unlikely(!txdesc_ring->avail_desc)) { -+ netdev_dbg(netdev, "No available descriptors are present at %d ring\n", -+ txdesc_ring->id); -+ -+ u64_stats_update_begin(&txdesc_stats->syncp); -+ ++txdesc_stats->no_desc_avail; -+ u64_stats_update_end(&txdesc_stats->syncp); -+ return EDMA_TX_FAIL_NO_DESC; -+ } -+ } -+ -+ /* Process head skb for linear skb. -+ * Process head skb + nr_frags + fraglist for non linear skb. -+ */ -+ if (likely(!skb_is_nonlinear(skb))) { -+ txdesc = edma_tx_skb_first_desc(port_priv, txdesc_ring, skb, -+ &hw_next_to_use, stats); -+ if (unlikely(!txdesc)) { -+ netdev_dbg(netdev, "No descriptor available for ring %d\n", -+ txdesc_ring->id); -+ u64_stats_update_begin(&txdesc_stats->syncp); -+ ++txdesc_stats->no_desc_avail; -+ u64_stats_update_end(&txdesc_stats->syncp); -+ return EDMA_TX_FAIL_NO_DESC; -+ } -+ -+ EDMA_TXDESC_ENDIAN_SET(txdesc); -+ num_desc_filled++; -+ } else { -+ num_tx_desc_needed = edma_tx_num_descs_for_sg(skb); -+ -+ /* HW does not support TSO for packets with more than 32 segments. -+ * HW hangs up if it sees more than 32 segments. Kernel Perform GSO -+ * for such packets with netdev gso_max_segs set to 32. -+ */ -+ if (unlikely(num_tx_desc_needed > EDMA_TX_TSO_SEG_MAX)) { -+ netdev_dbg(netdev, "Number of segments %u more than %u for %d ring\n", -+ num_tx_desc_needed, EDMA_TX_TSO_SEG_MAX, txdesc_ring->id); -+ u64_stats_update_begin(&txdesc_stats->syncp); -+ ++txdesc_stats->tso_max_seg_exceed; -+ u64_stats_update_end(&txdesc_stats->syncp); -+ -+ u64_stats_update_begin(&stats->syncp); -+ stats->tx_tso_drop_pkts++; -+ u64_stats_update_end(&stats->syncp); -+ -+ return EDMA_TX_FAIL; -+ } -+ -+ if (unlikely(num_tx_desc_needed > txdesc_ring->avail_desc)) { -+ txdesc_ring->avail_desc = edma_tx_avail_desc(txdesc_ring, -+ hw_next_to_use); -+ if (num_tx_desc_needed > txdesc_ring->avail_desc) { -+ u64_stats_update_begin(&txdesc_stats->syncp); -+ ++txdesc_stats->no_desc_avail; -+ u64_stats_update_end(&txdesc_stats->syncp); -+ netdev_dbg(netdev, "Not enough available descriptors are present at %d ring for SG packet. Needed %d, currently available %d\n", -+ txdesc_ring->id, num_tx_desc_needed, -+ txdesc_ring->avail_desc); -+ return EDMA_TX_FAIL_NO_DESC; -+ } -+ } -+ -+ txdesc = edma_tx_skb_first_desc(port_priv, txdesc_ring, skb, -+ &hw_next_to_use, stats); -+ if (unlikely(!txdesc)) { -+ netdev_dbg(netdev, "No non-linear descriptor available for ring %d\n", -+ txdesc_ring->id); -+ u64_stats_update_begin(&txdesc_stats->syncp); -+ ++txdesc_stats->no_desc_avail; -+ u64_stats_update_end(&txdesc_stats->syncp); -+ return EDMA_TX_FAIL_NO_DESC; -+ } -+ -+ num_desc_filled = edma_tx_skb_sg_fill_desc(txdesc_ring, -+ &txdesc, skb, &hw_next_to_use, stats); -+ if (unlikely(!txdesc)) { -+ netdev_dbg(netdev, "No descriptor available for ring %d\n", -+ txdesc_ring->id); -+ dma_unmap_single(dev, virt_to_phys(skb->data), -+ skb->len, DMA_TO_DEVICE); -+ u64_stats_update_begin(&txdesc_stats->syncp); -+ ++txdesc_stats->no_desc_avail; -+ u64_stats_update_end(&txdesc_stats->syncp); -+ return EDMA_TX_FAIL_NO_DESC; -+ } -+ } -+ -+ /* Set the skb pointer to the descriptor's opaque field/s -+ * on the last descriptor of the packet/SG packet. -+ */ -+ EDMA_TXDESC_OPAQUE_SET(txdesc, skb); -+ -+ /* Update producer index. */ -+ txdesc_ring->prod_idx = hw_next_to_use & EDMA_TXDESC_PROD_IDX_MASK; -+ txdesc_ring->avail_desc -= num_desc_filled; -+ -+ netdev_dbg(netdev, "%s: skb:%p tx_ring:%u proto:0x%x skb->len:%d\n port:%u prod_idx:%u ip_summed:0x%x\n", -+ netdev->name, skb, txdesc_ring->id, ntohs(skb->protocol), -+ skb->len, port_id, hw_next_to_use, skb->ip_summed); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC_PROD_IDX(txdesc_ring->id); -+ regmap_write(regmap, reg, txdesc_ring->prod_idx); -+ -+ u64_stats_update_begin(&stats->syncp); -+ stats->tx_pkts++; -+ stats->tx_bytes += skb->len; -+ u64_stats_update_end(&stats->syncp); -+ -+ return EDMA_TX_OK; -+} ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_tx.h -@@ -0,0 +1,302 @@ -+/* SPDX-License-Identifier: GPL-2.0-only -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#ifndef __EDMA_TX__ -+#define __EDMA_TX__ -+ -+#include "edma_port.h" -+ -+#define EDMA_GET_DESC(R, i, type) (&(((type *)((R)->desc))[(i)])) -+#define EDMA_GET_PDESC(R, i, type) (&(((type *)((R)->pdesc))[(i)])) -+#define EDMA_GET_SDESC(R, i, type) (&(((type *)((R)->sdesc))[(i)])) -+#define EDMA_TXCMPL_DESC(R, i) EDMA_GET_DESC(R, i, \ -+ struct edma_txcmpl_desc) -+#define EDMA_TXDESC_PRI_DESC(R, i) EDMA_GET_PDESC(R, i, \ -+ struct edma_txdesc_pri) -+#define EDMA_TXDESC_SEC_DESC(R, i) EDMA_GET_SDESC(R, i, \ -+ struct edma_txdesc_sec) -+ -+#define EDMA_DESC_AVAIL_COUNT(head, tail, _max) ({ \ -+ typeof(_max) (max) = (_max); \ -+ ((((head) - (tail)) + \ -+ (max)) & ((max) - 1)); }) -+ -+#define EDMA_TX_RING_SIZE 2048 -+#define EDMA_TX_RING_SIZE_MASK (EDMA_TX_RING_SIZE - 1) -+ -+/* Max segment processing capacity of HW for TSO. */ -+#define EDMA_TX_TSO_SEG_MAX 32 -+ -+/* HW defined low and high MSS size. */ -+#define EDMA_TX_TSO_MSS_MIN 256 -+#define EDMA_TX_TSO_MSS_MAX 10240 -+ -+#define EDMA_DST_PORT_TYPE 2 -+#define EDMA_DST_PORT_TYPE_SHIFT 28 -+#define EDMA_DST_PORT_TYPE_MASK (0xf << EDMA_DST_PORT_TYPE_SHIFT) -+#define EDMA_DST_PORT_ID_SHIFT 16 -+#define EDMA_DST_PORT_ID_MASK (0xfff << EDMA_DST_PORT_ID_SHIFT) -+ -+#define EDMA_DST_PORT_TYPE_SET(x) (((x) << EDMA_DST_PORT_TYPE_SHIFT) & \ -+ EDMA_DST_PORT_TYPE_MASK) -+#define EDMA_DST_PORT_ID_SET(x) (((x) << EDMA_DST_PORT_ID_SHIFT) & \ -+ EDMA_DST_PORT_ID_MASK) -+#define EDMA_DST_INFO_SET(desc, x) ((desc)->word4 |= \ -+ (EDMA_DST_PORT_TYPE_SET(EDMA_DST_PORT_TYPE) | EDMA_DST_PORT_ID_SET(x))) -+ -+#define EDMA_TXDESC_TSO_ENABLE_MASK BIT(24) -+#define EDMA_TXDESC_TSO_ENABLE_SET(desc, x) ((desc)->word5 |= \ -+ FIELD_PREP(EDMA_TXDESC_TSO_ENABLE_MASK, x)) -+#define EDMA_TXDESC_MSS_MASK GENMASK(31, 16) -+#define EDMA_TXDESC_MSS_SET(desc, x) ((desc)->word6 |= \ -+ FIELD_PREP(EDMA_TXDESC_MSS_MASK, x)) -+#define EDMA_TXDESC_MORE_BIT_MASK BIT(30) -+#define EDMA_TXDESC_MORE_BIT_SET(desc, x) ((desc)->word1 |= \ -+ FIELD_PREP(EDMA_TXDESC_MORE_BIT_MASK, x)) -+ -+#define EDMA_TXDESC_ADV_OFFSET_BIT BIT(31) -+#define EDMA_TXDESC_ADV_OFFLOAD_SET(desc) ((desc)->word5 |= \ -+ FIELD_PREP(EDMA_TXDESC_ADV_OFFSET_BIT, 1)) -+#define EDMA_TXDESC_IP_CSUM_BIT BIT(25) -+#define EDMA_TXDESC_IP_CSUM_SET(desc) ((desc)->word5 |= \ -+ FIELD_PREP(EDMA_TXDESC_IP_CSUM_BIT, 1)) -+ -+#define EDMA_TXDESC_L4_CSUM_SET_MASK GENMASK(27, 26) -+#define EDMA_TXDESC_L4_CSUM_SET(desc) ((desc)->word5 |= \ -+ (FIELD_PREP(EDMA_TXDESC_L4_CSUM_SET_MASK, 1))) -+ -+#define EDMA_TXDESC_POOL_ID_SET_MASK GENMASK(24, 18) -+#define EDMA_TXDESC_POOL_ID_SET(desc, x) ((desc)->word5 |= \ -+ (FIELD_PREP(EDMA_TXDESC_POOL_ID_SET_MASK, x))) -+ -+#define EDMA_TXDESC_DATA_LEN_SET(desc, x) ((desc)->word5 |= ((x) & 0x1ffff)) -+#define EDMA_TXDESC_SERVICE_CODE_MASK GENMASK(24, 16) -+#define EDMA_TXDESC_SERVICE_CODE_SET(desc, x) ((desc)->word1 |= \ -+ (FIELD_PREP(EDMA_TXDESC_SERVICE_CODE_MASK, x))) -+#define EDMA_TXDESC_BUFFER_ADDR_SET(desc, addr) (((desc)->word0) = (addr)) -+ -+#ifdef __LP64__ -+#define EDMA_TXDESC_OPAQUE_GET(_desc) ({ \ -+ typeof(_desc) (desc) = (_desc); \ -+ (((u64)(desc)->word3 << 32) | (desc)->word2); }) -+ -+#define EDMA_TXCMPL_OPAQUE_GET(_desc) ({ \ -+ typeof(_desc) (desc) = (_desc); \ -+ (((u64)(desc)->word1 << 32) | \ -+ (desc)->word0); }) -+ -+#define EDMA_TXDESC_OPAQUE_LO_SET(desc, ptr) ((desc)->word2 = \ -+ (u32)(uintptr_t)(ptr)) -+ -+#define EDMA_TXDESC_OPAQUE_HI_SET(desc, ptr) ((desc)->word3 = \ -+ (u32)((u64)(ptr) >> 32)) -+ -+#define EDMA_TXDESC_OPAQUE_SET(_desc, _ptr) do { \ -+ typeof(_desc) (desc) = (_desc); \ -+ typeof(_ptr) (ptr) = (_ptr); \ -+ EDMA_TXDESC_OPAQUE_LO_SET(desc, ptr); \ -+ EDMA_TXDESC_OPAQUE_HI_SET(desc, ptr); \ -+} while (0) -+#else -+#define EDMA_TXCMPL_OPAQUE_GET(desc) ((desc)->word0) -+#define EDMA_TXDESC_OPAQUE_GET(desc) ((desc)->word2) -+#define EDMA_TXDESC_OPAQUE_LO_SET(desc, ptr) ((desc)->word2 = (u32)(uintptr_t)ptr) -+ -+#define EDMA_TXDESC_OPAQUE_SET(desc, ptr) \ -+ EDMA_TXDESC_OPAQUE_LO_SET(desc, ptr) -+#endif -+#define EDMA_TXCMPL_MORE_BIT_MASK BIT(30) -+ -+#define EDMA_TXCMPL_MORE_BIT_GET(desc) ((le32_to_cpu((__force __le32)((desc)->word2))) & \ -+ EDMA_TXCMPL_MORE_BIT_MASK) -+ -+#define EDMA_TXCOMP_RING_ERROR_MASK GENMASK(22, 0) -+ -+#define EDMA_TXCOMP_RING_ERROR_GET(x) ((le32_to_cpu((__force __le32)x)) & \ -+ EDMA_TXCOMP_RING_ERROR_MASK) -+ -+#define EDMA_TXCOMP_POOL_ID_MASK GENMASK(5, 0) -+ -+#define EDMA_TXCOMP_POOL_ID_GET(desc) ((le32_to_cpu((__force __le32)((desc)->word2))) & \ -+ EDMA_TXCOMP_POOL_ID_MASK) -+ -+/* Opaque values are set in word2 and word3, -+ * they are not accessed by the EDMA HW, -+ * so endianness conversion is not needed. -+ */ -+#define EDMA_TXDESC_ENDIAN_SET(_desc) ({ \ -+ typeof(_desc) (desc) = (_desc); \ -+ cpu_to_le32s(&((desc)->word0)); \ -+ cpu_to_le32s(&((desc)->word1)); \ -+ cpu_to_le32s(&((desc)->word4)); \ -+ cpu_to_le32s(&((desc)->word5)); \ -+ cpu_to_le32s(&((desc)->word6)); \ -+ cpu_to_le32s(&((desc)->word7)); \ -+}) -+ -+/* EDMA Tx GSO status */ -+enum edma_tx_status { -+ EDMA_TX_OK = 0, /* Tx success. */ -+ EDMA_TX_FAIL_NO_DESC = 1, /* Not enough descriptors. */ -+ EDMA_TX_FAIL = 2, /* Tx failure. */ -+}; -+ -+/* EDMA TX GSO status */ -+enum edma_tx_gso_status { -+ EDMA_TX_GSO_NOT_NEEDED = 0, -+ /* Packet has segment count less than TX_TSO_SEG_MAX. */ -+ EDMA_TX_GSO_SUCCEED = 1, -+ /* GSO Succeed. */ -+ EDMA_TX_GSO_FAIL = 2, -+ /* GSO failed, drop the packet. */ -+}; -+ -+/** -+ * struct edma_txcmpl_stats - EDMA TX complete ring statistics. -+ * @invalid_buffer: Invalid buffer address received. -+ * @errors: Other Tx complete descriptor errors indicated by the hardware. -+ * @desc_with_more_bit: Packet's segment transmit count. -+ * @no_pending_desc: No descriptor is pending for processing. -+ * @syncp: Synchronization pointer. -+ */ -+struct edma_txcmpl_stats { -+ u64 invalid_buffer; -+ u64 errors; -+ u64 desc_with_more_bit; -+ u64 no_pending_desc; -+ struct u64_stats_sync syncp; -+}; -+ -+/** -+ * struct edma_txdesc_stats - EDMA Tx descriptor ring statistics. -+ * @no_desc_avail: No descriptor available to transmit. -+ * @tso_max_seg_exceed: Packets extending EDMA_TX_TSO_SEG_MAX segments. -+ * @syncp: Synchronization pointer. -+ */ -+struct edma_txdesc_stats { -+ u64 no_desc_avail; -+ u64 tso_max_seg_exceed; -+ struct u64_stats_sync syncp; -+}; -+ -+/** -+ * struct edma_txdesc_pri - EDMA primary TX descriptor. -+ * @word0: Low 32-bit of buffer address. -+ * @word1: Buffer recycling, PTP tag flag, PRI valid flag. -+ * @word2: Low 32-bit of opaque value. -+ * @word3: High 32-bit of opaque value. -+ * @word4: Source/Destination port info. -+ * @word5: VLAN offload, csum mode, ip_csum_en, tso_en, data len. -+ * @word6: MSS/hash_value/PTP tag, data offset. -+ * @word7: L4/L3 offset, PROT type, L2 type, CVLAN/SVLAN tag, service code. -+ */ -+struct edma_txdesc_pri { -+ u32 word0; -+ u32 word1; -+ u32 word2; -+ u32 word3; -+ u32 word4; -+ u32 word5; -+ u32 word6; -+ u32 word7; -+}; -+ -+/** -+ * struct edma_txdesc_sec - EDMA secondary TX descriptor. -+ * @word0: Reserved. -+ * @word1: Custom csum offset, payload offset, TTL/NAT action. -+ * @word2: NAPT translated port, DSCP value, TTL value. -+ * @word3: Flow index value and valid flag. -+ * @word4: Reserved. -+ * @word5: Reserved. -+ * @word6: CVLAN/SVLAN command. -+ * @word7: CVLAN/SVLAN tag value. -+ */ -+struct edma_txdesc_sec { -+ u32 word0; -+ u32 word1; -+ u32 word2; -+ u32 word3; -+ u32 word4; -+ u32 word5; -+ u32 word6; -+ u32 word7; -+}; -+ -+/** -+ * struct edma_txcmpl_desc - EDMA TX complete descriptor. -+ * @word0: Low 32-bit opaque value. -+ * @word1: High 32-bit opaque value. -+ * @word2: More fragment, transmit ring id, pool id. -+ * @word3: Error indications. -+ */ -+struct edma_txcmpl_desc { -+ u32 word0; -+ u32 word1; -+ u32 word2; -+ u32 word3; -+}; -+ -+/** -+ * struct edma_txdesc_ring - EDMA TX descriptor ring -+ * @prod_idx: Producer index -+ * @id: Tx ring number -+ * @avail_desc: Number of available descriptor to process -+ * @pdesc: Primary descriptor ring virtual address -+ * @pdma: Primary descriptor ring physical address -+ * @sdesc: Secondary descriptor ring virtual address -+ * @tx_desc_stats: Tx descriptor ring statistics -+ * @sdma: Secondary descriptor ring physical address -+ * @count: Number of descriptors -+ * @fc_grp_id: Flow control group ID -+ */ -+struct edma_txdesc_ring { -+ u32 prod_idx; -+ u32 id; -+ u32 avail_desc; -+ struct edma_txdesc_pri *pdesc; -+ dma_addr_t pdma; -+ struct edma_txdesc_sec *sdesc; -+ struct edma_txdesc_stats txdesc_stats; -+ dma_addr_t sdma; -+ u32 count; -+ u8 fc_grp_id; -+}; -+ -+/** -+ * struct edma_txcmpl_ring - EDMA TX complete ring -+ * @napi: NAPI -+ * @cons_idx: Consumer index -+ * @avail_pkt: Number of available packets to process -+ * @desc: Descriptor ring virtual address -+ * @id: Txcmpl ring number -+ * @tx_cmpl_stats: Tx complete ring statistics -+ * @dma: Descriptor ring physical address -+ * @count: Number of descriptors in the ring -+ * @napi_added: Flag to indicate NAPI add status -+ */ -+struct edma_txcmpl_ring { -+ struct napi_struct napi; -+ u32 cons_idx; -+ u32 avail_pkt; -+ struct edma_txcmpl_desc *desc; -+ u32 id; -+ struct edma_txcmpl_stats txcmpl_stats; -+ dma_addr_t dma; -+ u32 count; -+ bool napi_added; -+}; -+ -+enum edma_tx_status edma_tx_ring_xmit(struct net_device *netdev, -+ struct sk_buff *skb, -+ struct edma_txdesc_ring *txdesc_ring, -+ struct edma_port_tx_stats *stats); -+u32 edma_tx_complete(u32 work_to_do, -+ struct edma_txcmpl_ring *txcmpl_ring); -+irqreturn_t edma_tx_handle_irq(int irq, void *ctx); -+int edma_tx_napi_poll(struct napi_struct *napi, int budget); -+enum edma_tx_gso_status edma_tx_gso_segment(struct sk_buff *skb, -+ struct net_device *netdev, struct sk_buff **segs); -+ -+#endif diff --git a/target/linux/qualcommbe/patches-6.12/0346-net-ethernet-qualcomm-Add-miscellaneous-error-interr.patch b/target/linux/qualcommbe/patches-6.12/0346-net-ethernet-qualcomm-Add-miscellaneous-error-interr.patch deleted file mode 100644 index 0bdfb0c897..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0346-net-ethernet-qualcomm-Add-miscellaneous-error-interr.patch +++ /dev/null @@ -1,730 +0,0 @@ -From 8a924457c0b71acee96c8f78ef386e2a354a2aca Mon Sep 17 00:00:00 2001 -From: Suruchi Agarwal -Date: Thu, 21 Mar 2024 16:31:04 -0700 -Subject: [PATCH] net: ethernet: qualcomm: Add miscellaneous error interrupts - and counters - -Miscellaneous error interrupts, EDMA Tx/Rx and error counters are supported -using debugfs framework. - -Change-Id: I7da8b978a7e93947b03a45269a81b401f35da31c -Co-developed-by: Pavithra R -Signed-off-by: Pavithra R -Signed-off-by: Suruchi Agarwal ---- - drivers/net/ethernet/qualcomm/ppe/Makefile | 2 +- - drivers/net/ethernet/qualcomm/ppe/edma.c | 162 ++++++++ - drivers/net/ethernet/qualcomm/ppe/edma.h | 30 ++ - .../net/ethernet/qualcomm/ppe/edma_debugfs.c | 370 ++++++++++++++++++ - .../net/ethernet/qualcomm/ppe/ppe_debugfs.c | 17 + - 5 files changed, 580 insertions(+), 1 deletion(-) - create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma_debugfs.c - ---- a/drivers/net/ethernet/qualcomm/ppe/Makefile -+++ b/drivers/net/ethernet/qualcomm/ppe/Makefile -@@ -7,4 +7,4 @@ obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o - qcom-ppe-objs := ppe.o ppe_config.o ppe_debugfs.o ppe_port.o - - #EDMA --qcom-ppe-objs += edma.o edma_cfg_rx.o edma_cfg_tx.o edma_port.o edma_rx.o edma_tx.o -+qcom-ppe-objs += edma.o edma_cfg_rx.o edma_cfg_tx.o edma_debugfs.o edma_port.o edma_rx.o edma_tx.o ---- a/drivers/net/ethernet/qualcomm/ppe/edma.c -+++ b/drivers/net/ethernet/qualcomm/ppe/edma.c -@@ -152,6 +152,42 @@ static int edma_clock_init(void) - } - - /** -+ * edma_err_stats_alloc - Allocate stats memory -+ * -+ * Allocate memory for per-CPU error stats. -+ */ -+int edma_err_stats_alloc(void) -+{ -+ u32 i; -+ -+ edma_ctx->err_stats = alloc_percpu(*edma_ctx->err_stats); -+ if (!edma_ctx->err_stats) -+ return -ENOMEM; -+ -+ for_each_possible_cpu(i) { -+ struct edma_err_stats *stats; -+ -+ stats = per_cpu_ptr(edma_ctx->err_stats, i); -+ u64_stats_init(&stats->syncp); -+ } -+ -+ return 0; -+} -+ -+/** -+ * edma_err_stats_free - Free stats memory -+ * -+ * Free memory of per-CPU error stats. -+ */ -+void edma_err_stats_free(void) -+{ -+ if (edma_ctx->err_stats) { -+ free_percpu(edma_ctx->err_stats); -+ edma_ctx->err_stats = NULL; -+ } -+} -+ -+/** - * edma_configure_ucast_prio_map_tbl - Configure unicast priority map table. - * - * Map int_priority values to priority class and initialize -@@ -191,11 +227,113 @@ static int edma_configure_ucast_prio_map - return ret; - } - -+static void edma_disable_misc_interrupt(void) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ u32 reg; -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_MISC_INT_MASK_ADDR; -+ regmap_write(regmap, reg, EDMA_MASK_INT_CLEAR); -+} -+ -+static void edma_enable_misc_interrupt(void) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ u32 reg; -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_MISC_INT_MASK_ADDR; -+ regmap_write(regmap, reg, edma_ctx->intr_info.intr_mask_misc); -+} -+ -+static irqreturn_t edma_misc_handle_irq(int irq, -+ __maybe_unused void *ctx) -+{ -+ struct edma_err_stats *stats = this_cpu_ptr(edma_ctx->err_stats); -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ u32 misc_intr_status, data, reg; -+ -+ /* Read Misc intr status */ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_MISC_INT_STAT_ADDR; -+ regmap_read(regmap, reg, &data); -+ misc_intr_status = data & edma_ctx->intr_info.intr_mask_misc; -+ -+ pr_debug("Received misc irq %d, status: %d\n", irq, misc_intr_status); -+ -+ if (FIELD_GET(EDMA_MISC_AXI_RD_ERR_MASK, misc_intr_status)) { -+ pr_err("MISC AXI read error received\n"); -+ u64_stats_update_begin(&stats->syncp); -+ ++stats->edma_axi_read_err; -+ u64_stats_update_end(&stats->syncp); -+ } -+ -+ if (FIELD_GET(EDMA_MISC_AXI_WR_ERR_MASK, misc_intr_status)) { -+ pr_err("MISC AXI write error received\n"); -+ u64_stats_update_begin(&stats->syncp); -+ ++stats->edma_axi_write_err; -+ u64_stats_update_end(&stats->syncp); -+ } -+ -+ if (FIELD_GET(EDMA_MISC_RX_DESC_FIFO_FULL_MASK, misc_intr_status)) { -+ if (net_ratelimit()) -+ pr_err("MISC Rx descriptor fifo full error received\n"); -+ u64_stats_update_begin(&stats->syncp); -+ ++stats->edma_rxdesc_fifo_full; -+ u64_stats_update_end(&stats->syncp); -+ } -+ -+ if (FIELD_GET(EDMA_MISC_RX_ERR_BUF_SIZE_MASK, misc_intr_status)) { -+ if (net_ratelimit()) -+ pr_err("MISC Rx buffer size error received\n"); -+ u64_stats_update_begin(&stats->syncp); -+ ++stats->edma_rx_buf_size_err; -+ u64_stats_update_end(&stats->syncp); -+ } -+ -+ if (FIELD_GET(EDMA_MISC_TX_SRAM_FULL_MASK, misc_intr_status)) { -+ if (net_ratelimit()) -+ pr_err("MISC Tx SRAM full error received\n"); -+ u64_stats_update_begin(&stats->syncp); -+ ++stats->edma_tx_sram_full; -+ u64_stats_update_end(&stats->syncp); -+ } -+ -+ if (FIELD_GET(EDMA_MISC_TX_CMPL_BUF_FULL_MASK, misc_intr_status)) { -+ if (net_ratelimit()) -+ pr_err("MISC Tx complete buffer full error received\n"); -+ u64_stats_update_begin(&stats->syncp); -+ ++stats->edma_txcmpl_buf_full; -+ u64_stats_update_end(&stats->syncp); -+ } -+ -+ if (FIELD_GET(EDMA_MISC_DATA_LEN_ERR_MASK, misc_intr_status)) { -+ if (net_ratelimit()) -+ pr_err("MISC data length error received\n"); -+ u64_stats_update_begin(&stats->syncp); -+ ++stats->edma_tx_data_len_err; -+ u64_stats_update_end(&stats->syncp); -+ } -+ -+ if (FIELD_GET(EDMA_MISC_TX_TIMEOUT_MASK, misc_intr_status)) { -+ if (net_ratelimit()) -+ pr_err("MISC Tx timeout error received\n"); -+ u64_stats_update_begin(&stats->syncp); -+ ++stats->edma_tx_timeout; -+ u64_stats_update_end(&stats->syncp); -+ } -+ -+ return IRQ_HANDLED; -+} -+ - static int edma_irq_register(void) - { - struct edma_hw_info *hw_info = edma_ctx->hw_info; - struct edma_ring_info *txcmpl = hw_info->txcmpl; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; - struct edma_ring_info *rx = hw_info->rx; -+ struct device *dev = ppe_dev->dev; - int ret; - u32 i; - -@@ -270,8 +408,25 @@ static int edma_irq_register(void) - edma_rxdesc_irq_name[i]); - } - -+ /* Request Misc IRQ */ -+ ret = request_irq(edma_ctx->intr_info.intr_misc, edma_misc_handle_irq, -+ IRQF_SHARED, "edma_misc", -+ (void *)dev); -+ if (ret) { -+ pr_err("MISC IRQ:%d request failed\n", -+ edma_ctx->intr_info.intr_misc); -+ goto misc_intr_req_fail; -+ } -+ - return 0; - -+misc_intr_req_fail: -+ /* Free IRQ for RXDESC rings */ -+ for (i = 0; i < rx->num_rings; i++) { -+ synchronize_irq(edma_ctx->intr_info.intr_rx[i]); -+ free_irq(edma_ctx->intr_info.intr_rx[i], -+ (void *)&edma_ctx->rx_rings[i]); -+ } - rx_desc_ring_intr_req_fail: - for (i = 0; i < rx->num_rings; i++) - kfree(edma_rxdesc_irq_name[i]); -@@ -503,6 +658,7 @@ static int edma_hw_configure(void) - edma_cfg_tx_disable_interrupts(i); - - edma_cfg_rx_disable_interrupts(); -+ edma_disable_misc_interrupt(); - - edma_cfg_rx_rings_disable(); - -@@ -614,6 +770,7 @@ void edma_destroy(struct ppe_device *ppe - edma_cfg_tx_disable_interrupts(i); - - edma_cfg_rx_disable_interrupts(); -+ edma_disable_misc_interrupt(); - - /* Free IRQ for TXCMPL rings. */ - for (i = 0; i < txcmpl->num_rings; i++) { -@@ -634,6 +791,10 @@ void edma_destroy(struct ppe_device *ppe - } - kfree(edma_rxdesc_irq_name); - -+ /* Free Misc IRQ */ -+ synchronize_irq(edma_ctx->intr_info.intr_misc); -+ free_irq(edma_ctx->intr_info.intr_misc, (void *)(ppe_dev->dev)); -+ - kfree(edma_ctx->intr_info.intr_rx); - kfree(edma_ctx->intr_info.intr_txcmpl); - -@@ -699,6 +860,7 @@ int edma_setup(struct ppe_device *ppe_de - } - - edma_cfg_rx_enable_interrupts(); -+ edma_enable_misc_interrupt(); - - dev_info(dev, "EDMA configuration successful\n"); - ---- a/drivers/net/ethernet/qualcomm/ppe/edma.h -+++ b/drivers/net/ethernet/qualcomm/ppe/edma.h -@@ -47,6 +47,30 @@ enum ppe_queue_class_type { - }; - - /** -+ * struct edma_err_stats - EDMA error stats -+ * @edma_axi_read_err: AXI read error -+ * @edma_axi_write_err: AXI write error -+ * @edma_rxdesc_fifo_full: Rx desc FIFO full error -+ * @edma_rx_buf_size_err: Rx buffer size too small error -+ * @edma_tx_sram_full: Tx packet SRAM buffer full error -+ * @edma_tx_data_len_err: Tx data length error -+ * @edma_tx_timeout: Tx timeout error -+ * @edma_txcmpl_buf_full: Tx completion buffer full error -+ * @syncp: Synchronization pointer -+ */ -+struct edma_err_stats { -+ u64 edma_axi_read_err; -+ u64 edma_axi_write_err; -+ u64 edma_rxdesc_fifo_full; -+ u64 edma_rx_buf_size_err; -+ u64 edma_tx_sram_full; -+ u64 edma_tx_data_len_err; -+ u64 edma_tx_timeout; -+ u64 edma_txcmpl_buf_full; -+ struct u64_stats_sync syncp; -+}; -+ -+/** - * struct edma_ring_info - EDMA ring data structure. - * @max_rings: Maximum number of rings - * @ring_start: Ring start ID -@@ -107,6 +131,7 @@ struct edma_intr_info { - * @rx_rings: Rx Desc Rings, SW is consumer - * @tx_rings: Tx Descriptor Ring, SW is producer - * @txcmpl_rings: Tx complete Ring, SW is consumer -+ * @err_stats: Per CPU error statistics - * @rx_page_mode: Page mode enabled or disabled - * @rx_buf_size: Rx buffer size for Jumbo MRU - * @tx_requeue_stop: Tx requeue stop enabled or disabled -@@ -121,6 +146,7 @@ struct edma_context { - struct edma_rxdesc_ring *rx_rings; - struct edma_txdesc_ring *tx_rings; - struct edma_txcmpl_ring *txcmpl_rings; -+ struct edma_err_stats __percpu *err_stats; - u32 rx_page_mode; - u32 rx_buf_size; - bool tx_requeue_stop; -@@ -129,8 +155,12 @@ struct edma_context { - /* Global EDMA context */ - extern struct edma_context *edma_ctx; - -+int edma_err_stats_alloc(void); -+void edma_err_stats_free(void); - void edma_destroy(struct ppe_device *ppe_dev); - int edma_setup(struct ppe_device *ppe_dev); -+void edma_debugfs_teardown(void); -+int edma_debugfs_setup(struct ppe_device *ppe_dev); - int ppe_edma_queue_offset_config(struct ppe_device *ppe_dev, - enum ppe_queue_class_type class, - int index, int queue_offset); ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_debugfs.c -@@ -0,0 +1,370 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+/* EDMA debugfs routines for display of Tx/Rx counters. */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "edma.h" -+ -+#define EDMA_STATS_BANNER_MAX_LEN 80 -+#define EDMA_RX_RING_STATS_NODE_NAME "EDMA_RX" -+#define EDMA_TX_RING_STATS_NODE_NAME "EDMA_TX" -+#define EDMA_ERR_STATS_NODE_NAME "EDMA_ERR" -+ -+static struct dentry *edma_dentry; -+static struct dentry *stats_dentry; -+ -+static void edma_debugfs_print_banner(struct seq_file *m, char *node) -+{ -+ u32 banner_char_len, i; -+ -+ for (i = 0; i < EDMA_STATS_BANNER_MAX_LEN; i++) -+ seq_puts(m, "_"); -+ banner_char_len = (EDMA_STATS_BANNER_MAX_LEN - (strlen(node) + 2)) / 2; -+ seq_puts(m, "\n\n"); -+ -+ for (i = 0; i < banner_char_len; i++) -+ seq_puts(m, "<"); -+ seq_printf(m, " %s ", node); -+ -+ for (i = 0; i < banner_char_len; i++) -+ seq_puts(m, ">"); -+ seq_puts(m, "\n"); -+ -+ for (i = 0; i < EDMA_STATS_BANNER_MAX_LEN; i++) -+ seq_puts(m, "_"); -+ seq_puts(m, "\n\n"); -+} -+ -+static int edma_debugfs_rx_rings_stats_show(struct seq_file *m, -+ void __maybe_unused *p) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rxfill = hw_info->rxfill; -+ struct edma_rxfill_stats *rxfill_stats; -+ struct edma_rxdesc_stats *rxdesc_stats; -+ struct edma_ring_info *rx = hw_info->rx; -+ unsigned int start; -+ u32 i; -+ -+ rxfill_stats = kcalloc(rxfill->num_rings, sizeof(*rxfill_stats), GFP_KERNEL); -+ if (!rxfill_stats) -+ return -ENOMEM; -+ -+ rxdesc_stats = kcalloc(rx->num_rings, sizeof(*rxdesc_stats), GFP_KERNEL); -+ if (!rxdesc_stats) { -+ kfree(rxfill_stats); -+ return -ENOMEM; -+ } -+ -+ /* Get stats for Rx fill rings. */ -+ for (i = 0; i < rxfill->num_rings; i++) { -+ struct edma_rxfill_ring *rxfill_ring; -+ struct edma_rxfill_stats *stats; -+ -+ rxfill_ring = &edma_ctx->rxfill_rings[i]; -+ stats = &rxfill_ring->rxfill_stats; -+ do { -+ start = u64_stats_fetch_begin(&stats->syncp); -+ rxfill_stats[i].alloc_failed = stats->alloc_failed; -+ rxfill_stats[i].page_alloc_failed = stats->page_alloc_failed; -+ } while (u64_stats_fetch_retry(&stats->syncp, start)); -+ } -+ -+ /* Get stats for Rx Desc rings. */ -+ for (i = 0; i < rx->num_rings; i++) { -+ struct edma_rxdesc_ring *rxdesc_ring; -+ struct edma_rxdesc_stats *stats; -+ -+ rxdesc_ring = &edma_ctx->rx_rings[i]; -+ stats = &rxdesc_ring->rxdesc_stats; -+ do { -+ start = u64_stats_fetch_begin(&stats->syncp); -+ rxdesc_stats[i].src_port_inval = stats->src_port_inval; -+ rxdesc_stats[i].src_port_inval_type = stats->src_port_inval_type; -+ rxdesc_stats[i].src_port_inval_netdev = stats->src_port_inval_netdev; -+ } while (u64_stats_fetch_retry(&stats->syncp, start)); -+ } -+ -+ edma_debugfs_print_banner(m, EDMA_RX_RING_STATS_NODE_NAME); -+ -+ seq_puts(m, "\n#EDMA RX descriptor rings stats:\n\n"); -+ for (i = 0; i < rx->num_rings; i++) { -+ seq_printf(m, "\t\tEDMA RX descriptor %d ring stats:\n", i + rx->ring_start); -+ seq_printf(m, "\t\t rxdesc[%d]:src_port_inval = %llu\n", -+ i + rx->ring_start, rxdesc_stats[i].src_port_inval); -+ seq_printf(m, "\t\t rxdesc[%d]:src_port_inval_type = %llu\n", -+ i + rx->ring_start, rxdesc_stats[i].src_port_inval_type); -+ seq_printf(m, "\t\t rxdesc[%d]:src_port_inval_netdev = %llu\n", -+ i + rx->ring_start, -+ rxdesc_stats[i].src_port_inval_netdev); -+ seq_puts(m, "\n"); -+ } -+ -+ seq_puts(m, "\n#EDMA RX fill rings stats:\n\n"); -+ for (i = 0; i < rxfill->num_rings; i++) { -+ seq_printf(m, "\t\tEDMA RX fill %d ring stats:\n", i + rxfill->ring_start); -+ seq_printf(m, "\t\t rxfill[%d]:alloc_failed = %llu\n", -+ i + rxfill->ring_start, rxfill_stats[i].alloc_failed); -+ seq_printf(m, "\t\t rxfill[%d]:page_alloc_failed = %llu\n", -+ i + rxfill->ring_start, rxfill_stats[i].page_alloc_failed); -+ seq_puts(m, "\n"); -+ } -+ -+ kfree(rxfill_stats); -+ kfree(rxdesc_stats); -+ return 0; -+} -+ -+static int edma_debugfs_tx_rings_stats_show(struct seq_file *m, -+ void __maybe_unused *p) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *txcmpl = hw_info->txcmpl; -+ struct edma_ring_info *tx = hw_info->tx; -+ struct edma_txcmpl_stats *txcmpl_stats; -+ struct edma_txdesc_stats *txdesc_stats; -+ unsigned int start; -+ u32 i; -+ -+ txcmpl_stats = kcalloc(txcmpl->num_rings, sizeof(*txcmpl_stats), GFP_KERNEL); -+ if (!txcmpl_stats) -+ return -ENOMEM; -+ -+ txdesc_stats = kcalloc(tx->num_rings, sizeof(*txdesc_stats), GFP_KERNEL); -+ if (!txdesc_stats) { -+ kfree(txcmpl_stats); -+ return -ENOMEM; -+ } -+ -+ /* Get stats for Tx desc rings. */ -+ for (i = 0; i < tx->num_rings; i++) { -+ struct edma_txdesc_ring *txdesc_ring; -+ struct edma_txdesc_stats *stats; -+ -+ txdesc_ring = &edma_ctx->tx_rings[i]; -+ stats = &txdesc_ring->txdesc_stats; -+ do { -+ start = u64_stats_fetch_begin(&stats->syncp); -+ txdesc_stats[i].no_desc_avail = stats->no_desc_avail; -+ txdesc_stats[i].tso_max_seg_exceed = stats->tso_max_seg_exceed; -+ } while (u64_stats_fetch_retry(&stats->syncp, start)); -+ } -+ -+ /* Get stats for Tx Complete rings. */ -+ for (i = 0; i < txcmpl->num_rings; i++) { -+ struct edma_txcmpl_ring *txcmpl_ring; -+ struct edma_txcmpl_stats *stats; -+ -+ txcmpl_ring = &edma_ctx->txcmpl_rings[i]; -+ stats = &txcmpl_ring->txcmpl_stats; -+ do { -+ start = u64_stats_fetch_begin(&stats->syncp); -+ txcmpl_stats[i].invalid_buffer = stats->invalid_buffer; -+ txcmpl_stats[i].errors = stats->errors; -+ txcmpl_stats[i].desc_with_more_bit = stats->desc_with_more_bit; -+ txcmpl_stats[i].no_pending_desc = stats->no_pending_desc; -+ } while (u64_stats_fetch_retry(&stats->syncp, start)); -+ } -+ -+ edma_debugfs_print_banner(m, EDMA_TX_RING_STATS_NODE_NAME); -+ -+ seq_puts(m, "\n#EDMA TX complete rings stats:\n\n"); -+ for (i = 0; i < txcmpl->num_rings; i++) { -+ seq_printf(m, "\t\tEDMA TX complete %d ring stats:\n", i + txcmpl->ring_start); -+ seq_printf(m, "\t\t txcmpl[%d]:invalid_buffer = %llu\n", -+ i + txcmpl->ring_start, txcmpl_stats[i].invalid_buffer); -+ seq_printf(m, "\t\t txcmpl[%d]:errors = %llu\n", -+ i + txcmpl->ring_start, txcmpl_stats[i].errors); -+ seq_printf(m, "\t\t txcmpl[%d]:desc_with_more_bit = %llu\n", -+ i + txcmpl->ring_start, txcmpl_stats[i].desc_with_more_bit); -+ seq_printf(m, "\t\t txcmpl[%d]:no_pending_desc = %llu\n", -+ i + txcmpl->ring_start, txcmpl_stats[i].no_pending_desc); -+ seq_puts(m, "\n"); -+ } -+ -+ seq_puts(m, "\n#EDMA TX descriptor rings stats:\n\n"); -+ for (i = 0; i < tx->num_rings; i++) { -+ seq_printf(m, "\t\tEDMA TX descriptor %d ring stats:\n", i + tx->ring_start); -+ seq_printf(m, "\t\t txdesc[%d]:no_desc_avail = %llu\n", -+ i + tx->ring_start, txdesc_stats[i].no_desc_avail); -+ seq_printf(m, "\t\t txdesc[%d]:tso_max_seg_exceed = %llu\n", -+ i + tx->ring_start, txdesc_stats[i].tso_max_seg_exceed); -+ seq_puts(m, "\n"); -+ } -+ -+ kfree(txcmpl_stats); -+ kfree(txdesc_stats); -+ return 0; -+} -+ -+static int edma_debugfs_err_stats_show(struct seq_file *m, -+ void __maybe_unused *p) -+{ -+ struct edma_err_stats *err_stats, *pcpu_err_stats; -+ unsigned int start; -+ u32 cpu; -+ -+ err_stats = kzalloc(sizeof(*err_stats), GFP_KERNEL); -+ if (!err_stats) -+ return -ENOMEM; -+ -+ /* Get percpu EDMA miscellaneous stats. */ -+ for_each_possible_cpu(cpu) { -+ pcpu_err_stats = per_cpu_ptr(edma_ctx->err_stats, cpu); -+ do { -+ start = u64_stats_fetch_begin(&pcpu_err_stats->syncp); -+ err_stats->edma_axi_read_err += -+ pcpu_err_stats->edma_axi_read_err; -+ err_stats->edma_axi_write_err += -+ pcpu_err_stats->edma_axi_write_err; -+ err_stats->edma_rxdesc_fifo_full += -+ pcpu_err_stats->edma_rxdesc_fifo_full; -+ err_stats->edma_rx_buf_size_err += -+ pcpu_err_stats->edma_rx_buf_size_err; -+ err_stats->edma_tx_sram_full += -+ pcpu_err_stats->edma_tx_sram_full; -+ err_stats->edma_tx_data_len_err += -+ pcpu_err_stats->edma_tx_data_len_err; -+ err_stats->edma_tx_timeout += -+ pcpu_err_stats->edma_tx_timeout; -+ err_stats->edma_txcmpl_buf_full += -+ pcpu_err_stats->edma_txcmpl_buf_full; -+ } while (u64_stats_fetch_retry(&pcpu_err_stats->syncp, start)); -+ } -+ -+ edma_debugfs_print_banner(m, EDMA_ERR_STATS_NODE_NAME); -+ -+ seq_puts(m, "\n#EDMA error stats:\n\n"); -+ seq_printf(m, "\t\t axi read error = %llu\n", -+ err_stats->edma_axi_read_err); -+ seq_printf(m, "\t\t axi write error = %llu\n", -+ err_stats->edma_axi_write_err); -+ seq_printf(m, "\t\t Rx descriptor fifo full = %llu\n", -+ err_stats->edma_rxdesc_fifo_full); -+ seq_printf(m, "\t\t Rx buffer size error = %llu\n", -+ err_stats->edma_rx_buf_size_err); -+ seq_printf(m, "\t\t Tx SRAM full = %llu\n", -+ err_stats->edma_tx_sram_full); -+ seq_printf(m, "\t\t Tx data length error = %llu\n", -+ err_stats->edma_tx_data_len_err); -+ seq_printf(m, "\t\t Tx timeout = %llu\n", -+ err_stats->edma_tx_timeout); -+ seq_printf(m, "\t\t Tx completion buffer full = %llu\n", -+ err_stats->edma_txcmpl_buf_full); -+ -+ kfree(err_stats); -+ return 0; -+} -+ -+static int edma_debugs_rx_rings_stats_open(struct inode *inode, -+ struct file *file) -+{ -+ return single_open(file, edma_debugfs_rx_rings_stats_show, -+ inode->i_private); -+} -+ -+static const struct file_operations edma_debugfs_rx_rings_file_ops = { -+ .open = edma_debugs_rx_rings_stats_open, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = seq_release -+}; -+ -+static int edma_debugs_tx_rings_stats_open(struct inode *inode, struct file *file) -+{ -+ return single_open(file, edma_debugfs_tx_rings_stats_show, inode->i_private); -+} -+ -+static const struct file_operations edma_debugfs_tx_rings_file_ops = { -+ .open = edma_debugs_tx_rings_stats_open, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = seq_release -+}; -+ -+static int edma_debugs_err_stats_open(struct inode *inode, struct file *file) -+{ -+ return single_open(file, edma_debugfs_err_stats_show, inode->i_private); -+} -+ -+static const struct file_operations edma_debugfs_misc_file_ops = { -+ .open = edma_debugs_err_stats_open, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = seq_release -+}; -+ -+/** -+ * edma_debugfs_teardown - EDMA debugfs teardown. -+ * -+ * EDMA debugfs teardown and free stats memory. -+ */ -+void edma_debugfs_teardown(void) -+{ -+ /* Free EDMA miscellaneous stats memory */ -+ edma_err_stats_free(); -+ -+ debugfs_remove_recursive(edma_dentry); -+ edma_dentry = NULL; -+ stats_dentry = NULL; -+} -+ -+/** -+ * edma_debugfs_setup - EDMA debugfs setup. -+ * @ppe_dev: PPE Device -+ * -+ * EDMA debugfs setup. -+ */ -+int edma_debugfs_setup(struct ppe_device *ppe_dev) -+{ -+ edma_dentry = debugfs_create_dir("edma", ppe_dev->debugfs_root); -+ if (!edma_dentry) { -+ pr_err("Unable to create debugfs edma directory in debugfs\n"); -+ goto debugfs_dir_failed; -+ } -+ -+ stats_dentry = debugfs_create_dir("stats", edma_dentry); -+ if (!stats_dentry) { -+ pr_err("Unable to create debugfs stats directory in debugfs\n"); -+ goto debugfs_dir_failed; -+ } -+ -+ if (!debugfs_create_file("rx_ring_stats", 0444, stats_dentry, -+ NULL, &edma_debugfs_rx_rings_file_ops)) { -+ pr_err("Unable to create Rx rings statistics file entry in debugfs\n"); -+ goto debugfs_dir_failed; -+ } -+ -+ if (!debugfs_create_file("tx_ring_stats", 0444, stats_dentry, -+ NULL, &edma_debugfs_tx_rings_file_ops)) { -+ pr_err("Unable to create Tx rings statistics file entry in debugfs\n"); -+ goto debugfs_dir_failed; -+ } -+ -+ /* Allocate memory for EDMA miscellaneous stats */ -+ if (edma_err_stats_alloc() < 0) { -+ pr_err("Unable to allocate miscellaneous percpu stats\n"); -+ goto debugfs_dir_failed; -+ } -+ -+ if (!debugfs_create_file("err_stats", 0444, stats_dentry, -+ NULL, &edma_debugfs_misc_file_ops)) { -+ pr_err("Unable to create EDMA miscellaneous statistics file entry in debugfs\n"); -+ goto debugfs_dir_failed; -+ } -+ -+ return 0; -+ -+debugfs_dir_failed: -+ debugfs_remove_recursive(edma_dentry); -+ edma_dentry = NULL; -+ stats_dentry = NULL; -+ return -ENOMEM; -+} ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_debugfs.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_debugfs.c -@@ -7,9 +7,11 @@ - - #include - #include -+#include - #include - #include - -+#include "edma.h" - #include "ppe.h" - #include "ppe_config.h" - #include "ppe_debugfs.h" -@@ -678,15 +680,30 @@ static const struct file_operations ppe_ - - void ppe_debugfs_setup(struct ppe_device *ppe_dev) - { -+ int ret; -+ - ppe_dev->debugfs_root = debugfs_create_dir("ppe", NULL); - debugfs_create_file("packet_counters", 0444, - ppe_dev->debugfs_root, - ppe_dev, - &ppe_debugfs_packet_counter_fops); -+ -+ if (!ppe_dev->debugfs_root) { -+ dev_err(ppe_dev->dev, "Error in PPE debugfs setup\n"); -+ return; -+ } -+ -+ ret = edma_debugfs_setup(ppe_dev); -+ if (ret) { -+ dev_err(ppe_dev->dev, "Error in EDMA debugfs setup API. ret: %d\n", ret); -+ debugfs_remove_recursive(ppe_dev->debugfs_root); -+ ppe_dev->debugfs_root = NULL; -+ } - } - - void ppe_debugfs_teardown(struct ppe_device *ppe_dev) - { -+ edma_debugfs_teardown(); - debugfs_remove_recursive(ppe_dev->debugfs_root); - ppe_dev->debugfs_root = NULL; - } diff --git a/target/linux/qualcommbe/patches-6.12/0347-net-ethernet-qualcomm-Add-ethtool-support-for-EDMA.patch b/target/linux/qualcommbe/patches-6.12/0347-net-ethernet-qualcomm-Add-ethtool-support-for-EDMA.patch deleted file mode 100644 index 4e0103db57..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0347-net-ethernet-qualcomm-Add-ethtool-support-for-EDMA.patch +++ /dev/null @@ -1,344 +0,0 @@ -From bd61a680fb657eb65272225f18c93fe338c700da Mon Sep 17 00:00:00 2001 -From: Pavithra R -Date: Thu, 30 May 2024 20:46:36 +0530 -Subject: [PATCH] net: ethernet: qualcomm: Add ethtool support for EDMA - -ethtool ops can be used for EDMA netdevice configuration and statistics. - -Change-Id: I57fc19415dacbe51fed000520336463938220609 -Signed-off-by: Pavithra R -Alex G: use struct ethtool_keee instead of ethtool_eee -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/ethernet/qualcomm/ppe/Makefile | 2 +- - drivers/net/ethernet/qualcomm/ppe/edma.h | 1 + - .../net/ethernet/qualcomm/ppe/edma_ethtool.c | 294 ++++++++++++++++++ - drivers/net/ethernet/qualcomm/ppe/edma_port.c | 1 + - 4 files changed, 297 insertions(+), 1 deletion(-) - create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma_ethtool.c - ---- a/drivers/net/ethernet/qualcomm/ppe/Makefile -+++ b/drivers/net/ethernet/qualcomm/ppe/Makefile -@@ -7,4 +7,4 @@ obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o - qcom-ppe-objs := ppe.o ppe_config.o ppe_debugfs.o ppe_port.o - - #EDMA --qcom-ppe-objs += edma.o edma_cfg_rx.o edma_cfg_tx.o edma_debugfs.o edma_port.o edma_rx.o edma_tx.o -+qcom-ppe-objs += edma.o edma_cfg_rx.o edma_cfg_tx.o edma_debugfs.o edma_port.o edma_rx.o edma_tx.o edma_ethtool.o ---- a/drivers/net/ethernet/qualcomm/ppe/edma.h -+++ b/drivers/net/ethernet/qualcomm/ppe/edma.h -@@ -161,6 +161,7 @@ void edma_destroy(struct ppe_device *ppe - int edma_setup(struct ppe_device *ppe_dev); - void edma_debugfs_teardown(void); - int edma_debugfs_setup(struct ppe_device *ppe_dev); -+void edma_set_ethtool_ops(struct net_device *netdev); - int ppe_edma_queue_offset_config(struct ppe_device *ppe_dev, - enum ppe_queue_class_type class, - int index, int queue_offset); ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_ethtool.c -@@ -0,0 +1,294 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+/* ethtool support for EDMA */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "edma.h" -+#include "edma_port.h" -+ -+struct edma_ethtool_stats { -+ u8 stat_string[ETH_GSTRING_LEN]; -+ u32 stat_offset; -+}; -+ -+/** -+ * struct edma_gmac_stats - Per-GMAC statistics. -+ * @rx_packets: Number of RX packets -+ * @rx_bytes: Number of RX bytes -+ * @rx_dropped: Number of RX dropped packets -+ * @rx_fraglist_packets: Number of RX fraglist packets -+ * @rx_nr_frag_packets: Number of RX nr fragment packets -+ * @rx_nr_frag_headroom_err: Number of RX nr fragment packets with headroom error -+ * @tx_packets: Number of TX packets -+ * @tx_bytes: Number of TX bytes -+ * @tx_dropped: Number of TX dropped packets -+ * @tx_nr_frag_packets: Number of TX nr fragment packets -+ * @tx_fraglist_packets: Number of TX fraglist packets -+ * @tx_fraglist_with_nr_frags_packets: Number of TX fraglist packets with nr fragments -+ * @tx_tso_packets: Number of TX TCP segmentation offload packets -+ * @tx_tso_drop_packets: Number of TX TCP segmentation dropped packets -+ * @tx_gso_packets: Number of TX SW GSO packets -+ * @tx_gso_drop_packets: Number of TX SW GSO dropped packets -+ * @tx_queue_stopped: Number of times Queue got stopped -+ */ -+struct edma_gmac_stats { -+ u64 rx_packets; -+ u64 rx_bytes; -+ u64 rx_dropped; -+ u64 rx_fraglist_packets; -+ u64 rx_nr_frag_packets; -+ u64 rx_nr_frag_headroom_err; -+ u64 tx_packets; -+ u64 tx_bytes; -+ u64 tx_dropped; -+ u64 tx_nr_frag_packets; -+ u64 tx_fraglist_packets; -+ u64 tx_fraglist_with_nr_frags_packets; -+ u64 tx_tso_packets; -+ u64 tx_tso_drop_packets; -+ u64 tx_gso_packets; -+ u64 tx_gso_drop_packets; -+ u64 tx_queue_stopped[EDMA_MAX_CORE]; -+}; -+ -+#define EDMA_STAT(m) offsetof(struct edma_gmac_stats, m) -+ -+static const struct edma_ethtool_stats edma_gstrings_stats[] = { -+ {"rx_bytes", EDMA_STAT(rx_bytes)}, -+ {"rx_packets", EDMA_STAT(rx_packets)}, -+ {"rx_dropped", EDMA_STAT(rx_dropped)}, -+ {"rx_fraglist_packets", EDMA_STAT(rx_fraglist_packets)}, -+ {"rx_nr_frag_packets", EDMA_STAT(rx_nr_frag_packets)}, -+ {"rx_nr_frag_headroom_err", EDMA_STAT(rx_nr_frag_headroom_err)}, -+ {"tx_bytes", EDMA_STAT(tx_bytes)}, -+ {"tx_packets", EDMA_STAT(tx_packets)}, -+ {"tx_dropped", EDMA_STAT(tx_dropped)}, -+ {"tx_nr_frag_packets", EDMA_STAT(tx_nr_frag_packets)}, -+ {"tx_fraglist_packets", EDMA_STAT(tx_fraglist_packets)}, -+ {"tx_fraglist_nr_frags_packets", EDMA_STAT(tx_fraglist_with_nr_frags_packets)}, -+ {"tx_tso_packets", EDMA_STAT(tx_tso_packets)}, -+ {"tx_tso_drop_packets", EDMA_STAT(tx_tso_drop_packets)}, -+ {"tx_gso_packets", EDMA_STAT(tx_gso_packets)}, -+ {"tx_gso_drop_packets", EDMA_STAT(tx_gso_drop_packets)}, -+ {"tx_queue_stopped_cpu0", EDMA_STAT(tx_queue_stopped[0])}, -+ {"tx_queue_stopped_cpu1", EDMA_STAT(tx_queue_stopped[1])}, -+ {"tx_queue_stopped_cpu2", EDMA_STAT(tx_queue_stopped[2])}, -+ {"tx_queue_stopped_cpu3", EDMA_STAT(tx_queue_stopped[3])}, -+}; -+ -+#define EDMA_STATS_LEN ARRAY_SIZE(edma_gstrings_stats) -+ -+static void edma_port_get_stats(struct net_device *netdev, -+ struct edma_gmac_stats *stats) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ struct edma_port_rx_stats *pcpu_rx_stats; -+ struct edma_port_tx_stats *pcpu_tx_stats; -+ int i; -+ -+ memset(stats, 0, sizeof(struct edma_port_pcpu_stats)); -+ -+ for_each_possible_cpu(i) { -+ struct edma_port_rx_stats rxp; -+ struct edma_port_tx_stats txp; -+ unsigned int start; -+ -+ pcpu_rx_stats = per_cpu_ptr(port_priv->pcpu_stats.rx_stats, i); -+ -+ do { -+ start = u64_stats_fetch_begin(&pcpu_rx_stats->syncp); -+ memcpy(&rxp, pcpu_rx_stats, sizeof(*pcpu_rx_stats)); -+ } while (u64_stats_fetch_retry(&pcpu_rx_stats->syncp, start)); -+ -+ stats->rx_packets += rxp.rx_pkts; -+ stats->rx_bytes += rxp.rx_bytes; -+ stats->rx_dropped += rxp.rx_drops; -+ stats->rx_nr_frag_packets += rxp.rx_nr_frag_pkts; -+ stats->rx_fraglist_packets += rxp.rx_fraglist_pkts; -+ stats->rx_nr_frag_headroom_err += rxp.rx_nr_frag_headroom_err; -+ -+ pcpu_tx_stats = per_cpu_ptr(port_priv->pcpu_stats.tx_stats, i); -+ -+ do { -+ start = u64_stats_fetch_begin(&pcpu_tx_stats->syncp); -+ memcpy(&txp, pcpu_tx_stats, sizeof(*pcpu_tx_stats)); -+ } while (u64_stats_fetch_retry(&pcpu_tx_stats->syncp, start)); -+ -+ stats->tx_packets += txp.tx_pkts; -+ stats->tx_bytes += txp.tx_bytes; -+ stats->tx_dropped += txp.tx_drops; -+ stats->tx_nr_frag_packets += txp.tx_nr_frag_pkts; -+ stats->tx_fraglist_packets += txp.tx_fraglist_pkts; -+ stats->tx_fraglist_with_nr_frags_packets += txp.tx_fraglist_with_nr_frags_pkts; -+ stats->tx_tso_packets += txp.tx_tso_pkts; -+ stats->tx_tso_drop_packets += txp.tx_tso_drop_pkts; -+ stats->tx_gso_packets += txp.tx_gso_pkts; -+ stats->tx_gso_drop_packets += txp.tx_gso_drop_pkts; -+ stats->tx_queue_stopped[i] += txp.tx_queue_stopped[i]; -+ } -+} -+ -+static void edma_get_ethtool_stats(struct net_device *netdev, -+ __maybe_unused struct ethtool_stats *stats, -+ u64 *data) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ struct edma_gmac_stats edma_stats; -+ u64 *mib_data; -+ int i; -+ u8 *p; -+ -+ if (!port_priv) -+ return; -+ -+ /* Get the DMA Driver statistics from the data plane if available. */ -+ memset(&edma_stats, 0, sizeof(struct edma_gmac_stats)); -+ edma_port_get_stats(netdev, &edma_stats); -+ -+ /* Populate data plane statistics. */ -+ for (i = 0; i < EDMA_STATS_LEN; i++) { -+ p = ((u8 *)(&edma_stats) + edma_gstrings_stats[i].stat_offset); -+ data[i] = *(u64 *)p; -+ } -+ -+ /* Get the GMAC MIB statistics along with the DMA driver statistics. */ -+ mib_data = &data[EDMA_STATS_LEN]; -+ ppe_port_get_ethtool_stats(port_priv->ppe_port, mib_data); -+} -+ -+static int edma_get_strset_count(struct net_device *netdev, int sset) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ int sset_count = 0; -+ -+ if (!port_priv || sset != ETH_SS_STATS) -+ return 0; -+ -+ sset_count = ppe_port_get_sset_count(port_priv->ppe_port, sset); -+ -+ return (EDMA_STATS_LEN + sset_count); -+} -+ -+static void edma_get_strings(struct net_device *netdev, u32 stringset, -+ u8 *data) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ int i; -+ -+ if (!port_priv || stringset != ETH_SS_STATS) -+ return; -+ -+ for (i = 0; i < EDMA_STATS_LEN; i++) { -+ memcpy(data, edma_gstrings_stats[i].stat_string, -+ strlen(edma_gstrings_stats[i].stat_string)); -+ data += ETH_GSTRING_LEN; -+ } -+ -+ ppe_port_get_strings(port_priv->ppe_port, stringset, data); -+} -+ -+static int edma_get_link_ksettings(struct net_device *netdev, -+ struct ethtool_link_ksettings *cmd) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ struct ppe_port *port = port_priv->ppe_port; -+ -+ if (!port_priv) -+ return -EINVAL; -+ -+ return phylink_ethtool_ksettings_get(port->phylink, cmd); -+} -+ -+static int edma_set_link_ksettings(struct net_device *netdev, -+ const struct ethtool_link_ksettings *cmd) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ struct ppe_port *port = port_priv->ppe_port; -+ -+ if (!port_priv) -+ return -EINVAL; -+ -+ return phylink_ethtool_ksettings_set(port->phylink, cmd); -+} -+ -+static void edma_get_pauseparam(struct net_device *netdev, -+ struct ethtool_pauseparam *pause) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ struct ppe_port *port = port_priv->ppe_port; -+ -+ if (!port_priv) -+ return; -+ -+ phylink_ethtool_get_pauseparam(port->phylink, pause); -+} -+ -+static int edma_set_pauseparam(struct net_device *netdev, -+ struct ethtool_pauseparam *pause) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ struct ppe_port *port = port_priv->ppe_port; -+ -+ if (!port_priv) -+ return -EINVAL; -+ -+ return phylink_ethtool_set_pauseparam(port->phylink, pause); -+} -+ -+static int edma_get_eee(struct net_device *netdev, struct ethtool_keee *eee) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ struct ppe_port *port = port_priv->ppe_port; -+ -+ if (!port_priv) -+ return -EINVAL; -+ -+ return phylink_ethtool_get_eee(port->phylink, eee); -+} -+ -+static int edma_set_eee(struct net_device *netdev, struct ethtool_keee *eee) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ struct ppe_port *port = port_priv->ppe_port; -+ int ret; -+ -+ if (!port_priv) -+ return -EINVAL; -+ -+ ret = ppe_port_set_mac_eee(port_priv->ppe_port, eee); -+ if (ret) -+ return ret; -+ -+ return phylink_ethtool_set_eee(port->phylink, eee); -+} -+ -+static const struct ethtool_ops edma_ethtool_ops = { -+ .get_strings = &edma_get_strings, -+ .get_sset_count = &edma_get_strset_count, -+ .get_ethtool_stats = &edma_get_ethtool_stats, -+ .get_link = ðtool_op_get_link, -+ .get_link_ksettings = edma_get_link_ksettings, -+ .set_link_ksettings = edma_set_link_ksettings, -+ .get_pauseparam = &edma_get_pauseparam, -+ .set_pauseparam = &edma_set_pauseparam, -+ .get_eee = &edma_get_eee, -+ .set_eee = &edma_set_eee, -+}; -+ -+/** -+ * edma_set_ethtool_ops - Set ethtool operations -+ * @netdev: Netdevice -+ * -+ * Set ethtool operations. -+ */ -+void edma_set_ethtool_ops(struct net_device *netdev) -+{ -+ netdev->ethtool_ops = &edma_ethtool_ops; -+} ---- a/drivers/net/ethernet/qualcomm/ppe/edma_port.c -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_port.c -@@ -380,6 +380,7 @@ int edma_port_setup(struct ppe_port *por - netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE; - netdev->netdev_ops = &edma_port_netdev_ops; - netdev->gso_max_segs = GSO_MAX_SEGS; -+ edma_set_ethtool_ops(netdev); - - maddr = mac_addr; - if (of_get_mac_address(np, maddr)) diff --git a/target/linux/qualcommbe/patches-6.12/0348-net-ethernet-qualcomm-Add-module-parameters-for-driv.patch b/target/linux/qualcommbe/patches-6.12/0348-net-ethernet-qualcomm-Add-module-parameters-for-driv.patch deleted file mode 100644 index 65eb3c6c20..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0348-net-ethernet-qualcomm-Add-module-parameters-for-driv.patch +++ /dev/null @@ -1,286 +0,0 @@ -From 2ecec7e47e269e05cdd393c34aae51d4866070c6 Mon Sep 17 00:00:00 2001 -From: Pavithra R -Date: Tue, 11 Jun 2024 00:00:46 +0530 -Subject: [PATCH] net: ethernet: qualcomm: Add module parameters for driver - tunings - -Add module params and corresponding functionality for Tx/Rx -mitigation timer/packet count, napi budget and tx requeue stop. - -Change-Id: I1717559c931bba4f355ee06ab89f289818400ca2 -Signed-off-by: Pavithra R ---- - drivers/net/ethernet/qualcomm/ppe/edma.c | 35 +++++++++++++++++++ - .../net/ethernet/qualcomm/ppe/edma_cfg_rx.c | 29 +++++++++++++-- - .../net/ethernet/qualcomm/ppe/edma_cfg_rx.h | 21 +++++++++++ - .../net/ethernet/qualcomm/ppe/edma_cfg_tx.c | 29 +++++++++++++-- - .../net/ethernet/qualcomm/ppe/edma_cfg_tx.h | 16 +++++++++ - drivers/net/ethernet/qualcomm/ppe/edma_rx.h | 4 +++ - drivers/net/ethernet/qualcomm/ppe/edma_tx.h | 4 +++ - 7 files changed, 134 insertions(+), 4 deletions(-) - ---- a/drivers/net/ethernet/qualcomm/ppe/edma.c -+++ b/drivers/net/ethernet/qualcomm/ppe/edma.c -@@ -38,6 +38,38 @@ static int rx_buff_size; - module_param(rx_buff_size, int, 0640); - MODULE_PARM_DESC(rx_buff_size, "Rx Buffer size for Jumbo MRU value (default:0)"); - -+int edma_rx_napi_budget = EDMA_RX_NAPI_WORK_DEF; -+module_param(edma_rx_napi_budget, int, 0444); -+MODULE_PARM_DESC(edma_rx_napi_budget, "Rx NAPI budget (default:128, min:16, max:512)"); -+ -+int edma_tx_napi_budget = EDMA_TX_NAPI_WORK_DEF; -+module_param(edma_tx_napi_budget, int, 0444); -+MODULE_PARM_DESC(edma_tx_napi_budget, "Tx NAPI budget (default:512 for ipq95xx, min:16, max:512)"); -+ -+int edma_rx_mitigation_pkt_cnt = EDMA_RX_MITIGATION_PKT_CNT_DEF; -+module_param(edma_rx_mitigation_pkt_cnt, int, 0444); -+MODULE_PARM_DESC(edma_rx_mitigation_pkt_cnt, -+ "Rx mitigation packet count value (default:16, min:0, max: 256)"); -+ -+s32 edma_rx_mitigation_timer = EDMA_RX_MITIGATION_TIMER_DEF; -+module_param(edma_rx_mitigation_timer, int, 0444); -+MODULE_PARM_DESC(edma_dp_rx_mitigation_timer, -+ "Rx mitigation timer value in microseconds (default:25, min:0, max: 1000)"); -+ -+int edma_tx_mitigation_timer = EDMA_TX_MITIGATION_TIMER_DEF; -+module_param(edma_tx_mitigation_timer, int, 0444); -+MODULE_PARM_DESC(edma_tx_mitigation_timer, -+ "Tx mitigation timer value in microseconds (default:250, min:0, max: 1000)"); -+ -+int edma_tx_mitigation_pkt_cnt = EDMA_TX_MITIGATION_PKT_CNT_DEF; -+module_param(edma_tx_mitigation_pkt_cnt, int, 0444); -+MODULE_PARM_DESC(edma_tx_mitigation_pkt_cnt, -+ "Tx mitigation packet count value (default:16, min:0, max: 256)"); -+ -+static int tx_requeue_stop; -+module_param(tx_requeue_stop, int, 0640); -+MODULE_PARM_DESC(tx_requeue_stop, "Disable Tx requeue function (default:0)"); -+ - /* Priority to multi-queue mapping. */ - static u8 edma_pri_map[PPE_QUEUE_INTER_PRI_NUM] = { - 0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7}; -@@ -828,7 +860,10 @@ int edma_setup(struct ppe_device *ppe_de - edma_ctx->hw_info = &ipq9574_hw_info; - edma_ctx->ppe_dev = ppe_dev; - edma_ctx->rx_buf_size = rx_buff_size; -+ - edma_ctx->tx_requeue_stop = false; -+ if (tx_requeue_stop != 0) -+ edma_ctx->tx_requeue_stop = true; - - /* Configure the EDMA common clocks. */ - ret = edma_clock_init(); ---- a/drivers/net/ethernet/qualcomm/ppe/edma_cfg_rx.c -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_cfg_rx.c -@@ -166,6 +166,24 @@ static void edma_cfg_rx_desc_ring_config - reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_RING_SIZE(rxdesc_ring->ring_id); - regmap_write(regmap, reg, data); - -+ /* Validate mitigation timer value */ -+ if (edma_rx_mitigation_timer < EDMA_RX_MITIGATION_TIMER_MIN || -+ edma_rx_mitigation_timer > EDMA_RX_MITIGATION_TIMER_MAX) { -+ pr_err("Invalid Rx mitigation timer configured:%d for ring:%d. Using the default timer value:%d\n", -+ edma_rx_mitigation_timer, rxdesc_ring->ring_id, -+ EDMA_RX_MITIGATION_TIMER_DEF); -+ edma_rx_mitigation_timer = EDMA_RX_MITIGATION_TIMER_DEF; -+ } -+ -+ /* Validate mitigation packet count value */ -+ if (edma_rx_mitigation_pkt_cnt < EDMA_RX_MITIGATION_PKT_CNT_MIN || -+ edma_rx_mitigation_pkt_cnt > EDMA_RX_MITIGATION_PKT_CNT_MAX) { -+ pr_err("Invalid Rx mitigation packet count configured:%d for ring:%d. Using the default packet counter value:%d\n", -+ edma_rx_mitigation_timer, rxdesc_ring->ring_id, -+ EDMA_RX_MITIGATION_PKT_CNT_DEF); -+ edma_rx_mitigation_pkt_cnt = EDMA_RX_MITIGATION_PKT_CNT_DEF; -+ } -+ - /* Configure the Mitigation timer */ - data = EDMA_MICROSEC_TO_TIMER_UNIT(EDMA_RX_MITIGATION_TIMER_DEF, - ppe_dev->clk_rate / MHZ); -@@ -176,7 +194,7 @@ static void edma_cfg_rx_desc_ring_config - regmap_write(regmap, reg, data); - - /* Configure the Mitigation packet count */ -- data = (EDMA_RX_MITIGATION_PKT_CNT_DEF & EDMA_RXDESC_LOW_THRE_MASK) -+ data = (edma_rx_mitigation_pkt_cnt & EDMA_RXDESC_LOW_THRE_MASK) - << EDMA_RXDESC_LOW_THRE_SHIFT; - pr_debug("EDMA Rx mitigation packet count value: %d\n", data); - reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_UGT_THRE(rxdesc_ring->ring_id); -@@ -915,6 +933,13 @@ void edma_cfg_rx_napi_add(void) - struct edma_ring_info *rx = hw_info->rx; - u32 i; - -+ if (edma_rx_napi_budget < EDMA_RX_NAPI_WORK_MIN || -+ edma_rx_napi_budget > EDMA_RX_NAPI_WORK_MAX) { -+ pr_err("Incorrect Rx NAPI budget: %d, setting to default: %d", -+ edma_rx_napi_budget, hw_info->napi_budget_rx); -+ edma_rx_napi_budget = hw_info->napi_budget_rx; -+ } -+ - for (i = 0; i < rx->num_rings; i++) { - struct edma_rxdesc_ring *rxdesc_ring = &edma_ctx->rx_rings[i]; - -@@ -923,7 +948,7 @@ void edma_cfg_rx_napi_add(void) - rxdesc_ring->napi_added = true; - } - -- netdev_dbg(edma_ctx->dummy_dev, "Rx NAPI budget: %d\n", hw_info->napi_budget_rx); -+ netdev_dbg(edma_ctx->dummy_dev, "Rx NAPI budget: %d\n", edma_rx_napi_budget); - } - - /** ---- a/drivers/net/ethernet/qualcomm/ppe/edma_cfg_rx.h -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_cfg_rx.h -@@ -5,6 +5,15 @@ - #ifndef __EDMA_CFG_RX__ - #define __EDMA_CFG_RX__ - -+/* Rx default NAPI budget */ -+#define EDMA_RX_NAPI_WORK_DEF 128 -+ -+/* RX minimum NAPI budget */ -+#define EDMA_RX_NAPI_WORK_MIN 16 -+ -+/* Rx maximum NAPI budget */ -+#define EDMA_RX_NAPI_WORK_MAX 512 -+ - /* SKB payload size used in page mode */ - #define EDMA_RX_PAGE_MODE_SKB_SIZE 256 - -@@ -22,9 +31,21 @@ - /* Rx mitigation timer's default value in microseconds */ - #define EDMA_RX_MITIGATION_TIMER_DEF 25 - -+/* Rx mitigation timer's minimum value in microseconds */ -+#define EDMA_RX_MITIGATION_TIMER_MIN 0 -+ -+/* Rx mitigation timer's maximum value in microseconds */ -+#define EDMA_RX_MITIGATION_TIMER_MAX 1000 -+ - /* Rx mitigation packet count's default value */ - #define EDMA_RX_MITIGATION_PKT_CNT_DEF 16 - -+/* Rx mitigation packet count's minimum value */ -+#define EDMA_RX_MITIGATION_PKT_CNT_MIN 0 -+ -+/* Rx mitigation packet count's maximum value */ -+#define EDMA_RX_MITIGATION_PKT_CNT_MAX 256 -+ - /* Default bitmap of cores for RPS to ARM cores */ - #define EDMA_RX_DEFAULT_BITMAP ((1 << EDMA_MAX_CORE) - 1) - ---- a/drivers/net/ethernet/qualcomm/ppe/edma_cfg_tx.c -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_cfg_tx.c -@@ -170,6 +170,24 @@ static void edma_cfg_txcmpl_ring_configu - reg = EDMA_BASE_OFFSET + EDMA_REG_TXCMPL_CTRL(txcmpl_ring->id); - regmap_write(regmap, reg, EDMA_TXCMPL_RETMODE_OPAQUE); - -+ /* Validate mitigation timer value */ -+ if (edma_tx_mitigation_timer < EDMA_TX_MITIGATION_TIMER_MIN || -+ edma_tx_mitigation_timer > EDMA_TX_MITIGATION_TIMER_MAX) { -+ pr_err("Invalid Tx mitigation timer configured:%d for ring:%d. Using the default timer value:%d\n", -+ edma_tx_mitigation_timer, txcmpl_ring->id, -+ EDMA_TX_MITIGATION_TIMER_DEF); -+ edma_tx_mitigation_timer = EDMA_TX_MITIGATION_TIMER_DEF; -+ } -+ -+ /* Validate mitigation packet count value */ -+ if (edma_tx_mitigation_pkt_cnt < EDMA_TX_MITIGATION_PKT_CNT_MIN || -+ edma_tx_mitigation_pkt_cnt > EDMA_TX_MITIGATION_PKT_CNT_MAX) { -+ pr_err("Invalid Tx mitigation packet count configured:%d for ring:%d. Using the default packet counter value:%d\n", -+ edma_tx_mitigation_timer, txcmpl_ring->id, -+ EDMA_TX_MITIGATION_PKT_CNT_DEF); -+ edma_tx_mitigation_pkt_cnt = EDMA_TX_MITIGATION_PKT_CNT_DEF; -+ } -+ - /* Configure the Mitigation timer. */ - data = EDMA_MICROSEC_TO_TIMER_UNIT(EDMA_TX_MITIGATION_TIMER_DEF, - ppe_dev->clk_rate / MHZ); -@@ -180,7 +198,7 @@ static void edma_cfg_txcmpl_ring_configu - regmap_write(regmap, reg, data); - - /* Configure the Mitigation packet count. */ -- data = (EDMA_TX_MITIGATION_PKT_CNT_DEF & EDMA_TXCMPL_LOW_THRE_MASK) -+ data = (edma_tx_mitigation_pkt_cnt & EDMA_TXCMPL_LOW_THRE_MASK) - << EDMA_TXCMPL_LOW_THRE_SHIFT; - pr_debug("EDMA Tx mitigation packet count value: %d\n", data); - reg = EDMA_BASE_OFFSET + EDMA_REG_TXCMPL_UGT_THRE(txcmpl_ring->id); -@@ -634,6 +652,13 @@ void edma_cfg_tx_napi_add(struct net_dev - struct edma_txcmpl_ring *txcmpl_ring; - u32 i, ring_idx; - -+ if (edma_tx_napi_budget < EDMA_TX_NAPI_WORK_MIN || -+ edma_tx_napi_budget > EDMA_TX_NAPI_WORK_MAX) { -+ pr_err("Incorrect Tx NAPI budget: %d, setting to default: %d", -+ edma_tx_napi_budget, hw_info->napi_budget_tx); -+ edma_tx_napi_budget = hw_info->napi_budget_tx; -+ } -+ - /* Adding tx napi for a interface with each queue. */ - for_each_possible_cpu(i) { - ring_idx = ((port_id - 1) * num_possible_cpus()) + i; -@@ -644,5 +669,5 @@ void edma_cfg_tx_napi_add(struct net_dev - netdev_dbg(netdev, "Napi added for txcmpl ring: %u\n", txcmpl_ring->id); - } - -- netdev_dbg(netdev, "Tx NAPI budget: %d\n", hw_info->napi_budget_tx); -+ netdev_dbg(netdev, "Tx NAPI budget: %d\n", edma_tx_napi_budget); - } ---- a/drivers/net/ethernet/qualcomm/ppe/edma_cfg_tx.h -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_cfg_tx.h -@@ -5,12 +5,28 @@ - #ifndef __EDMA_CFG_TX__ - #define __EDMA_CFG_TX__ - -+#define EDMA_TX_NAPI_WORK_DEF 512 -+#define EDMA_TX_NAPI_WORK_MIN 16 -+#define EDMA_TX_NAPI_WORK_MAX 512 -+ - /* Tx mitigation timer's default value. */ - #define EDMA_TX_MITIGATION_TIMER_DEF 250 - -+/* Tx mitigation timer's minimum value in microseconds */ -+#define EDMA_TX_MITIGATION_TIMER_MIN 0 -+ -+/* Tx mitigation timer's maximum value in microseconds */ -+#define EDMA_TX_MITIGATION_TIMER_MAX 1000 -+ - /* Tx mitigation packet count default value. */ - #define EDMA_TX_MITIGATION_PKT_CNT_DEF 16 - -+/* Tx mitigation packet count's minimum value */ -+#define EDMA_TX_MITIGATION_PKT_CNT_MIN 0 -+ -+/* Tx mitigation packet count's maximum value */ -+#define EDMA_TX_MITIGATION_PKT_CNT_MAX 256 -+ - void edma_cfg_tx_rings(void); - int edma_cfg_tx_rings_alloc(void); - void edma_cfg_tx_rings_cleanup(void); ---- a/drivers/net/ethernet/qualcomm/ppe/edma_rx.h -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_rx.h -@@ -281,6 +281,10 @@ struct edma_rxdesc_ring { - struct sk_buff *last; - }; - -+extern int edma_rx_napi_budget; -+extern int edma_rx_mitigation_timer; -+extern int edma_rx_mitigation_pkt_cnt; -+ - irqreturn_t edma_rx_handle_irq(int irq, void *ctx); - int edma_rx_alloc_buffer(struct edma_rxfill_ring *rxfill_ring, int alloc_count); - int edma_rx_napi_poll(struct napi_struct *napi, int budget); ---- a/drivers/net/ethernet/qualcomm/ppe/edma_tx.h -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_tx.h -@@ -288,6 +288,10 @@ struct edma_txcmpl_ring { - bool napi_added; - }; - -+extern int edma_tx_napi_budget; -+extern int edma_tx_mitigation_timer; -+extern int edma_tx_mitigation_pkt_cnt; -+ - enum edma_tx_status edma_tx_ring_xmit(struct net_device *netdev, - struct sk_buff *skb, - struct edma_txdesc_ring *txdesc_ring, diff --git a/target/linux/qualcommbe/patches-6.12/0349-net-ethernet-qualcomm-Add-sysctl-for-RPS-bitmap.patch b/target/linux/qualcommbe/patches-6.12/0349-net-ethernet-qualcomm-Add-sysctl-for-RPS-bitmap.patch deleted file mode 100644 index c6970015d7..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0349-net-ethernet-qualcomm-Add-sysctl-for-RPS-bitmap.patch +++ /dev/null @@ -1,145 +0,0 @@ -From dcac735a715c13a817d65ae371564cf2793330b2 Mon Sep 17 00:00:00 2001 -From: Pavithra R -Date: Tue, 11 Jun 2024 01:43:22 +0530 -Subject: [PATCH] net: ethernet: qualcomm: Add sysctl for RPS bitmap - -Add sysctl to configure RPS bitmap for EDMA receive. -This bitmap is used to configure the set of ARM cores -used to receive packets from EDMA. - -Change-Id: Ie0e7d5971db93ea1494608a9e79c4abb13ce69b6 -Signed-off-by: Pavithra R -Alex G: Use **const** ctl_table argument for .proc_handler -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/ethernet/qualcomm/ppe/edma.c | 23 ++++++++++++++++ - drivers/net/ethernet/qualcomm/ppe/edma.h | 2 ++ - .../net/ethernet/qualcomm/ppe/edma_cfg_rx.c | 27 +++++++++++++++++++ - .../net/ethernet/qualcomm/ppe/edma_cfg_rx.h | 6 ++++- - 4 files changed, 57 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/qualcomm/ppe/edma.c -+++ b/drivers/net/ethernet/qualcomm/ppe/edma.c -@@ -797,6 +797,11 @@ void edma_destroy(struct ppe_device *ppe - struct edma_ring_info *rx = hw_info->rx; - u32 i; - -+ if (edma_ctx->rx_rps_ctl_table_hdr) { -+ unregister_sysctl_table(edma_ctx->rx_rps_ctl_table_hdr); -+ edma_ctx->rx_rps_ctl_table_hdr = NULL; -+ } -+ - /* Disable interrupts. */ - for (i = 1; i <= hw_info->max_ports; i++) - edma_cfg_tx_disable_interrupts(i); -@@ -840,6 +845,17 @@ void edma_destroy(struct ppe_device *ppe - kfree(edma_ctx->netdev_arr); - } - -+/* EDMA Rx RPS core sysctl table */ -+static struct ctl_table edma_rx_rps_core_table[] = { -+ { -+ .procname = "rps_bitmap_cores", -+ .data = &edma_cfg_rx_rps_bitmap_cores, -+ .maxlen = sizeof(int), -+ .mode = 0644, -+ .proc_handler = edma_cfg_rx_rps_bitmap -+ }, -+}; -+ - /** - * edma_setup - EDMA Setup. - * @ppe_dev: PPE device -@@ -865,6 +881,13 @@ int edma_setup(struct ppe_device *ppe_de - if (tx_requeue_stop != 0) - edma_ctx->tx_requeue_stop = true; - -+ edma_ctx->rx_rps_ctl_table_hdr = register_sysctl("net/edma", -+ edma_rx_rps_core_table); -+ if (!edma_ctx->rx_rps_ctl_table_hdr) { -+ pr_err("Rx rps sysctl table configuration failed\n"); -+ return -EINVAL; -+ } -+ - /* Configure the EDMA common clocks. */ - ret = edma_clock_init(); - if (ret) { ---- a/drivers/net/ethernet/qualcomm/ppe/edma.h -+++ b/drivers/net/ethernet/qualcomm/ppe/edma.h -@@ -132,6 +132,7 @@ struct edma_intr_info { - * @tx_rings: Tx Descriptor Ring, SW is producer - * @txcmpl_rings: Tx complete Ring, SW is consumer - * @err_stats: Per CPU error statistics -+ * @rx_rps_ctl_table_hdr: Rx RPS sysctl table - * @rx_page_mode: Page mode enabled or disabled - * @rx_buf_size: Rx buffer size for Jumbo MRU - * @tx_requeue_stop: Tx requeue stop enabled or disabled -@@ -147,6 +148,7 @@ struct edma_context { - struct edma_txdesc_ring *tx_rings; - struct edma_txcmpl_ring *txcmpl_rings; - struct edma_err_stats __percpu *err_stats; -+ struct ctl_table_header *rx_rps_ctl_table_hdr; - u32 rx_page_mode; - u32 rx_buf_size; - bool tx_requeue_stop; ---- a/drivers/net/ethernet/qualcomm/ppe/edma_cfg_rx.c -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_cfg_rx.c -@@ -43,6 +43,8 @@ static u32 edma_rx_ring_queue_map[][EDMA - { 6, 14, 22, 30 }, - { 7, 15, 23, 31 }}; - -+u32 edma_cfg_rx_rps_bitmap_cores = EDMA_RX_DEFAULT_BITMAP; -+ - static int edma_cfg_rx_desc_rings_reset_queue_mapping(void) - { - struct edma_hw_info *hw_info = edma_ctx->hw_info; -@@ -987,3 +989,28 @@ int edma_cfg_rx_rps_hash_map(void) - - return 0; - } -+ -+/* Configure RPS hash mapping based on bitmap */ -+int edma_cfg_rx_rps_bitmap(const struct ctl_table *table, int write, -+ void *buffer, size_t *lenp, loff_t *ppos) -+{ -+ int ret; -+ -+ ret = proc_dointvec(table, write, buffer, lenp, ppos); -+ -+ if (!write) -+ return ret; -+ -+ if (!edma_cfg_rx_rps_bitmap_cores || -+ edma_cfg_rx_rps_bitmap_cores > EDMA_RX_DEFAULT_BITMAP) { -+ pr_warn("Incorrect CPU bitmap: %x. Setting it to default value: %d", -+ edma_cfg_rx_rps_bitmap_cores, EDMA_RX_DEFAULT_BITMAP); -+ edma_cfg_rx_rps_bitmap_cores = EDMA_RX_DEFAULT_BITMAP; -+ } -+ -+ ret = edma_cfg_rx_rps_hash_map(); -+ -+ pr_info("EDMA RPS bitmap value: %d\n", edma_cfg_rx_rps_bitmap_cores); -+ -+ return ret; -+} ---- a/drivers/net/ethernet/qualcomm/ppe/edma_cfg_rx.h -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_cfg_rx.h -@@ -49,6 +49,8 @@ - /* Default bitmap of cores for RPS to ARM cores */ - #define EDMA_RX_DEFAULT_BITMAP ((1 << EDMA_MAX_CORE) - 1) - -+extern u32 edma_cfg_rx_rps_bitmap_cores; -+ - int edma_cfg_rx_rings(void); - int edma_cfg_rx_rings_alloc(void); - void edma_cfg_rx_ring_mappings(void); -@@ -64,6 +66,8 @@ void edma_cfg_rx_rings_enable(void); - void edma_cfg_rx_rings_disable(void); - void edma_cfg_rx_buff_size_setup(void); - int edma_cfg_rx_rps_hash_map(void); --int edma_cfg_rx_rps(struct ctl_table *table, int write, -+int edma_cfg_rx_rps(const struct ctl_table *table, int write, - void *buffer, size_t *lenp, loff_t *ppos); -+int edma_cfg_rx_rps_bitmap(const struct ctl_table *table, int write, -+ void *buffer, size_t *lenp, loff_t *ppos); - #endif diff --git a/target/linux/qualcommbe/patches-6.12/0350-net-ethernet-qualcomm-Add-support-for-label-property.patch b/target/linux/qualcommbe/patches-6.12/0350-net-ethernet-qualcomm-Add-support-for-label-property.patch deleted file mode 100644 index 79af169c8e..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0350-net-ethernet-qualcomm-Add-support-for-label-property.patch +++ /dev/null @@ -1,48 +0,0 @@ -From a809433c9b6a418dd886f12a5dcb3376f73bf2a7 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Wed, 4 Dec 2024 01:37:05 +0100 -Subject: [PATCH] net: ethernet: qualcomm: Add support for label property for - EDMA port - -Add support for label property for EDMA port. This is useful to define -custom name in DTS for specific ethernet port instead of assigning a -dynamic name at runtime. - -This also improve the log output by using modern APIs. - -Signed-off-by: Christian Marangi ---- - drivers/net/ethernet/qualcomm/ppe/edma_port.c | 18 +++++++++++++++--- - 1 file changed, 15 insertions(+), 3 deletions(-) - ---- a/drivers/net/ethernet/qualcomm/ppe/edma_port.c -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_port.c -@@ -355,13 +355,25 @@ int edma_port_setup(struct ppe_port *por - int port_id = port->port_id; - struct net_device *netdev; - u8 mac_addr[ETH_ALEN]; -+ const char *name; -+ int assign_type; - int ret = 0; - u8 *maddr; - -- netdev = alloc_etherdev_mqs(sizeof(struct edma_port_priv), -- EDMA_NETDEV_QUEUE_NUM, EDMA_NETDEV_QUEUE_NUM); -+ name = of_get_property(np, "label", NULL); -+ if (name) { -+ assign_type = NET_NAME_PREDICTABLE; -+ } else { -+ name = "eth%d"; -+ assign_type = NET_NAME_ENUM; -+ } -+ -+ netdev = alloc_netdev_mqs(sizeof(struct edma_port_priv), -+ name, assign_type, -+ ether_setup, -+ EDMA_NETDEV_QUEUE_NUM, EDMA_NETDEV_QUEUE_NUM); - if (!netdev) { -- pr_err("alloc_etherdev() failed\n"); -+ dev_err(ppe_dev->dev, "alloc_netdev_mqs() failed\n"); - return -ENOMEM; - } - diff --git a/target/linux/qualcommbe/patches-6.12/0351-net-ethernet-qualcomm-ppe-Fix-unmet-dependency-with-.patch b/target/linux/qualcommbe/patches-6.12/0351-net-ethernet-qualcomm-ppe-Fix-unmet-dependency-with-.patch deleted file mode 100644 index a0d15cf2a0..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0351-net-ethernet-qualcomm-ppe-Fix-unmet-dependency-with-.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 9c4ad75f17788a64c1e37d0b9e19ca157e01c80a Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 9 Dec 2024 18:19:06 +0100 -Subject: [PATCH] net: ethernet: qualcomm: ppe: Fix unmet dependency with - QCOM_PPE - -Fix unmet dependency with QCOM_PPE on selecting SFP. - -WARNING: unmet direct dependencies detected for SFP - Depends on [m]: NETDEVICES [=y] && PHYLIB [=y] && I2C [=y] && PHYLINK [=y] && (HWMON [=m] || HWMON [=m]=n [=n]) - Selected by [y]: - - QCOM_PPE [=y] && NETDEVICES [=y] && ETHERNET [=y] && NET_VENDOR_QUALCOMM [=y] && HAS_IOMEM [=y] && OF [=y] && COMMON_CLK [=y] - -This permit correct compilation of the modules with SFP enabled. - -Signed-off-by: Christian Marangi ---- - drivers/net/ethernet/qualcomm/Kconfig | 1 - - 1 file changed, 1 deletion(-) - ---- a/drivers/net/ethernet/qualcomm/Kconfig -+++ b/drivers/net/ethernet/qualcomm/Kconfig -@@ -68,7 +68,6 @@ config QCOM_PPE - select REGMAP_MMIO - select PHYLINK - select PCS_QCOM_IPQ_UNIPHY -- select SFP - help - This driver supports the Qualcomm Technologies, Inc. packet - process engine (PPE) available with IPQ SoC. The PPE includes diff --git a/target/linux/qualcommbe/patches-6.12/0352-net-ethernet-qualcomm-ppe-select-correct-PCS-depende.patch b/target/linux/qualcommbe/patches-6.12/0352-net-ethernet-qualcomm-ppe-select-correct-PCS-depende.patch deleted file mode 100644 index 3893c5cd8d..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0352-net-ethernet-qualcomm-ppe-select-correct-PCS-depende.patch +++ /dev/null @@ -1,24 +0,0 @@ -From ac41b401d274a4004027fa4000d801cd28c51f4c Mon Sep 17 00:00:00 2001 -From: Alexandru Gagniuc -Date: Tue, 13 May 2025 13:41:37 -0500 -Subject: [PATCH] net: ethernet: qualcomm: ppe: select correct PCS dependency - -The config symbol for the PCS driver has changed to PCS_QCOM_IPQ9574, -since the original submission. Update Kconfig accordingly. - -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/ethernet/qualcomm/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/ethernet/qualcomm/Kconfig -+++ b/drivers/net/ethernet/qualcomm/Kconfig -@@ -67,7 +67,7 @@ config QCOM_PPE - depends on COMMON_CLK - select REGMAP_MMIO - select PHYLINK -- select PCS_QCOM_IPQ_UNIPHY -+ select PCS_QCOM_IPQ9574 - help - This driver supports the Qualcomm Technologies, Inc. packet - process engine (PPE) available with IPQ SoC. The PPE includes diff --git a/target/linux/qualcommbe/patches-6.12/0353-arm64-dts-qcom-Add-IPQ9574-PPE-base-device-node.patch b/target/linux/qualcommbe/patches-6.12/0353-arm64-dts-qcom-Add-IPQ9574-PPE-base-device-node.patch deleted file mode 100644 index 640a2a9f02..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0353-arm64-dts-qcom-Add-IPQ9574-PPE-base-device-node.patch +++ /dev/null @@ -1,72 +0,0 @@ -From bbf706ecfd4295d73c8217d5220573dd51d7a081 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Fri, 1 Mar 2024 14:46:45 +0800 -Subject: [PATCH] arm64: dts: qcom: Add IPQ9574 PPE base device node - -PPE is the packet process engine on the Qualcomm IPQ platform, -which is connected with the external switch or PHY device via -the UNIPHY (PCS). - -Change-Id: I254bd48c218aa4eab54f697a2ad149f5a93b682c -Signed-off-by: Luo Jie -Alex G: Add "qcom_ppe" label to PPE node -Signed-off-by: Alexandru Gagniuc ---- - arch/arm64/boot/dts/qcom/ipq9574.dtsi | 39 +++++++++++++++++++++++++++ - 1 file changed, 39 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - #include - - / { -@@ -1271,6 +1272,44 @@ - #interconnect-cells = <1>; - }; - -+ qcom_ppe: ethernet@3a000000 { -+ compatible = "qcom,ipq9574-ppe"; -+ reg = <0x3a000000 0xbef800>; -+ ranges; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ clocks = <&nsscc NSS_CC_PPE_SWITCH_CLK>, -+ <&nsscc NSS_CC_PPE_SWITCH_CFG_CLK>, -+ <&nsscc NSS_CC_PPE_SWITCH_IPE_CLK>, -+ <&nsscc NSS_CC_PPE_SWITCH_BTQ_CLK>; -+ clock-names = "ppe", -+ "ppe_cfg", -+ "ppe_ipe", -+ "ppe_btq"; -+ resets = <&nsscc PPE_FULL_RESET>; -+ interconnects = <&nsscc MASTER_NSSNOC_PPE -+ &nsscc SLAVE_NSSNOC_PPE>, -+ <&nsscc MASTER_NSSNOC_PPE_CFG -+ &nsscc SLAVE_NSSNOC_PPE_CFG>, -+ <&gcc MASTER_NSSNOC_QOSGEN_REF -+ &gcc SLAVE_NSSNOC_QOSGEN_REF>, -+ <&gcc MASTER_NSSNOC_TIMEOUT_REF -+ &gcc SLAVE_NSSNOC_TIMEOUT_REF>, -+ <&gcc MASTER_MEM_NOC_NSSNOC -+ &gcc SLAVE_MEM_NOC_NSSNOC>, -+ <&gcc MASTER_NSSNOC_MEMNOC -+ &gcc SLAVE_NSSNOC_MEMNOC>, -+ <&gcc MASTER_NSSNOC_MEM_NOC_1 -+ &gcc SLAVE_NSSNOC_MEM_NOC_1>; -+ interconnect-names = "ppe", -+ "ppe_cfg", -+ "qos_gen", -+ "timeout_ref", -+ "nssnoc_memnoc", -+ "memnoc_nssnoc", -+ "memnoc_nssnoc_1"; -+ }; -+ - pcs0: ethernet-pcs@7a00000 { - compatible = "qcom,ipq9574-pcs"; - reg = <0x7a00000 0x10000>; diff --git a/target/linux/qualcommbe/patches-6.12/0354-arm64-dts-qcom-Add-EDMA-node-for-IPQ9574.patch b/target/linux/qualcommbe/patches-6.12/0354-arm64-dts-qcom-Add-EDMA-node-for-IPQ9574.patch deleted file mode 100644 index f93ed0c37e..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0354-arm64-dts-qcom-Add-EDMA-node-for-IPQ9574.patch +++ /dev/null @@ -1,91 +0,0 @@ -From bd50babc7db2a35d98236a0386173dccd6c6374b Mon Sep 17 00:00:00 2001 -From: Pavithra R -Date: Wed, 6 Mar 2024 22:29:41 +0530 -Subject: [PATCH] arm64: dts: qcom: Add EDMA node for IPQ9574 - -Add EDMA (Ethernet DMA) device tree node for IPQ9574 to -enable ethernet support. - -Change-Id: I87d7c50f2485c8670948dce305000337f6499f8b -Signed-off-by: Pavithra R ---- - arch/arm64/boot/dts/qcom/ipq9574.dtsi | 68 +++++++++++++++++++++++++++ - 1 file changed, 68 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi -@@ -1308,6 +1308,74 @@ - "nssnoc_memnoc", - "memnoc_nssnoc", - "memnoc_nssnoc_1"; -+ -+ edma { -+ compatible = "qcom,ipq9574-edma"; -+ clocks = <&nsscc NSS_CC_PPE_EDMA_CLK>, -+ <&nsscc NSS_CC_PPE_EDMA_CFG_CLK>; -+ clock-names = "edma", -+ "edma-cfg"; -+ resets = <&nsscc EDMA_HW_RESET>; -+ reset-names = "edma_rst"; -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ ; -+ interrupt-names = "edma_txcmpl_8", -+ "edma_txcmpl_9", -+ "edma_txcmpl_10", -+ "edma_txcmpl_11", -+ "edma_txcmpl_12", -+ "edma_txcmpl_13", -+ "edma_txcmpl_14", -+ "edma_txcmpl_15", -+ "edma_txcmpl_16", -+ "edma_txcmpl_17", -+ "edma_txcmpl_18", -+ "edma_txcmpl_19", -+ "edma_txcmpl_20", -+ "edma_txcmpl_21", -+ "edma_txcmpl_22", -+ "edma_txcmpl_23", -+ "edma_txcmpl_24", -+ "edma_txcmpl_25", -+ "edma_txcmpl_26", -+ "edma_txcmpl_27", -+ "edma_txcmpl_28", -+ "edma_txcmpl_29", -+ "edma_txcmpl_30", -+ "edma_txcmpl_31", -+ "edma_rxdesc_20", -+ "edma_rxdesc_21", -+ "edma_rxdesc_22", -+ "edma_rxdesc_23", -+ "edma_misc"; -+ }; - }; - - pcs0: ethernet-pcs@7a00000 { diff --git a/target/linux/qualcommbe/patches-6.12/0355-arm64-dts-qcom-Add-IPQ9574-RDP433-port-node.patch b/target/linux/qualcommbe/patches-6.12/0355-arm64-dts-qcom-Add-IPQ9574-RDP433-port-node.patch deleted file mode 100644 index 83f0e24117..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0355-arm64-dts-qcom-Add-IPQ9574-RDP433-port-node.patch +++ /dev/null @@ -1,197 +0,0 @@ -From 001b663ecc5f838dac143623badae0e472749d8a Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Tue, 14 May 2024 10:53:27 +0800 -Subject: [PATCH] arm64: dts: qcom: Add IPQ9574 RDP433 port node - -There are 6 PPE MAC ports available on RDP433. The port1-port4 are -connected with QCA8075 QUAD PHYs through UNIPHY0 PCS channel0-channel3. -The port5 is connected with Aquantia PHY through UNIPHY1 PCS channel0 -and the port6 is connected with Aquantia PHY through UNIPHY2 PCS -channel0. - -Change-Id: Ic16efdef2fe2cff7b1e80245619c0f82afb24cb9 -Signed-off-by: Lei Wei ---- - arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts | 167 ++++++++++++++++++++ - 1 file changed, 167 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts -+++ b/arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts -@@ -55,6 +55,46 @@ - status = "okay"; - }; - -+&mdio { -+ reset-gpios = <&tlmm 60 GPIO_ACTIVE_LOW>; -+ clock-frequency = <6250000>; -+ status = "okay"; -+ -+ ethernet-phy-package@0 { -+ compatible = "qcom,qca8075-package"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0x10>; -+ qcom,package-mode = "qsgmii"; -+ -+ phy0: ethernet-phy@10 { -+ reg = <0x10>; -+ }; -+ -+ phy1: ethernet-phy@11 { -+ reg = <0x11>; -+ }; -+ -+ phy2: ethernet-phy@12 { -+ reg = <0x12>; -+ }; -+ -+ phy3: ethernet-phy@13 { -+ reg = <0x13>; -+ }; -+ }; -+ -+ phy4: ethernet-phy@8 { -+ compatible ="ethernet-phy-ieee802.3-c45"; -+ reg = <8>; -+ }; -+ -+ phy5: ethernet-phy@0 { -+ compatible ="ethernet-phy-ieee802.3-c45"; -+ reg = <0>; -+ }; -+}; -+ - &tlmm { - - pcie1_default: pcie1-default-state { -@@ -161,3 +201,130 @@ - }; - }; - }; -+ -+&qcom_ppe { -+ ethernet-ports { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ port@1 { -+ reg = <1>; -+ phy-mode = "qsgmii"; -+ managed = "in-band-status"; -+ phy-handle = <&phy0>; -+ pcs-handle = <&pcs0_ch0>; -+ clocks = <&nsscc NSS_CC_PORT1_MAC_CLK>, -+ <&nsscc NSS_CC_PORT1_RX_CLK>, -+ <&nsscc NSS_CC_PORT1_TX_CLK>; -+ clock-names = "mac", -+ "rx", -+ "tx"; -+ resets = <&nsscc PORT1_MAC_ARES>, -+ <&nsscc PORT1_RX_ARES>, -+ <&nsscc PORT1_TX_ARES>; -+ reset-names = "mac", -+ "rx", -+ "tx"; -+ }; -+ -+ port@2 { -+ reg = <2>; -+ phy-mode = "qsgmii"; -+ managed = "in-band-status"; -+ phy-handle = <&phy1>; -+ pcs-handle = <&pcs0_ch1>; -+ clocks = <&nsscc NSS_CC_PORT2_MAC_CLK>, -+ <&nsscc NSS_CC_PORT2_RX_CLK>, -+ <&nsscc NSS_CC_PORT2_TX_CLK>; -+ clock-names = "mac", -+ "rx", -+ "tx"; -+ resets = <&nsscc PORT2_MAC_ARES>, -+ <&nsscc PORT2_RX_ARES>, -+ <&nsscc PORT2_TX_ARES>; -+ reset-names = "mac", -+ "rx", -+ "tx"; -+ }; -+ -+ port@3 { -+ reg = <3>; -+ phy-mode = "qsgmii"; -+ managed = "in-band-status"; -+ phy-handle = <&phy2>; -+ pcs-handle = <&pcs0_ch2>; -+ clocks = <&nsscc NSS_CC_PORT3_MAC_CLK>, -+ <&nsscc NSS_CC_PORT3_RX_CLK>, -+ <&nsscc NSS_CC_PORT3_TX_CLK>; -+ clock-names = "mac", -+ "rx", -+ "tx"; -+ resets = <&nsscc PORT3_MAC_ARES>, -+ <&nsscc PORT3_RX_ARES>, -+ <&nsscc PORT3_TX_ARES>; -+ reset-names = "mac", -+ "rx", -+ "tx"; -+ }; -+ -+ port@4 { -+ reg = <4>; -+ phy-mode = "qsgmii"; -+ managed = "in-band-status"; -+ phy-handle = <&phy3>; -+ pcs-handle = <&pcs0_ch3>; -+ clocks = <&nsscc NSS_CC_PORT4_MAC_CLK>, -+ <&nsscc NSS_CC_PORT4_RX_CLK>, -+ <&nsscc NSS_CC_PORT4_TX_CLK>; -+ clock-names = "mac", -+ "rx", -+ "tx"; -+ resets = <&nsscc PORT4_MAC_ARES>, -+ <&nsscc PORT4_RX_ARES>, -+ <&nsscc PORT4_TX_ARES>; -+ reset-names = "mac", -+ "rx", -+ "tx"; -+ }; -+ -+ port@5 { -+ reg = <5>; -+ phy-mode = "usxgmii"; -+ managed = "in-band-status"; -+ phy-handle = <&phy4>; -+ pcs-handle = <&pcs1_ch0>; -+ clocks = <&nsscc NSS_CC_PORT5_MAC_CLK>, -+ <&nsscc NSS_CC_PORT5_RX_CLK>, -+ <&nsscc NSS_CC_PORT5_TX_CLK>; -+ clock-names = "mac", -+ "rx", -+ "tx"; -+ resets = <&nsscc PORT5_MAC_ARES>, -+ <&nsscc PORT5_RX_ARES>, -+ <&nsscc PORT5_TX_ARES>; -+ reset-names = "mac", -+ "rx", -+ "tx"; -+ }; -+ -+ port@6 { -+ reg = <6>; -+ phy-mode = "usxgmii"; -+ managed = "in-band-status"; -+ phy-handle = <&phy5>; -+ pcs-handle = <&pcs2_ch0>; -+ clocks = <&nsscc NSS_CC_PORT6_MAC_CLK>, -+ <&nsscc NSS_CC_PORT6_RX_CLK>, -+ <&nsscc NSS_CC_PORT6_TX_CLK>; -+ clock-names = "mac", -+ "rx", -+ "tx"; -+ resets = <&nsscc PORT6_MAC_ARES>, -+ <&nsscc PORT6_RX_ARES>, -+ <&nsscc PORT6_TX_ARES>; -+ reset-names = "mac", -+ "rx", -+ "tx"; -+ }; -+ }; -+}; diff --git a/target/linux/qualcommbe/patches-6.12/0356-arm64-dts-qcom-add-AQR-NVMEM-node-for-IPQ9574-RDP433.patch b/target/linux/qualcommbe/patches-6.12/0356-arm64-dts-qcom-add-AQR-NVMEM-node-for-IPQ9574-RDP433.patch deleted file mode 100644 index e508bad9a6..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0356-arm64-dts-qcom-add-AQR-NVMEM-node-for-IPQ9574-RDP433.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 30b751f5984e295f0b5e7a2308b6103fae3322d2 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 9 Dec 2024 18:10:43 +0100 -Subject: [PATCH] arm64: dts: qcom: add AQR NVMEM node for IPQ9574 RDP433 board - -Add Aquantia NVMEM node for IPQ9574 RDP433 board to load the firmware -for the Aquantia PHY. - -Signed-off-by: Christian Marangi ---- - arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts | 6 ++++++ - 1 file changed, 6 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts -+++ b/arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts -@@ -87,11 +87,17 @@ - phy4: ethernet-phy@8 { - compatible ="ethernet-phy-ieee802.3-c45"; - reg = <8>; -+ -+ nvmem-cells = <&aqr_fw>; -+ nvmem-cell-names = "firmware"; - }; - - phy5: ethernet-phy@0 { - compatible ="ethernet-phy-ieee802.3-c45"; - reg = <0>; -+ -+ nvmem-cells = <&aqr_fw>; -+ nvmem-cell-names = "firmware"; - }; - }; - diff --git a/target/linux/qualcommbe/patches-6.12/0357-arm64-dts-qcom-Add-label-to-EDMA-port-for-IPQ9574-RD.patch b/target/linux/qualcommbe/patches-6.12/0357-arm64-dts-qcom-Add-label-to-EDMA-port-for-IPQ9574-RD.patch deleted file mode 100644 index 950c9faf3c..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0357-arm64-dts-qcom-Add-label-to-EDMA-port-for-IPQ9574-RD.patch +++ /dev/null @@ -1,62 +0,0 @@ -From b297d12d434191845cf8ae359466dcd8312ed21d Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Wed, 4 Dec 2024 01:49:09 +0100 -Subject: [PATCH] arm64: dts: qcom: Add label to EDMA port for IPQ9574 RDP433 - -Add label to EDMA port for IPQ9574 RDP433 board. - -Signed-off-by: Christian Marangi ---- - arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts | 6 ++++++ - 1 file changed, 6 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts -+++ b/arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts -@@ -217,6 +217,7 @@ - reg = <1>; - phy-mode = "qsgmii"; - managed = "in-band-status"; -+ label = "lan1"; - phy-handle = <&phy0>; - pcs-handle = <&pcs0_ch0>; - clocks = <&nsscc NSS_CC_PORT1_MAC_CLK>, -@@ -237,6 +238,7 @@ - reg = <2>; - phy-mode = "qsgmii"; - managed = "in-band-status"; -+ label = "lan2"; - phy-handle = <&phy1>; - pcs-handle = <&pcs0_ch1>; - clocks = <&nsscc NSS_CC_PORT2_MAC_CLK>, -@@ -257,6 +259,7 @@ - reg = <3>; - phy-mode = "qsgmii"; - managed = "in-band-status"; -+ label = "lan3"; - phy-handle = <&phy2>; - pcs-handle = <&pcs0_ch2>; - clocks = <&nsscc NSS_CC_PORT3_MAC_CLK>, -@@ -277,6 +280,7 @@ - reg = <4>; - phy-mode = "qsgmii"; - managed = "in-band-status"; -+ label = "lan4"; - phy-handle = <&phy3>; - pcs-handle = <&pcs0_ch3>; - clocks = <&nsscc NSS_CC_PORT4_MAC_CLK>, -@@ -297,6 +301,7 @@ - reg = <5>; - phy-mode = "usxgmii"; - managed = "in-band-status"; -+ label = "lan5"; - phy-handle = <&phy4>; - pcs-handle = <&pcs1_ch0>; - clocks = <&nsscc NSS_CC_PORT5_MAC_CLK>, -@@ -317,6 +322,7 @@ - reg = <6>; - phy-mode = "usxgmii"; - managed = "in-band-status"; -+ label = "wan"; - phy-handle = <&phy5>; - pcs-handle = <&pcs2_ch0>; - clocks = <&nsscc NSS_CC_PORT6_MAC_CLK>, diff --git a/target/linux/qualcommbe/patches-6.12/0358-clk-qcom-nsscc-Attach-required-NSSNOC-clock-to-PM-do.patch b/target/linux/qualcommbe/patches-6.12/0358-clk-qcom-nsscc-Attach-required-NSSNOC-clock-to-PM-do.patch deleted file mode 100644 index 372572a24e..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0358-clk-qcom-nsscc-Attach-required-NSSNOC-clock-to-PM-do.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 6417cb20e854194a845d4ab092b92fd753c0e405 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Thu, 30 Jan 2025 16:11:14 +0100 -Subject: [PATCH] clk: qcom: nsscc: Attach required NSSNOC clock to PM domain - -There is currently a problem with ICC clock disabling the NSSNOC clock -as there isn't any user for them on calling sync_state. -This cause the kernel to stall if NSS is enabled and reboot with the watchdog. - -This is caused by the fact that the NSSNOC clock nsscc, snoc and snoc_1 -are actually required to make the NSS work and make the system continue -booting. - -To attach these clock, setup pm-clk in nsscc and setup the correct -resume/suspend OPs. - -With this change, the clock gets correctly attached and are not disabled -when ICC call the sync_state. - -Suggested-by: Dmitry Baryshkov -Signed-off-by: Christian Marangi -Alex G: Retrieve clocks by name rather than index. -Signed-off-by: Alexandru Gagniuc ---- - drivers/clk/qcom/nsscc-ipq9574.c | 21 +++++++++++++++++++++ - 1 file changed, 21 insertions(+) - ---- a/drivers/clk/qcom/nsscc-ipq9574.c -+++ b/drivers/clk/qcom/nsscc-ipq9574.c -@@ -3060,6 +3060,7 @@ MODULE_DEVICE_TABLE(of, nss_cc_ipq9574_m - - static int nss_cc_ipq9574_probe(struct platform_device *pdev) - { -+ struct device *dev = &pdev->dev; - struct regmap *regmap; - int ret; - -@@ -3075,6 +3076,18 @@ static int nss_cc_ipq9574_probe(struct p - if (ret) - return dev_err_probe(&pdev->dev, ret, "Fail to add bus clock\n"); - -+ ret = pm_clk_add(&pdev->dev, "nssnoc"); -+ if (ret) -+ return dev_err_probe(dev, ret,"failed to acquire nssnoc clock\n"); -+ -+ ret = pm_clk_add(&pdev->dev, "snoc"); -+ if (ret) -+ return dev_err_probe(dev, ret,"failed to acquire snoc clock\n"); -+ -+ ret = pm_clk_add(&pdev->dev, "snoc_1"); -+ if (ret) -+ return dev_err_probe(dev, ret,"failed to acquire snoc_1 clock\n"); -+ - ret = pm_runtime_resume_and_get(&pdev->dev); - if (ret) - return dev_err_probe(&pdev->dev, ret, "Fail to resume\n"); -@@ -3089,8 +3102,16 @@ static int nss_cc_ipq9574_probe(struct p - clk_alpha_pll_configure(&ubi32_pll_main, regmap, &ubi32_pll_config); - - ret = qcom_cc_really_probe(&pdev->dev, &nss_cc_ipq9574_desc, regmap); -+ if (ret) -+ goto err_put_pm; -+ - pm_runtime_put(&pdev->dev); - -+ return 0; -+ -+err_put_pm: -+ pm_runtime_put_sync(dev); -+ - return ret; - } - diff --git a/target/linux/qualcommbe/patches-6.12/0359-arm64-dts-qcom-ipq9574-add-NSSNOC-clock-to-nss-node.patch b/target/linux/qualcommbe/patches-6.12/0359-arm64-dts-qcom-ipq9574-add-NSSNOC-clock-to-nss-node.patch deleted file mode 100644 index c32f077a01..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0359-arm64-dts-qcom-ipq9574-add-NSSNOC-clock-to-nss-node.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 372bbae100ffe14908bfd8448143c6cdbea17e8d Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Thu, 30 Jan 2025 16:23:03 +0100 -Subject: [PATCH] arm64: dts: qcom: ipq9574: add NSSNOC clock to nss node - -Add NSSNOC clock to nss node to attach the clock with PM clock and fix -the boot stall after ICC sync_state. - -Signed-off-by: Christian Marangi -Alex G: Do not remove GCC_NSSCC_CLK ("bus") clock - Add clock-names for the new clocks -Signed-off-by: Alexandru Gagniuc ---- - arch/arm64/boot/dts/qcom/ipq9574.dtsi | 10 ++++++++-- - 1 file changed, 8 insertions(+), 2 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi -@@ -1255,7 +1255,10 @@ - <&pcs1 1>, - <&pcs2 0>, - <&pcs2 1>, -- <&gcc GCC_NSSCC_CLK>; -+ <&gcc GCC_NSSCC_CLK>, -+ <&gcc GCC_NSSNOC_NSSCC_CLK>, -+ <&gcc GCC_NSSNOC_SNOC_CLK>, -+ <&gcc GCC_NSSNOC_SNOC_1_CLK>; - clock-names = "xo", - "nss_1200", - "ppe_353", -@@ -1266,7 +1269,10 @@ - "uniphy1_tx", - "uniphy2_rx", - "uniphy2_tx", -- "bus"; -+ "bus", -+ "nssnoc", -+ "snoc", -+ "snoc_1"; - #clock-cells = <1>; - #reset-cells = <1>; - #interconnect-cells = <1>; diff --git a/target/linux/qualcommbe/patches-6.12/0360-clk-qcom-nsscc-ipq9574-fix-port5-clock-config.patch b/target/linux/qualcommbe/patches-6.12/0360-clk-qcom-nsscc-ipq9574-fix-port5-clock-config.patch deleted file mode 100644 index 725079c810..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0360-clk-qcom-nsscc-ipq9574-fix-port5-clock-config.patch +++ /dev/null @@ -1,46 +0,0 @@ -From fa691ff57c72a8f0bfeff1a9e86ae2d78765b0da Mon Sep 17 00:00:00 2001 -From: Mantas Pucka -Date: Mon, 31 Mar 2025 15:39:59 +0300 -Subject: [PATCH] clk: qcom: nsscc-ipq9574: fix port5 clock config - -Currently there is no configuration to derive 25/125MHz port5 clock -from uniphy1 running at 125MHz. This is needed for SGMII mode when -port5 is using uniphy1. - -Fix this by adding option such clock config option. - -Signed-off-by: Mantas Pucka ---- - drivers/clk/qcom/nsscc-ipq9574.c | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/drivers/clk/qcom/nsscc-ipq9574.c -+++ b/drivers/clk/qcom/nsscc-ipq9574.c -@@ -383,11 +383,13 @@ static const struct freq_multi_tbl ftbl_ - - static const struct freq_conf ftbl_nss_cc_port5_rx_clk_src_25[] = { - C(P_UNIPHY1_NSS_RX_CLK, 12.5, 0, 0), -+ C(P_UNIPHY1_NSS_RX_CLK, 5, 0, 0), - C(P_UNIPHY0_NSS_RX_CLK, 5, 0, 0), - }; - - static const struct freq_conf ftbl_nss_cc_port5_rx_clk_src_125[] = { - C(P_UNIPHY1_NSS_RX_CLK, 2.5, 0, 0), -+ C(P_UNIPHY1_NSS_RX_CLK, 1, 0, 0), - C(P_UNIPHY0_NSS_RX_CLK, 1, 0, 0), - }; - -@@ -408,11 +410,13 @@ static const struct freq_multi_tbl ftbl_ - - static const struct freq_conf ftbl_nss_cc_port5_tx_clk_src_25[] = { - C(P_UNIPHY1_NSS_TX_CLK, 12.5, 0, 0), -+ C(P_UNIPHY1_NSS_TX_CLK, 5, 0, 0), - C(P_UNIPHY0_NSS_TX_CLK, 5, 0, 0), - }; - - static const struct freq_conf ftbl_nss_cc_port5_tx_clk_src_125[] = { - C(P_UNIPHY1_NSS_TX_CLK, 2.5, 0, 0), -+ C(P_UNIPHY1_NSS_TX_CLK, 1, 0, 0), - C(P_UNIPHY0_NSS_TX_CLK, 1, 0, 0), - }; - diff --git a/target/linux/qualcommbe/patches-6.12/0361-net-pcs-Add-10GBASER-interface-mode-support-to-IPQ-U.patch b/target/linux/qualcommbe/patches-6.12/0361-net-pcs-Add-10GBASER-interface-mode-support-to-IPQ-U.patch deleted file mode 100644 index 5bdf3e9299..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0361-net-pcs-Add-10GBASER-interface-mode-support-to-IPQ-U.patch +++ /dev/null @@ -1,136 +0,0 @@ -From 432c2a2da1e0f4a8e2c0fea191361832a7f90f36 Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Wed, 6 Mar 2024 17:40:52 +0800 -Subject: [PATCH] net: pcs: Add 10GBASER interface mode support to IPQ UNIPHY - PCS driver - -10GBASER mode is used when PCS connects with a 10G SFP module. - -Change-Id: Ifc3c3bb23811807a9b34e88771aab2c830c2327c -Signed-off-by: Lei Wei -Alex G: Use regmap to read/write registers - Remove xpcs_reset deassert logic (to be implemented later) -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/pcs/pcs-qcom-ipq9574.c | 47 ++++++++++++++++++++++++++++++ - 1 file changed, 47 insertions(+) - ---- a/drivers/net/pcs/pcs-qcom-ipq9574.c -+++ b/drivers/net/pcs/pcs-qcom-ipq9574.c -@@ -55,6 +55,9 @@ - FIELD_PREP(GENMASK(9, 2), \ - FIELD_GET(XPCS_INDIRECT_ADDR_L, reg))) - -+#define XPCS_KR_STS 0x30020 -+#define XPCS_KR_LINK_STS BIT(12) -+ - #define XPCS_DIG_CTRL 0x38000 - #define XPCS_USXG_ADPT_RESET BIT(10) - #define XPCS_USXG_EN BIT(9) -@@ -196,6 +199,28 @@ static void ipq_pcs_get_state_usxgmii(st - state->duplex = DUPLEX_FULL; - } - -+static void ipq_pcs_get_state_10gbaser(struct ipq_pcs *qpcs, -+ struct phylink_link_state *state) -+{ -+ unsigned int val; -+ int ret; -+ -+ ret = regmap_read(qpcs->regmap, XPCS_KR_STS, &val); -+ if (ret) { -+ state->link = 0; -+ return; -+ } -+ -+ state->link = !!(val & XPCS_KR_LINK_STS); -+ -+ if (!state->link) -+ return; -+ -+ state->speed = SPEED_10000; -+ state->duplex = DUPLEX_FULL; -+ state->pause |= MLO_PAUSE_TXRX_MASK; -+} -+ - static int ipq_pcs_config_mode(struct ipq_pcs *qpcs, - phy_interface_t interface) - { -@@ -212,6 +237,7 @@ static int ipq_pcs_config_mode(struct ip - val = PCS_MODE_QSGMII; - break; - case PHY_INTERFACE_MODE_USXGMII: -+ case PHY_INTERFACE_MODE_10GBASER: - val = PCS_MODE_XPCS; - rate = 312500000; - break; -@@ -311,6 +337,15 @@ static int ipq_pcs_config_usxgmii(struct - return regmap_set_bits(qpcs->regmap, XPCS_MII_CTRL, XPCS_MII_AN_EN); - } - -+static int ipq_pcs_config_10gbaser(struct ipq_pcs *qpcs) -+{ -+ /* Configure 10GBASER mode if required */ -+ if (qpcs->interface == PHY_INTERFACE_MODE_10GBASER) -+ return 0; -+ -+ return ipq_pcs_config_mode(qpcs, PHY_INTERFACE_MODE_10GBASER); -+} -+ - static int ipq_pcs_link_up_config_sgmii(struct ipq_pcs *qpcs, - int index, - unsigned int neg_mode, -@@ -399,6 +434,7 @@ static int ipq_pcs_validate(struct phyli - switch (state->interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_10GBASER: - return 0; - case PHY_INTERFACE_MODE_USXGMII: - /* USXGMII only supports full duplex mode */ -@@ -418,6 +454,8 @@ static unsigned int ipq_pcs_inband_caps( - case PHY_INTERFACE_MODE_QSGMII: - case PHY_INTERFACE_MODE_USXGMII: - return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; -+ case PHY_INTERFACE_MODE_10GBASER: -+ return LINK_INBAND_DISABLE; - default: - return 0; - } -@@ -472,6 +510,9 @@ static void ipq_pcs_get_state(struct phy - case PHY_INTERFACE_MODE_USXGMII: - ipq_pcs_get_state_usxgmii(qpcs, state); - break; -+ case PHY_INTERFACE_MODE_10GBASER: -+ ipq_pcs_get_state_10gbaser(qpcs, state); -+ break; - default: - break; - } -@@ -500,6 +541,8 @@ static int ipq_pcs_config(struct phylink - return ipq_pcs_config_sgmii(qpcs, index, neg_mode, interface); - case PHY_INTERFACE_MODE_USXGMII: - return ipq_pcs_config_usxgmii(qpcs); -+ case PHY_INTERFACE_MODE_10GBASER: -+ return ipq_pcs_config_10gbaser(qpcs); - default: - return -EOPNOTSUPP; - }; -@@ -524,6 +567,9 @@ static void ipq_pcs_link_up(struct phyli - case PHY_INTERFACE_MODE_USXGMII: - ret = ipq_pcs_link_up_config_usxgmii(qpcs, speed); - break; -+ case PHY_INTERFACE_MODE_10GBASER: -+ /* Nothing to do here */ -+ return; - default: - return; - } -@@ -603,6 +649,7 @@ static unsigned long ipq_pcs_clk_rate_ge - { - switch (qpcs->interface) { - case PHY_INTERFACE_MODE_USXGMII: -+ case PHY_INTERFACE_MODE_10GBASER: - return 312500000; - default: - return 125000000; diff --git a/target/linux/qualcommbe/patches-6.12/0362-net-pcs-Add-2500BASEX-interface-mode-support-to-IPQ-.patch b/target/linux/qualcommbe/patches-6.12/0362-net-pcs-Add-2500BASEX-interface-mode-support-to-IPQ-.patch deleted file mode 100644 index fbdebec13a..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0362-net-pcs-Add-2500BASEX-interface-mode-support-to-IPQ-.patch +++ /dev/null @@ -1,166 +0,0 @@ -From 0d3a93e3a5544daec59d8f10ac5ccab39849536e Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Tue, 2 Apr 2024 18:28:42 +0800 -Subject: [PATCH] net: pcs: Add 2500BASEX interface mode support to IPQ UNIPHY - PCS driver - -2500BASEX mode is used when PCS connects with QCA8386 switch in a fixed -2500M link. It is also used when PCS connectes with QCA8081 PHY which -works at 2500M link speed. In addition, it can be also used when PCS -connects with a 2.5G SFP module. - -Change-Id: I3fe61113c1b3685debc20659736a9488216a029d -Signed-off-by: Lei Wei -Alex G: use regmap to read/write registers - 's/ipq_unipcs/ipq_pcs/' in function names as suggested by Luo Jie -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/pcs/pcs-qcom-ipq9574.c | 67 ++++++++++++++++++++++++++++++ - 1 file changed, 67 insertions(+) - ---- a/drivers/net/pcs/pcs-qcom-ipq9574.c -+++ b/drivers/net/pcs/pcs-qcom-ipq9574.c -@@ -26,6 +26,7 @@ - #define PCS_MODE_SEL_MASK GENMASK(12, 8) - #define PCS_MODE_SGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x4) - #define PCS_MODE_QSGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x1) -+#define PCS_MODE_2500BASEX FIELD_PREP(PCS_MODE_SEL_MASK, 0x8) - #define PCS_MODE_XPCS FIELD_PREP(PCS_MODE_SEL_MASK, 0x10) - - #define PCS_MII_CTRL(x) (0x480 + 0x18 * (x)) -@@ -155,6 +156,29 @@ static void ipq_pcs_get_state_sgmii(stru - state->duplex = DUPLEX_HALF; - } - -+static void ipq_pcs_get_state_2500basex(struct ipq_pcs *qpcs, -+ struct phylink_link_state *state) -+{ -+ unsigned int val; -+ int ret; -+ -+ ret = regmap_read(qpcs->regmap, PCS_MII_STS(0), &val); -+ if (ret) { -+ state->link = 0; -+ return; -+ } -+ -+ -+ state->link = !!(val & PCS_MII_LINK_STS); -+ -+ if (!state->link) -+ return; -+ -+ state->speed = SPEED_2500; -+ state->duplex = DUPLEX_FULL; -+ state->pause |= MLO_PAUSE_TXRX_MASK; -+} -+ - static void ipq_pcs_get_state_usxgmii(struct ipq_pcs *qpcs, - struct phylink_link_state *state) - { -@@ -236,6 +260,10 @@ static int ipq_pcs_config_mode(struct ip - case PHY_INTERFACE_MODE_QSGMII: - val = PCS_MODE_QSGMII; - break; -+ case PHY_INTERFACE_MODE_2500BASEX: -+ val = PCS_MODE_2500BASEX; -+ rate = 312500000; -+ break; - case PHY_INTERFACE_MODE_USXGMII: - case PHY_INTERFACE_MODE_10GBASER: - val = PCS_MODE_XPCS; -@@ -314,6 +342,15 @@ static int ipq_pcs_config_sgmii(struct i - PCS_MII_CTRL(index), PCS_MII_FORCE_MODE); - } - -+static int ipq_pcs_config_2500basex(struct ipq_pcs *qpcs) -+{ -+ /* Configure PCS for 2500BASEX mode if required */ -+ if (qpcs->interface == PHY_INTERFACE_MODE_2500BASEX) -+ return 0; -+ -+ return ipq_pcs_config_mode(qpcs, PHY_INTERFACE_MODE_2500BASEX); -+} -+ - static int ipq_pcs_config_usxgmii(struct ipq_pcs *qpcs) - { - int ret; -@@ -388,6 +425,22 @@ static int ipq_pcs_link_up_config_sgmii( - PCS_MII_CTRL(index), PCS_MII_ADPT_RESET); - } - -+static int ipq_pcs_link_up_config_2500basex(struct ipq_pcs *qpcs, int speed) -+{ -+ int ret; -+ -+ /* 2500BASEX does not support autoneg and does not need to -+ * configure PCS speed. Only reset PCS adapter here. -+ */ -+ ret = regmap_clear_bits(qpcs->regmap, -+ PCS_MII_CTRL(0), PCS_MII_ADPT_RESET); -+ if (ret) -+ return ret; -+ -+ return regmap_set_bits(qpcs->regmap, -+ PCS_MII_CTRL(0), PCS_MII_ADPT_RESET); -+} -+ - static int ipq_pcs_link_up_config_usxgmii(struct ipq_pcs *qpcs, int speed) - { - unsigned int val; -@@ -436,6 +489,10 @@ static int ipq_pcs_validate(struct phyli - case PHY_INTERFACE_MODE_QSGMII: - case PHY_INTERFACE_MODE_10GBASER: - return 0; -+ case PHY_INTERFACE_MODE_2500BASEX: -+ /* In-band autoneg is not supported for 2500BASEX */ -+ phylink_clear(supported, Autoneg); -+ return 0; - case PHY_INTERFACE_MODE_USXGMII: - /* USXGMII only supports full duplex mode */ - phylink_clear(supported, 100baseT_Half); -@@ -454,6 +511,7 @@ static unsigned int ipq_pcs_inband_caps( - case PHY_INTERFACE_MODE_QSGMII: - case PHY_INTERFACE_MODE_USXGMII: - return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; -+ case PHY_INTERFACE_MODE_2500BASEX: - case PHY_INTERFACE_MODE_10GBASER: - return LINK_INBAND_DISABLE; - default: -@@ -507,6 +565,9 @@ static void ipq_pcs_get_state(struct phy - case PHY_INTERFACE_MODE_QSGMII: - ipq_pcs_get_state_sgmii(qpcs, index, state); - break; -+ case PHY_INTERFACE_MODE_2500BASEX: -+ ipq_pcs_get_state_2500basex(qpcs, state); -+ break; - case PHY_INTERFACE_MODE_USXGMII: - ipq_pcs_get_state_usxgmii(qpcs, state); - break; -@@ -539,6 +600,8 @@ static int ipq_pcs_config(struct phylink - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: - return ipq_pcs_config_sgmii(qpcs, index, neg_mode, interface); -+ case PHY_INTERFACE_MODE_2500BASEX: -+ return ipq_pcs_config_2500basex(qpcs); - case PHY_INTERFACE_MODE_USXGMII: - return ipq_pcs_config_usxgmii(qpcs); - case PHY_INTERFACE_MODE_10GBASER: -@@ -564,6 +627,9 @@ static void ipq_pcs_link_up(struct phyli - ret = ipq_pcs_link_up_config_sgmii(qpcs, index, - neg_mode, speed); - break; -+ case PHY_INTERFACE_MODE_2500BASEX: -+ ret = ipq_pcs_link_up_config_2500basex(qpcs, speed); -+ break; - case PHY_INTERFACE_MODE_USXGMII: - ret = ipq_pcs_link_up_config_usxgmii(qpcs, speed); - break; -@@ -648,6 +714,7 @@ static int ipq_pcs_create_miis(struct ip - static unsigned long ipq_pcs_clk_rate_get(struct ipq_pcs *qpcs) - { - switch (qpcs->interface) { -+ case PHY_INTERFACE_MODE_2500BASEX: - case PHY_INTERFACE_MODE_USXGMII: - case PHY_INTERFACE_MODE_10GBASER: - return 312500000; diff --git a/target/linux/qualcommbe/patches-6.12/0363-net-pcs-Add-1000BASEX-interface-mode-support-to-IPQ-.patch b/target/linux/qualcommbe/patches-6.12/0363-net-pcs-Add-1000BASEX-interface-mode-support-to-IPQ-.patch deleted file mode 100644 index 37aa60d8ff..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0363-net-pcs-Add-1000BASEX-interface-mode-support-to-IPQ-.patch +++ /dev/null @@ -1,104 +0,0 @@ -From d82953614a4f09dd7479e1d3904351ff85d1d088 Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Tue, 9 Apr 2024 01:07:22 +0800 -Subject: [PATCH] net: pcs: Add 1000BASEX interface mode support to IPQ UNIPHY - PCS driver - -1000BASEX is used when PCS connects with a 1G SFP module. - -Change-Id: Ied7298de3c1ecba74e6457a07fdd6b3ceab79728 -Signed-off-by: Lei Wei -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/pcs/pcs-qcom-ipq9574.c | 21 ++++++++++++++++++--- - 1 file changed, 18 insertions(+), 3 deletions(-) - ---- a/drivers/net/pcs/pcs-qcom-ipq9574.c -+++ b/drivers/net/pcs/pcs-qcom-ipq9574.c -@@ -28,6 +28,9 @@ - #define PCS_MODE_QSGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x1) - #define PCS_MODE_2500BASEX FIELD_PREP(PCS_MODE_SEL_MASK, 0x8) - #define PCS_MODE_XPCS FIELD_PREP(PCS_MODE_SEL_MASK, 0x10) -+#define PCS_MODE_SGMII_MODE_MASK GENMASK(6, 4) -+#define PCS_MODE_SGMII_MODE_1000BASEX FIELD_PREP(PCS_MODE_SGMII_MODE_MASK, \ -+ 0x0) - - #define PCS_MII_CTRL(x) (0x480 + 0x18 * (x)) - #define PCS_MII_ADPT_RESET BIT(11) -@@ -249,10 +252,11 @@ static int ipq_pcs_config_mode(struct ip - phy_interface_t interface) - { - unsigned long rate = 125000000; -- unsigned int val; -+ unsigned int val, mask; - int ret; - - /* Configure PCS interface mode */ -+ mask = PCS_MODE_SEL_MASK; - switch (interface) { - case PHY_INTERFACE_MODE_SGMII: - val = PCS_MODE_SGMII; -@@ -260,6 +264,10 @@ static int ipq_pcs_config_mode(struct ip - case PHY_INTERFACE_MODE_QSGMII: - val = PCS_MODE_QSGMII; - break; -+ case PHY_INTERFACE_MODE_1000BASEX: -+ mask |= PCS_MODE_SGMII_MODE_MASK; -+ val = PCS_MODE_SGMII | PCS_MODE_SGMII_MODE_1000BASEX; -+ break; - case PHY_INTERFACE_MODE_2500BASEX: - val = PCS_MODE_2500BASEX; - rate = 312500000; -@@ -273,8 +281,7 @@ static int ipq_pcs_config_mode(struct ip - return -EOPNOTSUPP; - } - -- ret = regmap_update_bits(qpcs->regmap, PCS_MODE_CTRL, -- PCS_MODE_SEL_MASK, val); -+ ret = regmap_update_bits(qpcs->regmap, PCS_MODE_CTRL, mask, val); - if (ret) - return ret; - -@@ -487,6 +494,7 @@ static int ipq_pcs_validate(struct phyli - switch (state->interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_1000BASEX: - case PHY_INTERFACE_MODE_10GBASER: - return 0; - case PHY_INTERFACE_MODE_2500BASEX: -@@ -509,6 +517,7 @@ static unsigned int ipq_pcs_inband_caps( - switch (interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_1000BASEX: - case PHY_INTERFACE_MODE_USXGMII: - return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; - case PHY_INTERFACE_MODE_2500BASEX: -@@ -563,6 +572,10 @@ static void ipq_pcs_get_state(struct phy - switch (state->interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_1000BASEX: -+ /* SGMII and 1000BASEX in-band autoneg word format are decoded -+ * by PCS hardware and both placed to the same status register. -+ */ - ipq_pcs_get_state_sgmii(qpcs, index, state); - break; - case PHY_INTERFACE_MODE_2500BASEX: -@@ -599,6 +612,7 @@ static int ipq_pcs_config(struct phylink - switch (interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_1000BASEX: - return ipq_pcs_config_sgmii(qpcs, index, neg_mode, interface); - case PHY_INTERFACE_MODE_2500BASEX: - return ipq_pcs_config_2500basex(qpcs); -@@ -624,6 +638,7 @@ static void ipq_pcs_link_up(struct phyli - switch (interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_1000BASEX: - ret = ipq_pcs_link_up_config_sgmii(qpcs, index, - neg_mode, speed); - break; diff --git a/target/linux/qualcommbe/patches-6.12/0364-net-pcs-Add-10G_QXGMII-interface-mode-support-to-IPQ.patch b/target/linux/qualcommbe/patches-6.12/0364-net-pcs-Add-10G_QXGMII-interface-mode-support-to-IPQ.patch deleted file mode 100644 index 2563ac8396..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0364-net-pcs-Add-10G_QXGMII-interface-mode-support-to-IPQ.patch +++ /dev/null @@ -1,267 +0,0 @@ -From fc26c6f6c69149ce87c88d6878ae929b2a138063 Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Mon, 15 Apr 2024 11:06:02 +0800 -Subject: [PATCH] net: pcs: Add 10G_QXGMII interface mode support to IPQ UNIPHY - PCS driver - -10G_QXGMII is used when PCS connectes with QCA8084 four ports -2.5G PHYs. - -Change-Id: If3dc92a07ac3e51f7c9473fb05fa0668617916fb -Signed-off-by: Lei Wei -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/pcs/pcs-qcom-ipq9574.c | 109 +++++++++++++++++++++++------ - 1 file changed, 87 insertions(+), 22 deletions(-) - ---- a/drivers/net/pcs/pcs-qcom-ipq9574.c -+++ b/drivers/net/pcs/pcs-qcom-ipq9574.c -@@ -48,6 +48,9 @@ - #define PCS_MII_STS_SPEED_100 1 - #define PCS_MII_STS_SPEED_1000 2 - -+#define PCS_QP_USXG_OPTION 0x584 -+#define PCS_QP_USXG_GMII_SRC_XPCS BIT(0) -+ - #define PCS_PLL_RESET 0x780 - #define PCS_ANA_SW_RESET BIT(6) - -@@ -63,10 +66,23 @@ - #define XPCS_KR_LINK_STS BIT(12) - - #define XPCS_DIG_CTRL 0x38000 -+#define XPCS_SOFT_RESET BIT(15) - #define XPCS_USXG_ADPT_RESET BIT(10) - #define XPCS_USXG_EN BIT(9) - -+#define XPCS_KR_CTRL 0x38007 -+#define XPCS_USXG_MODE_MASK GENMASK(12, 10) -+#define XPCS_10G_QXGMII_MODE FIELD_PREP(XPCS_USXG_MODE_MASK, 0x5) -+ -+#define XPCS_DIG_STS 0x3800a -+#define XPCS_DIG_STS_AM_COUNT GENMASK(14, 0) -+ -+/* DIG control for MII1 - MII3 */ -+#define XPCS_MII1_DIG_CTRL(x) (0x1a8000 + 0x10000 * ((x) - 1)) -+#define XPCS_MII1_USXG_ADPT_RESET BIT(5) -+ - #define XPCS_MII_CTRL 0x1f0000 -+#define XPCS_MII1_CTRL(x) (0x1a0000 + 0x10000 * ((x) - 1)) - #define XPCS_MII_AN_EN BIT(12) - #define XPCS_DUPLEX_FULL BIT(8) - #define XPCS_SPEED_MASK (BIT(13) | BIT(6) | BIT(5)) -@@ -78,9 +94,11 @@ - #define XPCS_SPEED_10 0 - - #define XPCS_MII_AN_CTRL 0x1f8001 -+#define XPCS_MII1_AN_CTRL(x) (0x1a8001 + 0x10000 * ((x) - 1)) - #define XPCS_MII_AN_8BIT BIT(8) - - #define XPCS_MII_AN_INTR_STS 0x1f8002 -+#define XPCS_MII1_AN_INTR_STS(x) (0x1a8002 + 0x10000 * ((x) - 1)) - #define XPCS_USXG_AN_LINK_STS BIT(14) - #define XPCS_USXG_AN_SPEED_MASK GENMASK(12, 10) - #define XPCS_USXG_AN_SPEED_10 0 -@@ -90,6 +108,10 @@ - #define XPCS_USXG_AN_SPEED_5000 5 - #define XPCS_USXG_AN_SPEED_10000 3 - -+#define XPCS_XAUI_MODE_CTRL 0x1f8004 -+#define XPCS_MII1_XAUI_MODE_CTRL(x) (0x1a8004 + 0x10000 * ((x) - 1)) -+#define XPCS_TX_IPG_CHECK_DIS BIT(0) -+ - /* Per PCS MII private data */ - struct ipq_pcs_mii { - struct ipq_pcs *qpcs; -@@ -182,13 +204,14 @@ static void ipq_pcs_get_state_2500basex( - state->pause |= MLO_PAUSE_TXRX_MASK; - } - --static void ipq_pcs_get_state_usxgmii(struct ipq_pcs *qpcs, -+static void ipq_pcs_get_state_usxgmii(struct ipq_pcs *qpcs, int index, - struct phylink_link_state *state) - { -- unsigned int val; -+ unsigned int reg, val; - int ret; - -- ret = regmap_read(qpcs->regmap, XPCS_MII_AN_INTR_STS, &val); -+ reg = (index == 0) ? XPCS_MII_AN_INTR_STS : XPCS_MII1_AN_INTR_STS(index); -+ ret = regmap_read(qpcs->regmap, reg, &val); - if (ret) { - state->link = 0; - return; -@@ -273,6 +296,7 @@ static int ipq_pcs_config_mode(struct ip - rate = 312500000; - break; - case PHY_INTERFACE_MODE_USXGMII: -+ case PHY_INTERFACE_MODE_10G_QXGMII: - case PHY_INTERFACE_MODE_10GBASER: - val = PCS_MODE_XPCS; - rate = 312500000; -@@ -285,6 +309,13 @@ static int ipq_pcs_config_mode(struct ip - if (ret) - return ret; - -+ if (interface == PHY_INTERFACE_MODE_10G_QXGMII) { -+ ret = regmap_set_bits(qpcs->regmap, PCS_QP_USXG_OPTION, -+ PCS_QP_USXG_GMII_SRC_XPCS); -+ if (ret) -+ return ret; -+ } -+ - /* PCS PLL reset */ - ret = regmap_clear_bits(qpcs->regmap, PCS_PLL_RESET, PCS_ANA_SW_RESET); - if (ret) -@@ -358,27 +389,51 @@ static int ipq_pcs_config_2500basex(stru - return ipq_pcs_config_mode(qpcs, PHY_INTERFACE_MODE_2500BASEX); - } - --static int ipq_pcs_config_usxgmii(struct ipq_pcs *qpcs) -+static int ipq_pcs_config_usxgmii(struct ipq_pcs *qpcs, -+ int index, -+ phy_interface_t interface) - { -+ unsigned int reg; - int ret; - - /* Configure the XPCS for USXGMII mode if required */ -- if (qpcs->interface == PHY_INTERFACE_MODE_USXGMII) -- return 0; -- -- ret = ipq_pcs_config_mode(qpcs, PHY_INTERFACE_MODE_USXGMII); -- if (ret) -- return ret; -+ if (qpcs->interface != interface) { -+ ret = ipq_pcs_config_mode(qpcs, interface); -+ if (ret) -+ return ret; - -- ret = regmap_set_bits(qpcs->regmap, XPCS_DIG_CTRL, XPCS_USXG_EN); -- if (ret) -- return ret; -+ if (interface == PHY_INTERFACE_MODE_10G_QXGMII) { -+ ret = regmap_update_bits(qpcs->regmap, XPCS_KR_CTRL, -+ XPCS_USXG_MODE_MASK, XPCS_10G_QXGMII_MODE); -+ if (ret) -+ return ret; -+ -+ /* Set Alignment Marker Interval value as 0x6018 */ -+ ret = regmap_update_bits(qpcs->regmap, XPCS_DIG_STS, -+ XPCS_DIG_STS_AM_COUNT, 0x6018); -+ if (ret) -+ return ret; -+ -+ ret = regmap_set_bits(qpcs->regmap, XPCS_DIG_CTRL, XPCS_SOFT_RESET); -+ if (ret) -+ return ret; -+ } -+ -+ /* Disable Tx IPG check for 10G_QXGMII */ -+ if (interface == PHY_INTERFACE_MODE_10G_QXGMII) { -+ reg = (index == 0) ? XPCS_XAUI_MODE_CTRL : XPCS_MII1_XAUI_MODE_CTRL(index); -+ ret = regmap_set_bits(qpcs->regmap, reg, XPCS_TX_IPG_CHECK_DIS); -+ if (ret) -+ return ret; -+ } - -- ret = regmap_set_bits(qpcs->regmap, XPCS_MII_AN_CTRL, XPCS_MII_AN_8BIT); -+ reg = (index == 0) ? XPCS_MII_AN_CTRL : XPCS_MII1_AN_CTRL(index); -+ ret = regmap_set_bits(qpcs->regmap, reg, XPCS_MII_AN_8BIT); - if (ret) - return ret; - -- return regmap_set_bits(qpcs->regmap, XPCS_MII_CTRL, XPCS_MII_AN_EN); -+ reg = (index == 0) ? XPCS_MII_CTRL : XPCS_MII1_CTRL(index); -+ return regmap_set_bits(qpcs->regmap, reg, XPCS_MII_AN_EN); - } - - static int ipq_pcs_config_10gbaser(struct ipq_pcs *qpcs) -@@ -448,9 +503,10 @@ static int ipq_pcs_link_up_config_2500ba - PCS_MII_CTRL(0), PCS_MII_ADPT_RESET); - } - --static int ipq_pcs_link_up_config_usxgmii(struct ipq_pcs *qpcs, int speed) -+static int ipq_pcs_link_up_config_usxgmii(struct ipq_pcs *qpcs, -+ int index, int speed) - { -- unsigned int val; -+ unsigned int reg, val; - int ret; - - switch (speed) { -@@ -478,14 +534,17 @@ static int ipq_pcs_link_up_config_usxgmi - } - - /* Configure XPCS speed */ -- ret = regmap_update_bits(qpcs->regmap, XPCS_MII_CTRL, -+ reg = (index == 0) ? XPCS_MII_CTRL : XPCS_MII1_CTRL(index); -+ ret = regmap_update_bits(qpcs->regmap, reg, - XPCS_SPEED_MASK, val | XPCS_DUPLEX_FULL); - if (ret) - return ret; - - /* XPCS adapter reset */ -- return regmap_set_bits(qpcs->regmap, -- XPCS_DIG_CTRL, XPCS_USXG_ADPT_RESET); -+ reg = (index == 0) ? XPCS_DIG_CTRL : XPCS_MII1_DIG_CTRL(index); -+ val = (index == 0) ? XPCS_USXG_ADPT_RESET : XPCS_MII1_USXG_ADPT_RESET; -+ return regmap_set_bits(qpcs->regmap, reg, val); -+ - } - - static int ipq_pcs_validate(struct phylink_pcs *pcs, unsigned long *supported, -@@ -502,6 +561,7 @@ static int ipq_pcs_validate(struct phyli - phylink_clear(supported, Autoneg); - return 0; - case PHY_INTERFACE_MODE_USXGMII: -+ case PHY_INTERFACE_MODE_10G_QXGMII: - /* USXGMII only supports full duplex mode */ - phylink_clear(supported, 100baseT_Half); - phylink_clear(supported, 10baseT_Half); -@@ -519,6 +579,7 @@ static unsigned int ipq_pcs_inband_caps( - case PHY_INTERFACE_MODE_QSGMII: - case PHY_INTERFACE_MODE_1000BASEX: - case PHY_INTERFACE_MODE_USXGMII: -+ case PHY_INTERFACE_MODE_10G_QXGMII: - return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; - case PHY_INTERFACE_MODE_2500BASEX: - case PHY_INTERFACE_MODE_10GBASER: -@@ -582,7 +643,8 @@ static void ipq_pcs_get_state(struct phy - ipq_pcs_get_state_2500basex(qpcs, state); - break; - case PHY_INTERFACE_MODE_USXGMII: -- ipq_pcs_get_state_usxgmii(qpcs, state); -+ case PHY_INTERFACE_MODE_10G_QXGMII: -+ ipq_pcs_get_state_usxgmii(qpcs, index, state); - break; - case PHY_INTERFACE_MODE_10GBASER: - ipq_pcs_get_state_10gbaser(qpcs, state); -@@ -617,7 +679,8 @@ static int ipq_pcs_config(struct phylink - case PHY_INTERFACE_MODE_2500BASEX: - return ipq_pcs_config_2500basex(qpcs); - case PHY_INTERFACE_MODE_USXGMII: -- return ipq_pcs_config_usxgmii(qpcs); -+ case PHY_INTERFACE_MODE_10G_QXGMII: -+ return ipq_pcs_config_usxgmii(qpcs, index, interface); - case PHY_INTERFACE_MODE_10GBASER: - return ipq_pcs_config_10gbaser(qpcs); - default: -@@ -646,7 +709,8 @@ static void ipq_pcs_link_up(struct phyli - ret = ipq_pcs_link_up_config_2500basex(qpcs, speed); - break; - case PHY_INTERFACE_MODE_USXGMII: -- ret = ipq_pcs_link_up_config_usxgmii(qpcs, speed); -+ case PHY_INTERFACE_MODE_10G_QXGMII: -+ ret = ipq_pcs_link_up_config_usxgmii(qpcs, index, speed); - break; - case PHY_INTERFACE_MODE_10GBASER: - /* Nothing to do here */ -@@ -731,6 +795,7 @@ static unsigned long ipq_pcs_clk_rate_ge - switch (qpcs->interface) { - case PHY_INTERFACE_MODE_2500BASEX: - case PHY_INTERFACE_MODE_USXGMII: -+ case PHY_INTERFACE_MODE_10G_QXGMII: - case PHY_INTERFACE_MODE_10GBASER: - return 312500000; - default: diff --git a/target/linux/qualcommbe/patches-6.12/0365-net-pcs-ipq-uniphy-control-MISC2-register-for-2.5G-s.patch b/target/linux/qualcommbe/patches-6.12/0365-net-pcs-ipq-uniphy-control-MISC2-register-for-2.5G-s.patch deleted file mode 100644 index 6ec8f2634e..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0365-net-pcs-ipq-uniphy-control-MISC2-register-for-2.5G-s.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 87da3bbd25eb0a17e2c698120528e76c26b326d0 Mon Sep 17 00:00:00 2001 -From: Mantas Pucka -Date: Mon, 2 Jun 2025 17:18:13 +0300 -Subject: [PATCH] net: pcs: ipq-uniphy: control MISC2 register for 2.5G support - -When 2500base-x mode is enabled MISC2 regsister needs to have different -value than for other 1G modes. - -Signed-off-by: Mantas Pucka ---- - drivers/net/pcs/pcs-qcom-ipq9574.c | 17 ++++++++++++++++- - 1 file changed, 16 insertions(+), 1 deletion(-) - ---- a/drivers/net/pcs/pcs-qcom-ipq9574.c -+++ b/drivers/net/pcs/pcs-qcom-ipq9574.c -@@ -22,6 +22,11 @@ - #define PCS_CALIBRATION 0x1e0 - #define PCS_CALIBRATION_DONE BIT(7) - -+#define PCS_MISC2 0x218 -+#define PCS_MISC2_MODE_MASK GENMASK(6, 5) -+#define PCS_MISC2_MODE_SGMII FIELD_PREP(PCS_MISC2_MODE_MASK, 0x1) -+#define PCS_MISC2_MODE_SGMII_PLUS FIELD_PREP(PCS_MISC2_MODE_MASK, 0x2) -+ - #define PCS_MODE_CTRL 0x46c - #define PCS_MODE_SEL_MASK GENMASK(12, 8) - #define PCS_MODE_SGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x4) -@@ -275,7 +280,7 @@ static int ipq_pcs_config_mode(struct ip - phy_interface_t interface) - { - unsigned long rate = 125000000; -- unsigned int val, mask; -+ unsigned int val, mask, misc2 = 0; - int ret; - - /* Configure PCS interface mode */ -@@ -283,6 +288,7 @@ static int ipq_pcs_config_mode(struct ip - switch (interface) { - case PHY_INTERFACE_MODE_SGMII: - val = PCS_MODE_SGMII; -+ misc2 = PCS_MISC2_MODE_SGMII; - break; - case PHY_INTERFACE_MODE_QSGMII: - val = PCS_MODE_QSGMII; -@@ -290,9 +296,11 @@ static int ipq_pcs_config_mode(struct ip - case PHY_INTERFACE_MODE_1000BASEX: - mask |= PCS_MODE_SGMII_MODE_MASK; - val = PCS_MODE_SGMII | PCS_MODE_SGMII_MODE_1000BASEX; -+ misc2 = PCS_MISC2_MODE_SGMII; - break; - case PHY_INTERFACE_MODE_2500BASEX: - val = PCS_MODE_2500BASEX; -+ misc2 = PCS_MISC2_MODE_SGMII_PLUS; - rate = 312500000; - break; - case PHY_INTERFACE_MODE_USXGMII: -@@ -315,6 +323,13 @@ static int ipq_pcs_config_mode(struct ip - if (ret) - return ret; - } -+ -+ if (misc2) { -+ ret = regmap_update_bits(qpcs->regmap, PCS_MISC2, -+ PCS_MISC2_MODE_MASK, misc2); -+ if (ret) -+ return ret; -+ } - - /* PCS PLL reset */ - ret = regmap_clear_bits(qpcs->regmap, PCS_PLL_RESET, PCS_ANA_SW_RESET); diff --git a/target/linux/qualcommbe/patches-6.12/0367-net-pcs-ipq-uniphy-fix-USXGMII-link-up-failure.patch b/target/linux/qualcommbe/patches-6.12/0367-net-pcs-ipq-uniphy-fix-USXGMII-link-up-failure.patch deleted file mode 100644 index b02782e7b3..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0367-net-pcs-ipq-uniphy-fix-USXGMII-link-up-failure.patch +++ /dev/null @@ -1,24 +0,0 @@ -From bedf56b46ae53c4abb21eebb3e1d5a7483926dda Mon Sep 17 00:00:00 2001 -From: Mantas Pucka -Date: Mon, 2 Jun 2025 17:20:58 +0300 -Subject: [PATCH] net: pcs: ipq-uniphy: fix USXGMII link-up failure - -USXGMII link-up may fail due to too short delay after PLL reset. -Increase the delay to fix this. - -Signed-off-by: Mantas Pucka ---- - drivers/net/pcs/pcs-qcom-ipq9574.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/pcs/pcs-qcom-ipq9574.c -+++ b/drivers/net/pcs/pcs-qcom-ipq9574.c -@@ -336,7 +336,7 @@ static int ipq_pcs_config_mode(struct ip - if (ret) - return ret; - -- fsleep(1000); -+ fsleep(20000); - ret = regmap_set_bits(qpcs->regmap, PCS_PLL_RESET, PCS_ANA_SW_RESET); - if (ret) - return ret; diff --git a/target/linux/qualcommbe/patches-6.12/0368-net-pcs-qcom-ipq9574-Update-IPQ9574-PCS-driver.patch b/target/linux/qualcommbe/patches-6.12/0368-net-pcs-qcom-ipq9574-Update-IPQ9574-PCS-driver.patch deleted file mode 100644 index 63a523ae1c..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0368-net-pcs-qcom-ipq9574-Update-IPQ9574-PCS-driver.patch +++ /dev/null @@ -1,282 +0,0 @@ -From b4e07a8a3ec3dc5f676238987556e2aff0b14028 Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Mon, 29 Jan 2024 11:39:36 +0800 -Subject: [PATCH] net: pcs: qcom-ipq9574: Update IPQ9574 PCS driver - -Keep the PCS driver synced with the latest version posted to the kernel -community and add the XPCS reset support. - -Signed-off-by: Luo Jie -Signed-off-by: Alexandru Gagniuc ---- - .../bindings/net/pcs/qcom,ipq9574-pcs.yaml | 7 ++ - drivers/net/pcs/pcs-qcom-ipq9574.c | 68 +++++++++++++++---- - 2 files changed, 63 insertions(+), 12 deletions(-) - ---- a/Documentation/devicetree/bindings/net/pcs/qcom,ipq9574-pcs.yaml -+++ b/Documentation/devicetree/bindings/net/pcs/qcom,ipq9574-pcs.yaml -@@ -98,6 +98,10 @@ properties: - - const: sys - - const: ahb - -+ resets: -+ maxItems: 1 -+ description: XPCS reset -+ - '#clock-cells': - const: 1 - description: See include/dt-bindings/net/qcom,ipq9574-pcs.h for constants -@@ -137,6 +141,7 @@ required: - - '#size-cells' - - clocks - - clock-names -+ - resets - - '#clock-cells' - - additionalProperties: false -@@ -144,6 +149,7 @@ additionalProperties: false - examples: - - | - #include -+ #include - - ethernet-pcs@7a00000 { - compatible = "qcom,ipq9574-pcs"; -@@ -154,6 +160,7 @@ examples: - <&gcc GCC_UNIPHY0_AHB_CLK>; - clock-names = "sys", - "ahb"; -+ resets = <&gcc GCC_UNIPHY0_XPCS_RESET>; - #clock-cells = <1>; - - pcs-mii@0 { ---- a/drivers/net/pcs/pcs-qcom-ipq9574.c -+++ b/drivers/net/pcs/pcs-qcom-ipq9574.c -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - - #include - -@@ -31,9 +32,12 @@ - #define PCS_MODE_SEL_MASK GENMASK(12, 8) - #define PCS_MODE_SGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x4) - #define PCS_MODE_QSGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x1) -+#define PCS_MODE_PSGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x2) - #define PCS_MODE_2500BASEX FIELD_PREP(PCS_MODE_SEL_MASK, 0x8) - #define PCS_MODE_XPCS FIELD_PREP(PCS_MODE_SEL_MASK, 0x10) - #define PCS_MODE_SGMII_MODE_MASK GENMASK(6, 4) -+#define PCS_MODE_SGMII_MODE_MAC FIELD_PREP(PCS_MODE_SGMII_MODE_MASK, \ -+ 0x2) - #define PCS_MODE_SGMII_MODE_1000BASEX FIELD_PREP(PCS_MODE_SGMII_MODE_MASK, \ - 0x0) - -@@ -52,6 +56,8 @@ - #define PCS_MII_STS_SPEED_10 0 - #define PCS_MII_STS_SPEED_100 1 - #define PCS_MII_STS_SPEED_1000 2 -+#define PCS_MII_STS_PAUSE_TX_EN BIT(1) -+#define PCS_MII_STS_PAUSE_RX_EN BIT(0) - - #define PCS_QP_USXG_OPTION 0x584 - #define PCS_QP_USXG_GMII_SRC_XPCS BIT(0) -@@ -142,6 +148,7 @@ struct ipq_pcs { - struct clk_hw tx_hw; - - struct ipq_pcs_mii *qpcs_mii[PCS_MAX_MII_NRS]; -+ struct reset_control *xpcs_rstc; - }; - - #define phylink_pcs_to_qpcs_mii(_pcs) \ -@@ -184,6 +191,11 @@ static void ipq_pcs_get_state_sgmii(stru - state->duplex = DUPLEX_FULL; - else - state->duplex = DUPLEX_HALF; -+ -+ if (val & PCS_MII_STS_PAUSE_TX_EN) -+ state->pause |= MLO_PAUSE_TX; -+ if (val & PCS_MII_STS_PAUSE_RX_EN) -+ state->pause |= MLO_PAUSE_RX; - } - - static void ipq_pcs_get_state_2500basex(struct ipq_pcs *qpcs, -@@ -198,7 +210,6 @@ static void ipq_pcs_get_state_2500basex( - return; - } - -- - state->link = !!(val & PCS_MII_LINK_STS); - - if (!state->link) -@@ -281,17 +292,27 @@ static int ipq_pcs_config_mode(struct ip - { - unsigned long rate = 125000000; - unsigned int val, mask, misc2 = 0; -+ bool xpcs_mode = false; - int ret; - -+ /* Assert XPCS reset */ -+ reset_control_assert(qpcs->xpcs_rstc); -+ - /* Configure PCS interface mode */ - mask = PCS_MODE_SEL_MASK; - switch (interface) { - case PHY_INTERFACE_MODE_SGMII: -- val = PCS_MODE_SGMII; -+ mask |= PCS_MODE_SGMII_MODE_MASK; -+ val = PCS_MODE_SGMII | PCS_MODE_SGMII_MODE_MAC; - misc2 = PCS_MISC2_MODE_SGMII; - break; - case PHY_INTERFACE_MODE_QSGMII: -- val = PCS_MODE_QSGMII; -+ mask |= PCS_MODE_SGMII_MODE_MASK; -+ val = PCS_MODE_QSGMII | PCS_MODE_SGMII_MODE_MAC; -+ break; -+ case PHY_INTERFACE_MODE_PSGMII: -+ mask |= PCS_MODE_SGMII_MODE_MASK; -+ val = PCS_MODE_PSGMII | PCS_MODE_SGMII_MODE_MAC; - break; - case PHY_INTERFACE_MODE_1000BASEX: - mask |= PCS_MODE_SGMII_MODE_MASK; -@@ -308,6 +329,7 @@ static int ipq_pcs_config_mode(struct ip - case PHY_INTERFACE_MODE_10GBASER: - val = PCS_MODE_XPCS; - rate = 312500000; -+ xpcs_mode = true; - break; - default: - return -EOPNOTSUPP; -@@ -367,6 +389,10 @@ static int ipq_pcs_config_mode(struct ip - return ret; - } - -+ /* Deassert XPCS */ -+ if (xpcs_mode) -+ reset_control_deassert(qpcs->xpcs_rstc); -+ - return 0; - } - -@@ -384,15 +410,13 @@ static int ipq_pcs_config_sgmii(struct i - return ret; - } - -- /* Nothing to do here as in-band autoneg mode is enabled -- * by default for each PCS MII port. -- */ -+ /* Set AN mode or force mode */ - if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) -- return 0; -- -- /* Set force speed mode */ -- return regmap_set_bits(qpcs->regmap, -- PCS_MII_CTRL(index), PCS_MII_FORCE_MODE); -+ return regmap_clear_bits(qpcs->regmap, -+ PCS_MII_CTRL(index), PCS_MII_FORCE_MODE); -+ else -+ return regmap_set_bits(qpcs->regmap, -+ PCS_MII_CTRL(index), PCS_MII_FORCE_MODE); - } - - static int ipq_pcs_config_2500basex(struct ipq_pcs *qpcs) -@@ -417,6 +441,10 @@ static int ipq_pcs_config_usxgmii(struct - if (ret) - return ret; - -+ ret = regmap_set_bits(qpcs->regmap, XPCS_DIG_CTRL, XPCS_USXG_EN); -+ if (ret) -+ return ret; -+ - if (interface == PHY_INTERFACE_MODE_10G_QXGMII) { - ret = regmap_update_bits(qpcs->regmap, XPCS_KR_CTRL, - XPCS_USXG_MODE_MASK, XPCS_10G_QXGMII_MODE); -@@ -432,6 +460,7 @@ static int ipq_pcs_config_usxgmii(struct - ret = regmap_set_bits(qpcs->regmap, XPCS_DIG_CTRL, XPCS_SOFT_RESET); - if (ret) - return ret; -+ } - } - - /* Disable Tx IPG check for 10G_QXGMII */ -@@ -559,7 +588,6 @@ static int ipq_pcs_link_up_config_usxgmi - reg = (index == 0) ? XPCS_DIG_CTRL : XPCS_MII1_DIG_CTRL(index); - val = (index == 0) ? XPCS_USXG_ADPT_RESET : XPCS_MII1_USXG_ADPT_RESET; - return regmap_set_bits(qpcs->regmap, reg, val); -- - } - - static int ipq_pcs_validate(struct phylink_pcs *pcs, unsigned long *supported, -@@ -568,6 +596,7 @@ static int ipq_pcs_validate(struct phyli - switch (state->interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_PSGMII: - case PHY_INTERFACE_MODE_1000BASEX: - case PHY_INTERFACE_MODE_10GBASER: - return 0; -@@ -592,6 +621,7 @@ static unsigned int ipq_pcs_inband_caps( - switch (interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_PSGMII: - case PHY_INTERFACE_MODE_1000BASEX: - case PHY_INTERFACE_MODE_USXGMII: - case PHY_INTERFACE_MODE_10G_QXGMII: -@@ -648,6 +678,7 @@ static void ipq_pcs_get_state(struct phy - switch (state->interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_PSGMII: - case PHY_INTERFACE_MODE_1000BASEX: - /* SGMII and 1000BASEX in-band autoneg word format are decoded - * by PCS hardware and both placed to the same status register. -@@ -689,6 +720,7 @@ static int ipq_pcs_config(struct phylink - switch (interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_PSGMII: - case PHY_INTERFACE_MODE_1000BASEX: - return ipq_pcs_config_sgmii(qpcs, index, neg_mode, interface); - case PHY_INTERFACE_MODE_2500BASEX: -@@ -703,6 +735,11 @@ static int ipq_pcs_config(struct phylink - }; - } - -+static void ipq_pcs_an_restart(struct phylink_pcs *pcs) -+{ -+ /* Currently not used */ -+} -+ - static void ipq_pcs_link_up(struct phylink_pcs *pcs, - unsigned int neg_mode, - phy_interface_t interface, -@@ -716,6 +753,7 @@ static void ipq_pcs_link_up(struct phyli - switch (interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_PSGMII: - case PHY_INTERFACE_MODE_1000BASEX: - ret = ipq_pcs_link_up_config_sgmii(qpcs, index, - neg_mode, speed); -@@ -746,6 +784,7 @@ static const struct phylink_pcs_ops ipq_ - .pcs_disable = ipq_pcs_disable, - .pcs_get_state = ipq_pcs_get_state, - .pcs_config = ipq_pcs_config, -+ .pcs_an_restart = ipq_pcs_an_restart, - .pcs_link_up = ipq_pcs_link_up, - }; - -@@ -990,6 +1029,11 @@ static int ipq9574_pcs_probe(struct plat - return dev_err_probe(dev, PTR_ERR(clk), - "Failed to enable AHB clock\n"); - -+ qpcs->xpcs_rstc = devm_reset_control_get_optional(dev, NULL); -+ if (IS_ERR_OR_NULL(qpcs->xpcs_rstc)) -+ return dev_err_probe(dev, PTR_ERR(qpcs->xpcs_rstc), -+ "Failed to get XPCS reset\n"); -+ - ret = ipq_pcs_clk_register(qpcs); - if (ret) - return ret; diff --git a/target/linux/qualcommbe/patches-6.12/0370-net-phy-Add-phy_package_remove_once-helper.patch b/target/linux/qualcommbe/patches-6.12/0370-net-phy-Add-phy_package_remove_once-helper.patch deleted file mode 100644 index ec81286431..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0370-net-phy-Add-phy_package_remove_once-helper.patch +++ /dev/null @@ -1,36 +0,0 @@ -From d11eba3e178a9d42a579c656b2c9b643f4ce3e1e Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Mon, 23 Sep 2024 18:46:34 +0800 -Subject: [PATCH] net: phy: Add phy_package_remove_once helper - -QCA8084 PHY package needs to do the PHY package clean up, -add phy_package_remove_once helper to support. - -Change-Id: I3cd73bc7be1b1d531435ef72f48db0682548decf -Signed-off-by: Luo Jie ---- - include/linux/phy.h | 6 ++++++ - 1 file changed, 6 insertions(+) - ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -376,6 +376,7 @@ struct phy_package_shared { - /* used as bit number in atomic bitops */ - #define PHY_SHARED_F_INIT_DONE 0 - #define PHY_SHARED_F_PROBE_DONE 1 -+#define PHY_SHARED_F_REMOVE_DONE 2 - - /** - * struct mii_bus - Represents an MDIO bus -@@ -2290,6 +2291,11 @@ static inline bool phy_package_probe_onc - return __phy_package_set_once(phydev, PHY_SHARED_F_PROBE_DONE); - } - -+static inline bool phy_package_remove_once(struct phy_device *phydev) -+{ -+ return __phy_package_set_once(phydev, PHY_SHARED_F_REMOVE_DONE); -+} -+ - extern const struct bus_type mdio_bus_type; - - struct mdio_board_info { diff --git a/target/linux/qualcommbe/patches-6.12/0371-net-phy-qca808x-Add-QCA8084-SerDes-probe-and-remove-.patch b/target/linux/qualcommbe/patches-6.12/0371-net-phy-qca808x-Add-QCA8084-SerDes-probe-and-remove-.patch deleted file mode 100644 index a0c84bddeb..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0371-net-phy-qca808x-Add-QCA8084-SerDes-probe-and-remove-.patch +++ /dev/null @@ -1,437 +0,0 @@ -From c12b79af730116936504afe97234f9afb6ac8fc0 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Mon, 23 Sep 2024 20:28:24 +0800 -Subject: [PATCH] net: phy: qca808x: Add QCA8084 SerDes probe and remove - functions - -QCA8084 PHY package integrates the XPCS and PCS, which is used -to support 10G-QXGMII. XPCS includes 4 channels to connect with -Quad PHY, and PCS controls the interface mode configured. - -XPCS and PCS are probed and removed by PHY package. - -Change-Id: Ided0a5cd4c996dc2a2a0d0598e930fab060caaf8 -Signed-off-by: Luo Jie -Alex G: Use phy_package_get_*() accessors -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/phy/qcom/Makefile | 2 +- - drivers/net/phy/qcom/qca8084_serdes.c | 249 ++++++++++++++++++++++++++ - drivers/net/phy/qcom/qca8084_serdes.h | 18 ++ - drivers/net/phy/qcom/qca808x.c | 53 ++++++ - 4 files changed, 321 insertions(+), 1 deletion(-) - create mode 100644 drivers/net/phy/qcom/qca8084_serdes.c - create mode 100644 drivers/net/phy/qcom/qca8084_serdes.h - ---- a/drivers/net/phy/qcom/Makefile -+++ b/drivers/net/phy/qcom/Makefile -@@ -2,5 +2,5 @@ - obj-$(CONFIG_QCOM_NET_PHYLIB) += qcom-phy-lib.o - obj-$(CONFIG_AT803X_PHY) += at803x.o - obj-$(CONFIG_QCA83XX_PHY) += qca83xx.o --obj-$(CONFIG_QCA808X_PHY) += qca808x.o -+obj-$(CONFIG_QCA808X_PHY) += qca808x.o qca8084_serdes.o - obj-$(CONFIG_QCA807X_PHY) += qca807x.o ---- /dev/null -+++ b/drivers/net/phy/qcom/qca8084_serdes.c -@@ -0,0 +1,249 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "qca8084_serdes.h" -+ -+/* XPCS includes 4 channels, each channel has the different MMD ID for -+ * configuring auto-negotiation complete interrupt, mii-4bit, auto- -+ * negotiation capabilities and TX configuration for the connected PHY. -+ * -+ * MMD31 is for channel 0; -+ * MMD26 is for channel 1; -+ * MMD27 is for channel 2; -+ * MMD28 is for channel 3; -+ */ -+#define QCA8084_CHANNEL_MAX 4 -+ -+enum pcs_clk_id { -+ PCS_CLK, -+ PCS_RX_ROOT_CLK, -+ PCS_TX_ROOT_CLK, -+ PCS_CLK_MAX -+}; -+ -+enum xpcs_clk_id { -+ XPCS_XGMII_RX_CLK, -+ XPCS_XGMII_TX_CLK, -+ XPCS_RX_CLK, -+ XPCS_TX_CLK, -+ XPCS_PORT_RX_CLK, -+ XPCS_PORT_TX_CLK, -+ XPCS_RX_SRC_CLK, -+ XPCS_TX_SRC_CLK, -+ XPCS_CLK_MAX -+}; -+ -+struct qca8084_xpcs_channel_priv { -+ int ch_id; -+ struct reset_control *rstcs; -+ struct clk *clks[XPCS_CLK_MAX]; -+}; -+ -+struct qca8084_pcs_data { -+ struct reset_control *rstc; -+ struct clk *clks[PCS_CLK_MAX]; -+}; -+ -+struct qca8084_xpcs_data { -+ struct reset_control *rstc; -+ struct qca8084_xpcs_channel_priv xpcs_ch[QCA8084_CHANNEL_MAX]; -+}; -+ -+static const char *const xpcs_clock_names[XPCS_CLK_MAX] = { -+ [XPCS_XGMII_RX_CLK] = "xgmii_rx", -+ [XPCS_XGMII_TX_CLK] = "xgmii_tx", -+ [XPCS_RX_CLK] = "xpcs_rx", -+ [XPCS_TX_CLK] = "xpcs_tx", -+ [XPCS_PORT_RX_CLK] = "port_rx", -+ [XPCS_PORT_TX_CLK] = "port_tx", -+ [XPCS_RX_SRC_CLK] = "rx_src", -+ [XPCS_TX_SRC_CLK] = "tx_src", -+}; -+ -+static const char *const pcs_clock_names[PCS_CLK_MAX] = { -+ [PCS_CLK] = "pcs", -+ [PCS_RX_ROOT_CLK] = "pcs_rx_root", -+ [PCS_TX_ROOT_CLK] = "pcs_tx_root", -+}; -+ -+struct mdio_device *qca8084_package_pcs_probe(struct device_node *pcs_np) -+{ -+ struct qca8084_pcs_data *pcs_data; -+ struct mdio_device *mdiodev; -+ struct reset_control *rstc; -+ struct device *dev; -+ struct clk *clk; -+ int i; -+ -+ mdiodev = fwnode_mdio_find_device(of_fwnode_handle(pcs_np)); -+ if (!mdiodev) -+ return ERR_PTR(-EPROBE_DEFER); -+ -+ dev = &mdiodev->dev; -+ pcs_data = devm_kzalloc(dev, sizeof(*pcs_data), GFP_KERNEL); -+ if (!pcs_data) { -+ dev_err(dev, "Allocate PCS data failed\n"); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ rstc = devm_reset_control_get_exclusive(dev, NULL); -+ if (IS_ERR(rstc)) { -+ dev_err(dev, "Get PCS reset failed\n"); -+ return ERR_CAST(rstc); -+ } -+ -+ pcs_data->rstc = rstc; -+ -+ for (i = 0; i < ARRAY_SIZE(pcs_clock_names); i++) { -+ clk = devm_clk_get(dev, pcs_clock_names[i]); -+ if (IS_ERR(clk)) { -+ dev_err(dev, "Failed to get the PCS clock ID %s\n", -+ pcs_clock_names[i]); -+ return ERR_CAST(clk); -+ } -+ pcs_data->clks[i] = clk; -+ } -+ -+ mdiodev_set_drvdata(mdiodev, pcs_data); -+ -+ return mdiodev; -+} -+ -+struct mdio_device *qca8084_package_xpcs_probe(struct device_node *xpcs_np) -+{ -+ struct qca8084_xpcs_data *xpcs_data; -+ struct mdio_device *mdiodev; -+ struct reset_control *rstc; -+ struct device_node *child; -+ struct device *dev; -+ struct clk *clk; -+ int i, j, node; -+ -+ mdiodev = fwnode_mdio_find_device(of_fwnode_handle(xpcs_np)); -+ if (!mdiodev) -+ return ERR_PTR(-EPROBE_DEFER); -+ -+ dev = &mdiodev->dev; -+ -+ xpcs_data = devm_kzalloc(dev, sizeof(*xpcs_data), GFP_KERNEL); -+ if (!xpcs_data) { -+ dev_err(dev, "Allocate XPCS data failed\n"); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ rstc = devm_reset_control_get_exclusive(dev, NULL); -+ if (IS_ERR(rstc)) { -+ dev_err(dev, "Get XPCS reset failed\n"); -+ return ERR_CAST(rstc); -+ } -+ -+ xpcs_data->rstc = rstc; -+ -+ /* Sanity check the number of channel sub nodes */ -+ node = of_get_available_child_count(xpcs_np); -+ if (node != QCA8084_CHANNEL_MAX) -+ return ERR_PTR(-EINVAL); -+ -+ node = 0; -+ for_each_available_child_of_node(xpcs_np, child) { -+ struct qca8084_xpcs_channel_priv *ch_data; -+ u32 channel; -+ -+ /* The subnode name must be 'channel'. */ -+ if (!(of_node_name_eq(child, "channel"))) -+ continue; -+ -+ if (of_property_read_u32(child, "reg", &channel)) { -+ dev_err(dev, "%s: Failed to get reg\n", -+ child->full_name); -+ -+ mdiodev = ERR_PTR(-EINVAL); -+ goto put_ch_clk_rst; -+ } -+ -+ if (channel >= QCA8084_CHANNEL_MAX) { -+ dev_err(dev, "%s: Invalid reg %d\n", -+ child->full_name, channel); -+ -+ mdiodev = ERR_PTR(-EINVAL); -+ goto put_ch_clk_rst; -+ } -+ -+ ch_data = &xpcs_data->xpcs_ch[node]; -+ ch_data->ch_id = channel; -+ -+ ch_data->rstcs = of_reset_control_array_get_exclusive(child); -+ if (IS_ERR(ch_data->rstcs)) { -+ dev_err(dev, "%s: Failed to get reset\n", -+ child->full_name); -+ -+ mdiodev = ERR_CAST(ch_data->rstcs); -+ goto put_ch_clk_rst; -+ } -+ -+ for (j = 0; j < ARRAY_SIZE(xpcs_clock_names); j++) { -+ clk = of_clk_get_by_name(child, xpcs_clock_names[j]); -+ if (IS_ERR(clk)) { -+ dev_err(dev, "Failed to get the clock ID %s\n", -+ xpcs_clock_names[j]); -+ mdiodev = ERR_CAST(clk); -+ goto put_ch_child; -+ } -+ ch_data->clks[j] = clk; -+ } -+ -+ node++; -+ } -+ -+ mdiodev_set_drvdata(mdiodev, xpcs_data); -+ -+ return mdiodev; -+ -+put_ch_child: -+ node++; -+ -+put_ch_clk_rst: -+ for (i = 0; i < node; i++) { -+ j--; -+ while (j >= 0) { -+ clk_put(xpcs_data->xpcs_ch[i].clks[j]); -+ j--; -+ } -+ -+ j = ARRAY_SIZE(xpcs_clock_names); -+ } -+ -+ for (i = 0; i < node; i++) -+ reset_control_put(xpcs_data->xpcs_ch[i].rstcs); -+ -+ of_node_put(child); -+ -+ return mdiodev; -+} -+ -+void qca8084_package_xpcs_and_pcs_remove(struct mdio_device *xpcs_mdiodev, -+ struct mdio_device *pcs_mdiodev) -+{ -+ struct qca8084_xpcs_data *xpcs_data = mdiodev_get_drvdata(xpcs_mdiodev); -+ int i, j; -+ -+ for (i = 0; i < ARRAY_SIZE(xpcs_data->xpcs_ch); i++) { -+ reset_control_put(xpcs_data->xpcs_ch[i].rstcs); -+ -+ for (j = 0; j < ARRAY_SIZE(xpcs_data->xpcs_ch[i].clks); j++) -+ clk_put(xpcs_data->xpcs_ch[i].clks[j]); -+ } -+ -+ mdio_device_put(xpcs_mdiodev); -+ mdio_device_put(pcs_mdiodev); -+} ---- /dev/null -+++ b/drivers/net/phy/qcom/qca8084_serdes.h -@@ -0,0 +1,18 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Driver for QCA8084 SerDes -+ * -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#ifndef _QCA8084_SERDES_H_ -+#define _QCA8084_SERDES_H_ -+ -+#include -+#include -+ -+struct mdio_device *qca8084_package_pcs_probe(struct device_node *pcs_np); -+struct mdio_device *qca8084_package_xpcs_probe(struct device_node *xpcs_np); -+void qca8084_package_xpcs_and_pcs_remove(struct mdio_device *xpcs_mdiodev, -+ struct mdio_device *pcs_mdiodev); -+#endif /* _QCA8084_SERDES_H_ */ ---- a/drivers/net/phy/qcom/qca808x.c -+++ b/drivers/net/phy/qcom/qca808x.c -@@ -8,6 +8,7 @@ - #include - - #include "../phylib.h" -+#include "qca8084_serdes.h" - #include "qcom.h" - - /* ADC threshold */ -@@ -172,11 +173,13 @@ enum { - - struct qca808x_priv { - int led_polarity_mode; -+ int channel_id; - }; - - struct qca808x_shared_priv { - int package_mode; - struct clk *clk[PACKAGE_CLK_MAX]; -+ struct mdio_device *mdiodev[2]; /* PCS and XPCS mdio device */ - }; - - static const char *const qca8084_package_clk_name[PACKAGE_CLK_MAX] = { -@@ -354,6 +357,8 @@ static int qca808x_probe(struct phy_devi - { - struct device *dev = &phydev->mdio.dev; - struct qca808x_priv *priv; -+ u32 ch_id = 0; -+ int ret; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) -@@ -362,6 +367,14 @@ static int qca808x_probe(struct phy_devi - /* Init LED polarity mode to -1 */ - priv->led_polarity_mode = -1; - -+ /* DT property qcom,xpcs-channel" is optional and only available for -+ * 10G-QXGMII mode. -+ */ -+ ret = of_property_read_u32(dev->of_node, "qcom,xpcs-channel", &ch_id); -+ if (ret && ret != -EINVAL) -+ return ret; -+ -+ priv->channel_id = ch_id; - phydev->priv = priv; - - return 0; -@@ -1012,6 +1025,7 @@ static int qca8084_phy_package_probe_onc - struct device_node *np = phy_package_get_node(phydev); - struct qca808x_shared_priv *shared_priv; - struct reset_control *rstc; -+ struct device_node *child; - int i, ret, clear, set; - struct clk *clk; - -@@ -1072,6 +1086,26 @@ static int qca8084_phy_package_probe_onc - if (ret && ret != -EINVAL) - return ret; - -+ for_each_available_child_of_node(np, child) { -+ struct mdio_device *mdiodev; -+ -+ if (of_node_name_eq(child, "pcs-phy")) { -+ mdiodev = qca8084_package_pcs_probe(child); -+ if (IS_ERR(mdiodev)) -+ return PTR_ERR(mdiodev); -+ -+ shared_priv->mdiodev[0] = mdiodev; -+ } -+ -+ if (of_node_name_eq(child, "xpcs-phy")) { -+ mdiodev = qca8084_package_xpcs_probe(child); -+ if (IS_ERR(mdiodev)) -+ return PTR_ERR(mdiodev); -+ -+ shared_priv->mdiodev[1] = mdiodev; -+ } -+ } -+ - rstc = of_reset_control_get_exclusive(np, NULL); - if (IS_ERR(rstc)) - return dev_err_probe(&phydev->mdio.dev, PTR_ERR(rstc), -@@ -1081,6 +1115,14 @@ static int qca8084_phy_package_probe_onc - return reset_control_deassert(rstc); - } - -+static void qca8084_phy_package_remove_once(struct phy_device *phydev) -+{ -+ struct qca808x_shared_priv *shared_priv = phy_package_get_priv(phydev);; -+ -+ qca8084_package_xpcs_and_pcs_remove(shared_priv->mdiodev[1], -+ shared_priv->mdiodev[0]); -+} -+ - static int qca8084_probe(struct phy_device *phydev) - { - struct qca808x_shared_priv *shared_priv; -@@ -1099,6 +1141,10 @@ static int qca8084_probe(struct phy_devi - return ret; - } - -+ ret = qca808x_probe(phydev); -+ if (ret) -+ return ret; -+ - /* Enable clock of PHY device, so that the PHY register - * can be accessed to get PHY features. - */ -@@ -1116,6 +1162,12 @@ static int qca8084_probe(struct phy_devi - return reset_control_deassert(rstc); - } - -+static void qca8084_remove(struct phy_device *phydev) -+{ -+ if (phy_package_remove_once(phydev)) -+ qca8084_phy_package_remove_once(phydev); -+} -+ - static struct phy_driver qca808x_driver[] = { - { - /* Qualcomm QCA8081 */ -@@ -1167,6 +1219,7 @@ static struct phy_driver qca808x_driver[ - .config_init = qca8084_config_init, - .link_change_notify = qca8084_link_change_notify, - .probe = qca8084_probe, -+ .remove = qca8084_remove, - }, }; - - module_phy_driver(qca808x_driver); diff --git a/target/linux/qualcommbe/patches-6.12/0372-net-phy-qca808x-Add-QCA8084-SerDes-init-function.patch b/target/linux/qualcommbe/patches-6.12/0372-net-phy-qca808x-Add-QCA8084-SerDes-init-function.patch deleted file mode 100644 index 688d7ac474..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0372-net-phy-qca808x-Add-QCA8084-SerDes-init-function.patch +++ /dev/null @@ -1,446 +0,0 @@ -From d137b725f8f4a7d49a809dcd73c5b836495ec44d Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Mon, 23 Sep 2024 20:59:40 +0800 -Subject: [PATCH] net: phy: qca808x: Add QCA8084 SerDes init function - -When QCA8084 works on 10G-QXGMII, the XPCS and PCS need to be -configured in the PHY package init function. - -Change-Id: Iac48c44f0e80adf055fa9c2095e99a04ba24c4bb -Signed-off-by: Luo Jie ---- - drivers/net/phy/qcom/qca8084_serdes.c | 374 ++++++++++++++++++++++++++ - drivers/net/phy/qcom/qca8084_serdes.h | 2 + - drivers/net/phy/qcom/qca808x.c | 11 + - 3 files changed, 387 insertions(+) - ---- a/drivers/net/phy/qcom/qca8084_serdes.c -+++ b/drivers/net/phy/qcom/qca8084_serdes.c -@@ -24,6 +24,92 @@ - */ - #define QCA8084_CHANNEL_MAX 4 - -+/* MII registers */ -+#define PLL_POWER_ON_AND_RESET 0x0 -+#define PCS_ANA_SW_RESET BIT(6) -+ -+#define PLL_CONTROL 6 -+#define PLL_CONTROL_CMLDIV2_IBSEL_MASK GENMASK(5, 4) -+ -+/* MMD_PMAPMD registers */ -+#define CDR_CONTRL 0x20 -+#define SSC_FIX_MODE BIT(3) -+ -+#define CALIBRATION4 0x78 -+#define CALIBRATION_DONE BIT(7) -+ -+#define MODE_CONTROL 0x11b -+#define MODE_CONTROL_SEL_MASK GENMASK(12, 8) -+#define MODE_CONTROL_XPCS 0x10 -+#define MODE_CONTROL_SGMII_PLUS 0x8 -+#define MODE_CONTROL_SGMII 0x4 -+#define MODE_CONTROL_SGMII_SEL_MASK GENMASK(6, 4) -+#define MODE_CONTROL_SGMII_PHY 1 -+#define MODE_CONTROL_SGMII_MAC 2 -+ -+#define QP_USXG_OPTION1 0x180 -+#define QP_USXG_OPTION1_DATAPASS BIT(0) -+#define QP_USXG_OPTION1_DATAPASS_SGMII 0 -+#define QP_USXG_OPTION1_DATAPASS_USXGMII 1 -+ -+#define BYPASS_TUNNING_IPG 0x189 -+#define BYPASS_TUNNING_IPG_MASK GENMASK(11, 0) -+ -+/* MDIO_MMD_PCS register */ -+#define PCS_CONTROL2 0x7 -+#define PCS_TYPE_MASK GENMASK(3, 0) -+#define PCS_TYPE_BASER 0 -+ -+#define PCS_EEE_CONTROL 0x14 -+#define EEE_CAPABILITY BIT(6) -+ -+#define PCS_STATUS1 0x20 -+#define PCS_BASER_UP BIT(12) -+ -+#define DIG_CTRL1 0x8000 -+#define DIG_CTRL1_USXGMII_EN BIT(9) -+#define DIG_CTRL1_XPCS_RESET BIT(15) -+#define FIFO_RESET_CH0 BIT(10) -+#define FIFO_RESET_CH1_CH2_CH3 BIT(5) -+ -+#define EEE_MODE_CONTROL 0x8006 -+#define EEE_LCT_RES GENMASK(11, 8) -+#define EEE_SIGN BIT(6) -+#define EEE_LRX_EN BIT(1) -+#define EEE_LTX_EN BIT(0) -+ -+#define PCS_TPC 0x8007 -+#define PCS_QXGMII_MODE_MASK GENMASK(12, 10) -+#define PCS_QXGMII_EN 0x5 -+ -+#define EEE_RX_TIMER 0x8009 -+#define EEE_RX_TIMER_100US_RES GENMASK(7, 0) -+#define EEE_RX_TIMER_RWR_RES GENMASK(12, 8) -+ -+#define AM_LINK_TIMER 0x800a -+#define AM_LINK_TIMER_VAL 0x6018 -+ -+#define EEE_MODE_CONTROL1 0x800b -+#define TRANS_LPI_MODE BIT(0) -+#define TRANS_RX_LPI_MODE BIT(8) -+ -+/* QXGMII channel MMD register */ -+#define MII_CONTROL 0x0 -+#define AUTO_NEGOTIATION_EN BIT(12) -+#define AUTO_NEGOTIATION_RESTART BIT(9) -+#define PCS_SPEED_2500 BIT(5) -+#define PCS_SPEED_1000 BIT(6) -+#define PCS_SPEED_100 BIT(13) -+#define PCS_SPEED_10 0 -+ -+#define DIG_CONTROL2 0x8001 -+#define MII_BIT_CONTROL BIT(8) -+#define TX_CONFIG BIT(3) -+#define AUTO_NEGOTIATION_CMPLT_INTR BIT(0) -+ -+#define XAUI_CONTROL 0x8004 -+#define TX_IPG_CHECK_DISABLE BIT(0) -+ - enum pcs_clk_id { - PCS_CLK, - PCS_RX_ROOT_CLK, -@@ -76,6 +162,8 @@ static const char *const pcs_clock_names - [PCS_TX_ROOT_CLK] = "pcs_tx_root", - }; - -+static const int qca8084_xpcs_ch_mmd[QCA8084_CHANNEL_MAX] = { 31, 26, 27, 28 }; -+ - struct mdio_device *qca8084_package_pcs_probe(struct device_node *pcs_np) - { - struct qca8084_pcs_data *pcs_data; -@@ -247,3 +335,289 @@ void qca8084_package_xpcs_and_pcs_remove - mdio_device_put(xpcs_mdiodev); - mdio_device_put(pcs_mdiodev); - } -+ -+static int qca8084_pcs_set_interface_mode(struct mdio_device *mdio_dev, -+ phy_interface_t ifmode) -+{ -+ int ret, hw_ifmode, data; -+ -+ switch (ifmode) { -+ case PHY_INTERFACE_MODE_SGMII: -+ hw_ifmode = MODE_CONTROL_SGMII; -+ data = QP_USXG_OPTION1_DATAPASS_SGMII; -+ break; -+ case PHY_INTERFACE_MODE_2500BASEX: -+ hw_ifmode = MODE_CONTROL_SGMII_PLUS; -+ data = QP_USXG_OPTION1_DATAPASS_SGMII; -+ break; -+ case PHY_INTERFACE_MODE_10G_QXGMII: -+ hw_ifmode = MODE_CONTROL_XPCS; -+ data = QP_USXG_OPTION1_DATAPASS_USXGMII; -+ break; -+ default: -+ return -EOPNOTSUPP; -+ } -+ -+ /* For PLL stable under high temperature */ -+ ret = mdiodev_modify(mdio_dev, PLL_CONTROL, -+ PLL_CONTROL_CMLDIV2_IBSEL_MASK, -+ FIELD_PREP(PLL_CONTROL_CMLDIV2_IBSEL_MASK, 3)); -+ if (ret) -+ return ret; -+ -+ /* Configure the interface mode of PCS */ -+ ret = mdiodev_c45_modify(mdio_dev, MDIO_MMD_PMAPMD, MODE_CONTROL, -+ MODE_CONTROL_SEL_MASK, -+ FIELD_PREP(MODE_CONTROL_SEL_MASK, hw_ifmode)); -+ if (ret) -+ return ret; -+ -+ /* Data pass selects SGMII or USXGMII */ -+ return mdiodev_c45_modify(mdio_dev, MDIO_MMD_PMAPMD, QP_USXG_OPTION1, -+ QP_USXG_OPTION1_DATAPASS, -+ FIELD_PREP(QP_USXG_OPTION1_DATAPASS, data)); -+} -+ -+static int qca8084_do_calibration(struct mdio_device *mdio_dev) -+{ -+ int ret; -+ -+ ret = mdiodev_modify(mdio_dev, PLL_POWER_ON_AND_RESET, -+ PCS_ANA_SW_RESET, 0); -+ if (ret) -+ return ret; -+ -+ usleep_range(10000, 11000); -+ ret = mdiodev_modify(mdio_dev, PLL_POWER_ON_AND_RESET, -+ PCS_ANA_SW_RESET, PCS_ANA_SW_RESET); -+ if (ret) -+ return ret; -+ -+ /* Wait calibration done */ -+ return read_poll_timeout(mdiodev_c45_read, ret, -+ (ret & CALIBRATION_DONE), -+ 100, 100000, true, mdio_dev, -+ MDIO_MMD_PMAPMD, CALIBRATION4); -+} -+ -+ -+static int qca8084_xpcs_set_mode(struct mdio_device *xpcs_mdiodev) -+{ -+ int ret, val, i; -+ -+ /* Configure BaseR mode */ -+ ret = mdiodev_c45_modify(xpcs_mdiodev, MDIO_MMD_PCS, PCS_CONTROL2, -+ PCS_TYPE_MASK, -+ FIELD_PREP(PCS_TYPE_MASK, PCS_TYPE_BASER)); -+ if (ret) -+ return ret; -+ -+ /* Wait BaseR link up */ -+ ret = read_poll_timeout(mdiodev_c45_read, val, -+ (val & PCS_BASER_UP), 1000, 100000, true, -+ xpcs_mdiodev, -+ MDIO_MMD_PCS, PCS_STATUS1); -+ if (ret) { -+ dev_err(&xpcs_mdiodev->dev, "BaseR link failed!\n"); -+ return ret; -+ } -+ -+ /* Enable USXGMII mode */ -+ ret = mdiodev_c45_modify(xpcs_mdiodev, MDIO_MMD_PCS, DIG_CTRL1, -+ DIG_CTRL1_USXGMII_EN, -+ DIG_CTRL1_USXGMII_EN); -+ if (ret) -+ return ret; -+ -+ /* Configure QXGMII mode */ -+ ret = mdiodev_c45_modify(xpcs_mdiodev, MDIO_MMD_PCS, PCS_TPC, -+ PCS_QXGMII_MODE_MASK, -+ FIELD_PREP(PCS_QXGMII_MODE_MASK, -+ PCS_QXGMII_EN)); -+ if (ret) -+ return ret; -+ -+ /* Configure AM interval */ -+ ret = mdiodev_c45_write(xpcs_mdiodev, MDIO_MMD_PCS, AM_LINK_TIMER, -+ AM_LINK_TIMER_VAL); -+ if (ret) -+ return ret; -+ -+ /* Reset XPCS */ -+ ret = mdiodev_c45_modify(xpcs_mdiodev, MDIO_MMD_PCS, DIG_CTRL1, -+ DIG_CTRL1_XPCS_RESET, -+ DIG_CTRL1_XPCS_RESET); -+ if (ret) -+ return ret; -+ -+ /* Wait XPCS reset done */ -+ ret = read_poll_timeout(mdiodev_c45_read, val, -+ !(val & DIG_CTRL1_XPCS_RESET), -+ 1000, 100000, true, xpcs_mdiodev, -+ MDIO_MMD_PCS, DIG_CTRL1); -+ if (ret) { -+ dev_err(&xpcs_mdiodev->dev, "XPCS reset failed!\n"); -+ return ret; -+ } -+ -+ /* Enable auto-negotiation complete interrupt, using mii-4bit -+ * and TX configureation of PHY side on all XPCS channels. -+ */ -+ for (i = 0; i < QCA8084_CHANNEL_MAX; i++) { -+ ret = mdiodev_c45_modify(xpcs_mdiodev, qca8084_xpcs_ch_mmd[i], -+ DIG_CONTROL2, -+ (MII_BIT_CONTROL | TX_CONFIG | -+ AUTO_NEGOTIATION_CMPLT_INTR), -+ (TX_CONFIG | AUTO_NEGOTIATION_CMPLT_INTR)); -+ if (ret) -+ return ret; -+ -+ /* Enable auto-negotiation capability */ -+ ret = mdiodev_c45_modify(xpcs_mdiodev, qca8084_xpcs_ch_mmd[i], -+ MII_CONTROL, -+ AUTO_NEGOTIATION_EN, -+ AUTO_NEGOTIATION_EN); -+ if (ret) -+ return ret; -+ -+ /* Disable TX IPG check */ -+ ret = mdiodev_c45_modify(xpcs_mdiodev, qca8084_xpcs_ch_mmd[i], -+ XAUI_CONTROL, -+ TX_IPG_CHECK_DISABLE, -+ TX_IPG_CHECK_DISABLE); -+ if (ret) -+ return ret; -+ } -+ -+ /* Check EEE capability supported or not */ -+ ret = mdiodev_c45_read(xpcs_mdiodev, MDIO_MMD_PCS, PCS_EEE_CONTROL); -+ if (ret < 0) -+ return ret; -+ -+ if (ret & EEE_CAPABILITY) { -+ ret = mdiodev_c45_modify(xpcs_mdiodev, MDIO_MMD_PCS, -+ EEE_MODE_CONTROL, -+ EEE_LCT_RES | EEE_SIGN, -+ FIELD_PREP(EEE_LCT_RES, 1) | EEE_SIGN); -+ if (ret) -+ return ret; -+ -+ ret = mdiodev_c45_modify(xpcs_mdiodev, MDIO_MMD_PCS, -+ EEE_RX_TIMER, -+ EEE_RX_TIMER_100US_RES | EEE_RX_TIMER_RWR_RES, -+ FIELD_PREP(EEE_RX_TIMER_100US_RES, 0xc8) | -+ FIELD_PREP(EEE_RX_TIMER_RWR_RES, 0x1c)); -+ if (ret) -+ return ret; -+ -+ /* Enable EEE LPI */ -+ ret = mdiodev_c45_modify(xpcs_mdiodev, MDIO_MMD_PCS, -+ EEE_MODE_CONTROL1, -+ TRANS_LPI_MODE | TRANS_RX_LPI_MODE, -+ TRANS_LPI_MODE | TRANS_RX_LPI_MODE); -+ if (ret) -+ return ret; -+ -+ /* Enable TX/RX LPI pattern */ -+ ret = mdiodev_c45_modify(xpcs_mdiodev, MDIO_MMD_PCS, -+ EEE_MODE_CONTROL, -+ EEE_LRX_EN | EEE_LTX_EN, -+ EEE_LRX_EN | EEE_LTX_EN); -+ } -+ -+ return ret; -+} -+ -+static int qca8084_pcs_set_mode(struct mdio_device *xpcs_mdiodev, -+ struct mdio_device *pcs_mdiodev) -+{ -+ struct qca8084_xpcs_data *xpcs_data = mdiodev_get_drvdata(xpcs_mdiodev); -+ struct qca8084_pcs_data *pcs_data = mdiodev_get_drvdata(pcs_mdiodev); -+ struct qca8084_xpcs_channel_priv xpcs_ch; -+ int ret, channel; -+ -+ /* Enable clock and de-assert for PCS. */ -+ ret = clk_prepare_enable(pcs_data->clks[PCS_CLK]); -+ if (ret) -+ return ret; -+ -+ ret = reset_control_deassert(pcs_data->rstc); -+ if (ret) -+ return ret; -+ -+ /* IPG tunning selection for RX, TX and XGMII of all channels. */ -+ ret = mdiodev_c45_modify(pcs_mdiodev, MDIO_MMD_PMAPMD, -+ BYPASS_TUNNING_IPG, -+ BYPASS_TUNNING_IPG_MASK, 0); -+ if (ret) -+ return ret; -+ -+ reset_control_assert(xpcs_data->rstc); -+ -+ ret = qca8084_pcs_set_interface_mode(pcs_mdiodev, -+ PHY_INTERFACE_MODE_10G_QXGMII); -+ if (ret) -+ return ret; -+ -+ /* Reset of 4 channels */ -+ for (channel = 0; channel < QCA8084_CHANNEL_MAX; channel++) { -+ xpcs_ch = xpcs_data->xpcs_ch[channel]; -+ ret = reset_control_reset(xpcs_ch.rstcs); -+ if (ret) -+ return ret; -+ } -+ -+ ret = qca8084_do_calibration(pcs_mdiodev); -+ if (ret) { -+ dev_err(&pcs_mdiodev->dev, "PCS calibration timeout!\n"); -+ return ret; -+ } -+ -+ /* Enable PCS SSC to fix mode */ -+ ret = mdiodev_c45_modify(pcs_mdiodev, MDIO_MMD_PMAPMD, -+ CDR_CONTRL, SSC_FIX_MODE, SSC_FIX_MODE); -+ if (ret) -+ return ret; -+ -+ return reset_control_deassert(xpcs_data->rstc); -+} -+ -+static int qca8084_xpcs_clock_parent_set(struct mdio_device *xpcs_mdiodev, -+ struct mdio_device *pcs_mdiodev) -+{ -+ struct qca8084_xpcs_data *xpcs_data = mdiodev_get_drvdata(xpcs_mdiodev); -+ struct qca8084_pcs_data *pcs_data = mdiodev_get_drvdata(pcs_mdiodev); -+ struct qca8084_xpcs_channel_priv xpcs_ch; -+ int ret, channel; -+ -+ for (channel = 0; channel < QCA8084_CHANNEL_MAX; channel++) { -+ xpcs_ch = xpcs_data->xpcs_ch[channel]; -+ ret = clk_set_parent(xpcs_ch.clks[XPCS_RX_SRC_CLK], -+ pcs_data->clks[PCS_RX_ROOT_CLK]); -+ if (ret) -+ return ret; -+ -+ ret = clk_set_parent(xpcs_ch.clks[XPCS_TX_SRC_CLK], -+ pcs_data->clks[PCS_TX_ROOT_CLK]); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+int qca8084_qxgmii_set_mode(struct mdio_device *xpcs_mdiodev, -+ struct mdio_device *pcs_mdiodev) -+{ -+ int ret; -+ -+ ret = qca8084_xpcs_clock_parent_set(xpcs_mdiodev, pcs_mdiodev); -+ if (ret) -+ return ret; -+ -+ ret = qca8084_pcs_set_mode(xpcs_mdiodev, pcs_mdiodev); -+ if (ret) -+ return ret; -+ -+ return qca8084_xpcs_set_mode(xpcs_mdiodev); -+} ---- a/drivers/net/phy/qcom/qca8084_serdes.h -+++ b/drivers/net/phy/qcom/qca8084_serdes.h -@@ -15,4 +15,6 @@ struct mdio_device *qca8084_package_pcs_ - struct mdio_device *qca8084_package_xpcs_probe(struct device_node *xpcs_np); - void qca8084_package_xpcs_and_pcs_remove(struct mdio_device *xpcs_mdiodev, - struct mdio_device *pcs_mdiodev); -+int qca8084_qxgmii_set_mode(struct mdio_device *xpcs_mdiodev, -+ struct mdio_device *pcs_mdiodev); - #endif /* _QCA8084_SERDES_H_ */ ---- a/drivers/net/phy/qcom/qca808x.c -+++ b/drivers/net/phy/qcom/qca808x.c -@@ -926,6 +926,14 @@ static int qca8084_phy_package_config_in - - usleep_range(10000, 11000); - -+ /* Configure PCS working on 10G-QXGMII mode */ -+ if (phydev->interface == PHY_INTERFACE_MODE_10G_QXGMII) { -+ ret = qca8084_qxgmii_set_mode(shared_priv->mdiodev[1], -+ shared_priv->mdiodev[0]); -+ if (ret) -+ return ret; -+ } -+ - /* Initialize the PHY package clock and reset, which is the - * necessary config sequence after GPIO reset on the PHY package. - */ -@@ -1164,6 +1172,9 @@ static int qca8084_probe(struct phy_devi - - static void qca8084_remove(struct phy_device *phydev) - { -+ if (phydev->interface != PHY_INTERFACE_MODE_10G_QXGMII) -+ return; -+ - if (phy_package_remove_once(phydev)) - qca8084_phy_package_remove_once(phydev); - } diff --git a/target/linux/qualcommbe/patches-6.12/0373-net-phy-qca808x-Add-QCA8084-SerDes-speed-config.patch b/target/linux/qualcommbe/patches-6.12/0373-net-phy-qca808x-Add-QCA8084-SerDes-speed-config.patch deleted file mode 100644 index 1244837fd5..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0373-net-phy-qca808x-Add-QCA8084-SerDes-speed-config.patch +++ /dev/null @@ -1,251 +0,0 @@ -From 2f5b7e167d847a5b5b74a91f991d48635453c55f Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Mon, 23 Sep 2024 21:24:56 +0800 -Subject: [PATCH] net: phy: qca808x: Add QCA8084 SerDes speed config - -When the link of PHY is changed, the XPCS channel needs to be -configured to adapt the current link status. - -Change-Id: I50d8973691dff133fc6bec1e9a1043bb646811fc -Signed-off-by: Luo Jie -Alex G: Use phy_package_get_*() accessors -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/phy/qcom/qca8084_serdes.c | 159 ++++++++++++++++++++++++++ - drivers/net/phy/qcom/qca8084_serdes.h | 3 + - drivers/net/phy/qcom/qca808x.c | 15 ++- - 3 files changed, 175 insertions(+), 2 deletions(-) - ---- a/drivers/net/phy/qcom/qca8084_serdes.c -+++ b/drivers/net/phy/qcom/qca8084_serdes.c -@@ -4,6 +4,7 @@ - */ - - #include -+#include - #include - #include - #include -@@ -55,6 +56,13 @@ - #define BYPASS_TUNNING_IPG 0x189 - #define BYPASS_TUNNING_IPG_MASK GENMASK(11, 0) - -+#define QP_USXG_RESET 0x18c -+#define QP_USXG_SGMII_FUNC_RESET BIT(4) -+#define QP_USXG_P3_FUNC_RESET BIT(3) -+#define QP_USXG_P2_FUNC_RESET BIT(2) -+#define QP_USXG_P1_FUNC_RESET BIT(1) -+#define QP_USXG_P0_FUNC_RESET BIT(0) -+ - /* MDIO_MMD_PCS register */ - #define PCS_CONTROL2 0x7 - #define PCS_TYPE_MASK GENMASK(3, 0) -@@ -107,6 +115,9 @@ - #define TX_CONFIG BIT(3) - #define AUTO_NEGOTIATION_CMPLT_INTR BIT(0) - -+#define PCS_ERR_SEL 0x8002 -+#define PCS_AN_COMPLETE BIT(0) -+ - #define XAUI_CONTROL 0x8004 - #define TX_IPG_CHECK_DISABLE BIT(0) - -@@ -621,3 +632,151 @@ int qca8084_qxgmii_set_mode(struct mdio_ - - return qca8084_xpcs_set_mode(xpcs_mdiodev); - } -+ -+static int qca8084_pcs_ipg_tune_reset(struct mdio_device *mdio_dev, -+ int reset_function) -+{ -+ int ret; -+ -+ ret = mdiodev_c45_modify(mdio_dev, MDIO_MMD_PMAPMD, QP_USXG_RESET, -+ reset_function, 0); -+ if (ret) -+ return ret; -+ -+ usleep_range(1000, 1100); -+ -+ return mdiodev_c45_modify(mdio_dev, MDIO_MMD_PMAPMD, QP_USXG_RESET, -+ reset_function, reset_function); -+} -+ -+static int qca8084_xpcs_an_restart(struct mdio_device *xpcs_mdiodev, -+ int channel) -+{ -+ int ret, mmd; -+ -+ mmd = qca8084_xpcs_ch_mmd[channel]; -+ -+ /* Restart auto-negotiation */ -+ ret = mdiodev_c45_modify(xpcs_mdiodev, mmd, MII_CONTROL, -+ AUTO_NEGOTIATION_RESTART, -+ AUTO_NEGOTIATION_RESTART); -+ if (ret) -+ return ret; -+ -+ usleep_range(1000, 1100); -+ -+ /* Clear pcs auto-negotiation complete interrupt */ -+ return mdiodev_c45_modify(xpcs_mdiodev, mmd, PCS_ERR_SEL, -+ PCS_AN_COMPLETE, 0); -+} -+ -+void qca8084_qxgmii_set_speed(struct mdio_device *xpcs_mdiodev, -+ struct mdio_device *pcs_mdiodev, -+ int channel, int speed) -+{ -+ struct qca8084_xpcs_data *xpcs_data = mdiodev_get_drvdata(xpcs_mdiodev); -+ struct qca8084_xpcs_channel_priv *xpcs_ch; -+ int mmd, i, ret, xpcs_rate; -+ unsigned long rate; -+ -+ for (i = 0; i < QCA8084_CHANNEL_MAX; i++) { -+ xpcs_ch = &(xpcs_data->xpcs_ch[channel]); -+ if (channel == xpcs_ch->ch_id) -+ break; -+ } -+ -+ if (i == QCA8084_CHANNEL_MAX) { -+ dev_err(&xpcs_mdiodev->dev, "Invalid channel %d\n", channel); -+ return; -+ } -+ -+ mmd = qca8084_xpcs_ch_mmd[channel]; -+ -+ ret = qca8084_xpcs_an_restart(xpcs_mdiodev, channel); -+ if (ret) -+ return; -+ -+ switch (speed) { -+ case SPEED_2500: -+ rate = 312500000; -+ xpcs_rate = PCS_SPEED_2500; -+ break; -+ case SPEED_1000: -+ rate = 125000000; -+ xpcs_rate = PCS_SPEED_1000; -+ break; -+ case SPEED_100: -+ rate = 25000000; -+ xpcs_rate = PCS_SPEED_100; -+ break; -+ case SPEED_10: -+ default: -+ rate = 2500000; -+ xpcs_rate = PCS_SPEED_10; -+ break; -+ } -+ -+ clk_set_rate(xpcs_ch->clks[XPCS_RX_CLK], rate); -+ clk_set_rate(xpcs_ch->clks[XPCS_TX_CLK], rate); -+ -+ /* XGMII takes the different clock rate 78.125Mhz from XPCS clock -+ * when linked at 2500M. -+ */ -+ if (speed == SPEED_2500) -+ rate = 78125000; -+ -+ clk_set_rate(xpcs_ch->clks[XPCS_XGMII_RX_CLK], rate); -+ clk_set_rate(xpcs_ch->clks[XPCS_XGMII_TX_CLK], rate); -+ -+ ret = mdiodev_c45_modify(xpcs_mdiodev, mmd, MII_CONTROL, -+ PCS_SPEED_2500 | PCS_SPEED_1000 | -+ PCS_SPEED_100 | PCS_SPEED_10, -+ xpcs_rate); -+ if (ret) -+ return; -+ -+ /* Disable clocks if link down with unknown speed. The channel clocks -+ * are disabled by default, __clk_is_enabled() is used to avoid -+ * disabling the clocks that is already in the disabled status. -+ */ -+ if (speed == SPEED_UNKNOWN) { -+ if (__clk_is_enabled(xpcs_ch->clks[XPCS_RX_CLK])) -+ clk_disable_unprepare(xpcs_ch->clks[XPCS_RX_CLK]); -+ if (__clk_is_enabled(xpcs_ch->clks[XPCS_TX_CLK])) -+ clk_disable_unprepare(xpcs_ch->clks[XPCS_TX_CLK]); -+ if (__clk_is_enabled(xpcs_ch->clks[XPCS_PORT_RX_CLK])) -+ clk_disable_unprepare(xpcs_ch->clks[XPCS_PORT_RX_CLK]); -+ if (__clk_is_enabled(xpcs_ch->clks[XPCS_PORT_TX_CLK])) -+ clk_disable_unprepare(xpcs_ch->clks[XPCS_PORT_TX_CLK]); -+ if (__clk_is_enabled(xpcs_ch->clks[XPCS_XGMII_RX_CLK])) -+ clk_disable_unprepare(xpcs_ch->clks[XPCS_XGMII_RX_CLK]); -+ if (__clk_is_enabled(xpcs_ch->clks[XPCS_XGMII_TX_CLK])) -+ clk_disable_unprepare(xpcs_ch->clks[XPCS_XGMII_TX_CLK]); -+ } else { -+ clk_prepare_enable(xpcs_ch->clks[XPCS_RX_CLK]); -+ clk_prepare_enable(xpcs_ch->clks[XPCS_TX_CLK]); -+ clk_prepare_enable(xpcs_ch->clks[XPCS_PORT_RX_CLK]); -+ clk_prepare_enable(xpcs_ch->clks[XPCS_PORT_TX_CLK]); -+ clk_prepare_enable(xpcs_ch->clks[XPCS_XGMII_RX_CLK]); -+ clk_prepare_enable(xpcs_ch->clks[XPCS_XGMII_TX_CLK]); -+ } -+ -+ msleep(100); -+ -+ ret = reset_control_reset(xpcs_ch->rstcs); -+ if (ret) -+ return; -+ -+ /* Reset IPG tune of PCS device. */ -+ ret = qca8084_pcs_ipg_tune_reset(pcs_mdiodev, BIT(channel)); -+ if (ret) -+ return; -+ -+ if (channel == 0) -+ mdiodev_c45_modify(xpcs_mdiodev, MDIO_MMD_PCS, DIG_CTRL1, -+ FIFO_RESET_CH0, FIFO_RESET_CH0); -+ else -+ mdiodev_c45_modify(xpcs_mdiodev, mmd, DIG_CTRL1, -+ FIFO_RESET_CH1_CH2_CH3, -+ FIFO_RESET_CH1_CH2_CH3); -+} ---- a/drivers/net/phy/qcom/qca8084_serdes.h -+++ b/drivers/net/phy/qcom/qca8084_serdes.h -@@ -17,4 +17,7 @@ void qca8084_package_xpcs_and_pcs_remove - struct mdio_device *pcs_mdiodev); - int qca8084_qxgmii_set_mode(struct mdio_device *xpcs_mdiodev, - struct mdio_device *pcs_mdiodev); -+void qca8084_qxgmii_set_speed(struct mdio_device *xpcs_mdiodev, -+ struct mdio_device *pcs_mdiodev, -+ int channel, int speed); - #endif /* _QCA8084_SERDES_H_ */ ---- a/drivers/net/phy/qcom/qca808x.c -+++ b/drivers/net/phy/qcom/qca808x.c -@@ -976,6 +976,7 @@ static int qca8084_config_init(struct ph - - static void qca8084_link_change_notify(struct phy_device *phydev) - { -+ struct qca808x_shared_priv *shared_priv; - int ret; - - /* Assert the FIFO between PHY and MAC. */ -@@ -1007,14 +1008,24 @@ static void qca8084_link_change_notify(s - } - } - -- /* Enable IPG level 10 to 11 tuning for link speed 1000M in the -+ /* Enable IPG level 10 to 11 tuning for link speed 1000M and -+ * configure the related XPCS channel with the phydev in the - * 10G_QXGMII mode. - */ -- if (phydev->interface == PHY_INTERFACE_MODE_10G_QXGMII) -+ if (phydev->interface == PHY_INTERFACE_MODE_10G_QXGMII) { -+ shared_priv = phy_package_get_priv(phydev); -+ struct qca808x_priv *priv = phydev->priv; -+ - phy_modify_mmd(phydev, MDIO_MMD_AN, QCA8084_MMD7_IPG_OP, - QCA8084_IPG_10_TO_11_EN, - phydev->speed == SPEED_1000 ? - QCA8084_IPG_10_TO_11_EN : 0); -+ -+ qca8084_qxgmii_set_speed(shared_priv->mdiodev[1], -+ shared_priv->mdiodev[0], -+ priv->channel_id, -+ phydev->speed); -+ } - } - - /* QCA8084 is a four-port PHY, which integrates the clock controller, diff --git a/target/linux/qualcommbe/patches-6.12/0374-dt-bindings-pwm-add-IPQ6018-binding.patch b/target/linux/qualcommbe/patches-6.12/0374-dt-bindings-pwm-add-IPQ6018-binding.patch deleted file mode 100644 index 07a64a0f61..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0374-dt-bindings-pwm-add-IPQ6018-binding.patch +++ /dev/null @@ -1,181 +0,0 @@ -From patchwork Fri Nov 28 10:29:13 2025 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: George Moussalem via B4 Relay - -X-Patchwork-Id: 2169931 -Return-Path: - -X-Original-To: incoming@patchwork.ozlabs.org -Delivered-To: patchwork-incoming@legolas.ozlabs.org -Authentication-Results: legolas.ozlabs.org; - dkim=pass (2048-bit key; - unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 - header.s=k20201202 header.b=qU845OFh; - dkim-atps=neutral -Authentication-Results: legolas.ozlabs.org; - spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org - (client-ip=213.196.21.55; helo=ams.mirrors.kernel.org; - envelope-from=linux-pwm+bounces-7721-incoming=patchwork.ozlabs.org@vger.kernel.org; - receiver=patchwork.ozlabs.org) -Received: from ams.mirrors.kernel.org (ams.mirrors.kernel.org [213.196.21.55]) - (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) - key-exchange X25519 server-signature ECDSA (secp384r1)) - (No client certificate requested) - by legolas.ozlabs.org (Postfix) with ESMTPS id 4dHqMJ5gXFz1yDj - for ; Fri, 28 Nov 2025 21:30:52 +1100 (AEDT) -Received: from smtp.subspace.kernel.org (relay.kernel.org [52.25.139.140]) - (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) - (No client certificate requested) - by ams.mirrors.kernel.org (Postfix) with ESMTPS id 0783B352ED3 - for ; Fri, 28 Nov 2025 10:29:38 +0000 (UTC) -Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) - by smtp.subspace.kernel.org (Postfix) with ESMTP id 5B94630C370; - Fri, 28 Nov 2025 10:29:23 +0000 (UTC) -Authentication-Results: smtp.subspace.kernel.org; - dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org - header.b="qU845OFh" -X-Original-To: linux-pwm@vger.kernel.org -Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org - [10.30.226.201]) - (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) - (No client certificate requested) - by smtp.subspace.kernel.org (Postfix) with ESMTPS id 27F7930B525; - Fri, 28 Nov 2025 10:29:22 +0000 (UTC) -Authentication-Results: smtp.subspace.kernel.org; - arc=none smtp.client-ip=10.30.226.201 -ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; - t=1764325763; cv=none; - b=EZdjLPtvTBCzr24d6uks1u6xas9FiqaXRtClecDuZQfT8aKQnU9LDJSaswvWaMHcpRkbBujRZFntPyNohlI+P0vj+Zlmof30QOr4Cw61jr3wGlfQNPsH0ib1AuyADzOHFj1W0c+mfqIs2onOC15OGkIc+DWrCsNXePSM/0/0XQM= -ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; - s=arc-20240116; t=1764325763; c=relaxed/simple; - bh=fNS3C2NaCK+go2nQNBlkD9EyrNNHIb0CZcl2LNOQBmE=; - h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: - In-Reply-To:To:Cc; - b=iRh98acHGzMCOeqCHb4A30mpdpFjHp96ccf65E1oF0kaAGzHdhWM7H56NI22q+0GXrY7o91H7F+x1Dz1spr6OZc6bMG4DuV8oap/vEdtyjApt+7zNFUl0PcrMSLSe2YVFaWgVvk7/IenJxJhEqcPWhsFZR+HGM4iuhv2lP3w32c= -ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; - dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org - header.b=qU845OFh; arc=none smtp.client-ip=10.30.226.201 -Received: by smtp.kernel.org (Postfix) with ESMTPS id BDCD9C113D0; - Fri, 28 Nov 2025 10:29:22 +0000 (UTC) -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; - s=k20201202; t=1764325762; - bh=fNS3C2NaCK+go2nQNBlkD9EyrNNHIb0CZcl2LNOQBmE=; - h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; - b=qU845OFhU3cciT1imeWuTMro85tXusIJt99AroBlTX9t+aY8oZwFPjd4KhPNki2mi - gK5GyKlndlusCuuiAqnaaQahXFM6I16gAWHOaCMORh1VJ0Vdli6WOo66C/KlZBrRPN - 4x/+oieXIooU174yYf8PhFevu9NVbs1arlck6sgsyyW7HB0WwedreqFH2qfmTO4NyF - zDymUL0G9Og8hd89PsEyZkkDLVroKnvjU7POud+8el6a6PvDYUOmCTM/rsu2gJX64s - k9Nm5ZJmRWfQvaku8McARECvY/QLX3P+pweAuDyazDxpGgTTxPqMbyywNEBjfVYu+o - ksKwowwfTPqHg== -Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org - (localhost.localdomain [127.0.0.1]) - by smtp.lore.kernel.org (Postfix) with ESMTP id A0784D116EA; - Fri, 28 Nov 2025 10:29:22 +0000 (UTC) -From: George Moussalem via B4 Relay - -Date: Fri, 28 Nov 2025 14:29:13 +0400 -Subject: [PATCH v19 1/6] dt-bindings: pwm: add IPQ6018 binding -Precedence: bulk -X-Mailing-List: linux-pwm@vger.kernel.org -List-Id: -List-Subscribe: -List-Unsubscribe: -MIME-Version: 1.0 -Message-Id: <20251128-ipq-pwm-v19-1-13bc704cc6a5@outlook.com> -References: <20251128-ipq-pwm-v19-0-13bc704cc6a5@outlook.com> -In-Reply-To: <20251128-ipq-pwm-v19-0-13bc704cc6a5@outlook.com> -To: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , - Rob Herring , Krzysztof Kozlowski , - Conor Dooley , Baruch Siach , - Bjorn Andersson , - Konrad Dybcio -Cc: linux-arm-msm@vger.kernel.org, linux-pwm@vger.kernel.org, - devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, - George Moussalem , - Devi Priya , - Baruch Siach , - Bjorn Andersson , - Krzysztof Kozlowski -X-Mailer: b4 0.14.2 -X-Developer-Signature: v=1; a=ed25519-sha256; t=1764325760; l=2042; - i=george.moussalem@outlook.com; s=20250321; h=from:subject:message-id; - bh=8ayVJ9z0kZoRdShrug1dJ1pjUonk4k9SO1yJzG93fMg=; - b=o0lsJw1oX/jEPu9xLh+Ovt+AbJGXh3X8na0H8Ko0Vcl7PFsYQQEOP9HhJAp8Y5XyBFBcroa6x - AHFNonYE7aVArYgsi5KqkDnui4xwpKQpD5RwWJ3JFA96K5IALoApziu -X-Developer-Key: i=george.moussalem@outlook.com; a=ed25519; - pk=/PuRTSI9iYiHwcc6Nrde8qF4ZDhJBlUgpHdhsIjnqIk= -X-Endpoint-Received: by B4 Relay for george.moussalem@outlook.com/20250321 - with auth_id=364 -X-Original-From: George Moussalem -Reply-To: george.moussalem@outlook.com - -From: Devi Priya - -DT binding for the PWM block in Qualcomm IPQ6018 SoC. - -Reviewed-by: Bjorn Andersson -Reviewed-by: Krzysztof Kozlowski -Co-developed-by: Baruch Siach -Signed-off-by: Baruch Siach -Signed-off-by: Devi Priya -Signed-off-by: George Moussalem ---- - .../devicetree/bindings/pwm/qcom,ipq6018-pwm.yaml | 51 ++++++++++++++++++++++ - 1 file changed, 51 insertions(+) - ---- /dev/null -+++ b/Documentation/devicetree/bindings/pwm/qcom,ipq6018-pwm.yaml -@@ -0,0 +1,51 @@ -+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/pwm/qcom,ipq6018-pwm.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Qualcomm IPQ6018 PWM controller -+ -+maintainers: -+ - George Moussalem -+ -+properties: -+ compatible: -+ oneOf: -+ - items: -+ - enum: -+ - qcom,ipq5018-pwm -+ - qcom,ipq5332-pwm -+ - qcom,ipq9574-pwm -+ - const: qcom,ipq6018-pwm -+ - const: qcom,ipq6018-pwm -+ -+ reg: -+ maxItems: 1 -+ -+ clocks: -+ maxItems: 1 -+ -+ "#pwm-cells": -+ const: 3 -+ -+required: -+ - compatible -+ - reg -+ - clocks -+ - "#pwm-cells" -+ -+additionalProperties: false -+ -+examples: -+ - | -+ #include -+ -+ pwm: pwm@1941010 { -+ compatible = "qcom,ipq6018-pwm"; -+ reg = <0x01941010 0x20>; -+ clocks = <&gcc GCC_ADSS_PWM_CLK>; -+ assigned-clocks = <&gcc GCC_ADSS_PWM_CLK>; -+ assigned-clock-rates = <100000000>; -+ #pwm-cells = <3>; -+ }; diff --git a/target/linux/qualcommbe/patches-6.12/0375-pwm-driver-for-qualcomm-ipq6018-pwm-block.patch b/target/linux/qualcommbe/patches-6.12/0375-pwm-driver-for-qualcomm-ipq6018-pwm-block.patch deleted file mode 100644 index 670b360e98..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0375-pwm-driver-for-qualcomm-ipq6018-pwm-block.patch +++ /dev/null @@ -1,403 +0,0 @@ -From patchwork Wed Feb 4 11:25:08 2026 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: George Moussalem via B4 Relay - -X-Patchwork-Id: 2192910 -Return-Path: - -X-Original-To: incoming@patchwork.ozlabs.org -Delivered-To: patchwork-incoming@legolas.ozlabs.org -Authentication-Results: legolas.ozlabs.org; - dkim=pass (2048-bit key; - unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 - header.s=k20201202 header.b=WGUCMoYx; - dkim-atps=neutral -Authentication-Results: legolas.ozlabs.org; - spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org - (client-ip=172.105.105.114; helo=tor.lore.kernel.org; - envelope-from=linux-pwm+bounces-8087-incoming=patchwork.ozlabs.org@vger.kernel.org; - receiver=patchwork.ozlabs.org) -Received: from tor.lore.kernel.org (tor.lore.kernel.org [172.105.105.114]) - (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) - key-exchange x25519) - (No client certificate requested) - by legolas.ozlabs.org (Postfix) with ESMTPS id 4f5dMp0fDDz1xqf - for ; Wed, 04 Feb 2026 22:26:14 +1100 (AEDT) -Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org - [100.90.174.1]) - by tor.lore.kernel.org (Postfix) with ESMTP id EBABA301D322 - for ; Wed, 4 Feb 2026 11:25:18 +0000 (UTC) -Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) - by smtp.subspace.kernel.org (Postfix) with ESMTP id 498E93ECBC6; - Wed, 4 Feb 2026 11:25:14 +0000 (UTC) -Authentication-Results: smtp.subspace.kernel.org; - dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org - header.b="WGUCMoYx" -X-Original-To: linux-pwm@vger.kernel.org -Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org - [10.30.226.201]) - (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) - (No client certificate requested) - by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1653D3E9F8E; - Wed, 4 Feb 2026 11:25:14 +0000 (UTC) -Authentication-Results: smtp.subspace.kernel.org; - arc=none smtp.client-ip=10.30.226.201 -ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; - t=1770204314; cv=none; - b=G3d0Ri0xw7F/u2rUoaF2eprL1ihrTvDSfCszkp2ciK2Y+UB3YSBt1K9D5nrbQw3bG1mHFZSO34nH/NZUQUoP97w8cJNILcVALgdGNfpM1vdDsKcRjomVZOvJi5sTvm2qnS4gIzL5DhybGv6UMOPcMrPM4TyZjpnvnJyWo9twGXE= -ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; - s=arc-20240116; t=1770204314; c=relaxed/simple; - bh=DlyTmDysGY1XB33v65FxlGZh2bVxvGJcWBwNBttMHy4=; - h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: - In-Reply-To:To:Cc; - b=oscy1mdUqAhot2KYVVHi6uWkqWGm1fzDdZJUn82fx79nITsOMMaDBwep6Ra0KSpsxVMrI0KvqGJf5Aa68+YmcJpXOGKERtXl98pFEsTsnHR8ofyWZ5r2lR8Xiojdk3aCWuj3pkgi61p9TwpvAsXI4eZU0JoqNv2Ty8HO6hF2+cI= -ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; - dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org - header.b=WGUCMoYx; arc=none smtp.client-ip=10.30.226.201 -Received: by smtp.kernel.org (Postfix) with ESMTPS id C1097C2BCAF; - Wed, 4 Feb 2026 11:25:13 +0000 (UTC) -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; - s=k20201202; t=1770204313; - bh=DlyTmDysGY1XB33v65FxlGZh2bVxvGJcWBwNBttMHy4=; - h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; - b=WGUCMoYxqwybcHrn+vGBd5QHaN5JxKMe0VHNxaeZmtbFd0vYZ3BwJ8m5hAjyRZ0eD - 2JIVvL9CxJeb48YIWZL8Hp49Ofp7FboBk7Q31N1+sBMQOC74MJNfvnFS9aMDNmTwJc - /vWoridD8Vn4Nj7bwQyhMAkreL54siL8bGUwW32yihFKR1AztlfhSE8roX72luaGMc - ALHuZzPPpCZFC4ZQ55PvaDHDAdBAplA3bVN0hcawiL/9jlpNiFoFsNHNOSmYgbkxIH - KW9GymmfG5d9cinrJZ2EThR1WDiIs41hnH1ijcK7vMMG3L6LoXzyIrjZo973bSp+oB - H5T79DAQ5KXZA== -Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org - (localhost.localdomain [127.0.0.1]) - by smtp.lore.kernel.org (Postfix) with ESMTP id AABE3E95389; - Wed, 4 Feb 2026 11:25:13 +0000 (UTC) -From: George Moussalem via B4 Relay - -Date: Wed, 04 Feb 2026 15:25:08 +0400 -Subject: [PATCH v20 2/6] pwm: driver for qualcomm ipq6018 pwm block -Precedence: bulk -X-Mailing-List: linux-pwm@vger.kernel.org -List-Id: -List-Subscribe: -List-Unsubscribe: -MIME-Version: 1.0 -Message-Id: <20260204-ipq-pwm-v20-2-91733011a3d1@outlook.com> -References: <20260204-ipq-pwm-v20-0-91733011a3d1@outlook.com> -In-Reply-To: <20260204-ipq-pwm-v20-0-91733011a3d1@outlook.com> -To: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , - Rob Herring , Krzysztof Kozlowski , - Conor Dooley , Baruch Siach , - Bjorn Andersson , - Konrad Dybcio -Cc: linux-arm-msm@vger.kernel.org, linux-pwm@vger.kernel.org, - devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, - George Moussalem , - Devi Priya , - Baruch Siach -X-Mailer: b4 0.14.2 -X-Developer-Signature: v=1; a=ed25519-sha256; t=1770204310; l=9677; - i=george.moussalem@outlook.com; s=20250321; h=from:subject:message-id; - bh=lqVC0W9FHdaTi1eT81frsdr/MvrSo0xMFV72k7YrO7I=; - b=mcjrEkuzodOMpsOdLZkQ609EXbJZFxJ8sU8yRwppwYWMDGETj4y5NtRIMVLi7GxOiU0zqcWls - CZHLZJaNDRaCaTzN1DMBfmpBhwkY/Hu+GKk+Nh9uBfpU2UxvCU4SSmG -X-Developer-Key: i=george.moussalem@outlook.com; a=ed25519; - pk=/PuRTSI9iYiHwcc6Nrde8qF4ZDhJBlUgpHdhsIjnqIk= -X-Endpoint-Received: by B4 Relay for george.moussalem@outlook.com/20250321 - with auth_id=364 -X-Original-From: George Moussalem -Reply-To: george.moussalem@outlook.com - -From: Devi Priya - -Driver for the PWM block in Qualcomm IPQ6018 line of SoCs. Based on -driver from downstream Codeaurora kernel tree. Removed support for older -(V1) variants because I have no access to that hardware. - -Tested on IPQ5018 and IPQ6010 based hardware. - -Co-developed-by: Baruch Siach -Signed-off-by: Baruch Siach -Signed-off-by: Devi Priya -Reviewed-by: Bjorn Andersson -Signed-off-by: George Moussalem ---- ---- - drivers/pwm/Kconfig | 12 +++ - drivers/pwm/Makefile | 1 + - drivers/pwm/pwm-ipq.c | 239 ++++++++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 252 insertions(+) - ---- a/drivers/pwm/Kconfig -+++ b/drivers/pwm/Kconfig -@@ -319,6 +319,18 @@ config PWM_INTEL_LGM - To compile this driver as a module, choose M here: the module - will be called pwm-intel-lgm. - -+config PWM_IPQ -+ tristate "IPQ PWM support" -+ depends on ARCH_QCOM || COMPILE_TEST -+ depends on HAVE_CLK && HAS_IOMEM -+ help -+ Generic PWM framework driver for IPQ PWM block which supports -+ 4 pwm channels. Each of the these channels can be configured -+ independent of each other. -+ -+ To compile this driver as a module, choose M here: the module -+ will be called pwm-ipq. -+ - config PWM_IQS620A - tristate "Azoteq IQS620A PWM support" - depends on MFD_IQS62X || COMPILE_TEST ---- a/drivers/pwm/Makefile -+++ b/drivers/pwm/Makefile -@@ -27,6 +27,7 @@ obj-$(CONFIG_PWM_IMX1) += pwm-imx1.o - obj-$(CONFIG_PWM_IMX27) += pwm-imx27.o - obj-$(CONFIG_PWM_IMX_TPM) += pwm-imx-tpm.o - obj-$(CONFIG_PWM_INTEL_LGM) += pwm-intel-lgm.o -+obj-$(CONFIG_PWM_IPQ) += pwm-ipq.o - obj-$(CONFIG_PWM_IQS620A) += pwm-iqs620a.o - obj-$(CONFIG_PWM_JZ4740) += pwm-jz4740.o - obj-$(CONFIG_PWM_KEEMBAY) += pwm-keembay.o ---- /dev/null -+++ b/drivers/pwm/pwm-ipq.c -@@ -0,0 +1,239 @@ -+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 -+/* -+ * Copyright (c) 2016-2017, 2020 The Linux Foundation. All rights reserved. -+ * -+ * Hardware notes / Limitations: -+ * - The PWM controller has no publicly available datasheet. -+ * - Each of the four channels is programmed via two 32-bit registers -+ * (REG0 and REG1 at 8-byte stride). -+ * - Period and duty-cycle reconfiguration is fully atomic: new divider, -+ * pre-divider, and high-duration values are latched by setting the -+ * UPDATE bit (bit 30 in REG1). The hardware applies the new settings -+ * at the beginning of the next period without disabling the output, -+ * so the currently running period is always completed. -+ * - On disable (clearing the ENABLE bit 31 in REG1), the hardware -+ * finishes the current period before stopping the output. The pin -+ * is then driven to the inactive (low) level. -+ * - Upon disabling, the hardware resets the pre-divider (PRE_DIV) and divider -+ * fields (PWM_DIV) in REG0 and REG1 to 0x0000 and 0x0001 respectively. -+ * - Only normal polarity is supported. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* The frequency range supported is 1 Hz to clock rate */ -+#define IPQ_PWM_MAX_PERIOD_NS ((u64)NSEC_PER_SEC) -+ -+/* -+ * Two 32-bit registers for each PWM: REG0, and REG1. -+ * Base offset for PWM #i is at 8 * #i. -+ */ -+#define IPQ_PWM_REG0 0 -+#define IPQ_PWM_REG0_PWM_DIV GENMASK(15, 0) -+#define IPQ_PWM_REG0_HI_DURATION GENMASK(31, 16) -+ -+#define IPQ_PWM_REG1 4 -+#define IPQ_PWM_REG1_PRE_DIV GENMASK(15, 0) -+ -+/* -+ * The max value specified for each field is based on the number of bits -+ * in the pwm control register for that field (16-bit) -+ */ -+#define IPQ_PWM_MAX_DIV FIELD_MAX(IPQ_PWM_REG0_PWM_DIV) -+ -+/* -+ * Enable bit is set to enable output toggling in pwm device. -+ * Update bit is set to trigger the change and is unset automatically -+ * to reflect the changed divider and high duration values in register. -+ */ -+#define IPQ_PWM_REG1_UPDATE BIT(30) -+#define IPQ_PWM_REG1_ENABLE BIT(31) -+ -+struct ipq_pwm_chip { -+ void __iomem *mem; -+ unsigned long clk_rate; -+}; -+ -+static struct ipq_pwm_chip *ipq_pwm_from_chip(struct pwm_chip *chip) -+{ -+ return pwmchip_get_drvdata(chip); -+} -+ -+static unsigned int ipq_pwm_reg_read(struct pwm_device *pwm, unsigned int reg) -+{ -+ struct ipq_pwm_chip *ipq_chip = ipq_pwm_from_chip(pwm->chip); -+ unsigned int off = 8 * pwm->hwpwm + reg; -+ -+ return readl(ipq_chip->mem + off); -+} -+ -+static void ipq_pwm_reg_write(struct pwm_device *pwm, unsigned int reg, -+ unsigned int val) -+{ -+ struct ipq_pwm_chip *ipq_chip = ipq_pwm_from_chip(pwm->chip); -+ unsigned int off = 8 * pwm->hwpwm + reg; -+ -+ writel(val, ipq_chip->mem + off); -+} -+ -+static int ipq_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, -+ const struct pwm_state *state) -+{ -+ struct ipq_pwm_chip *ipq_chip = ipq_pwm_from_chip(chip); -+ unsigned int pre_div, pwm_div; -+ u64 period_ns, duty_ns; -+ unsigned long val = 0; -+ unsigned long hi_dur; -+ -+ if (state->polarity != PWM_POLARITY_NORMAL) -+ return -EINVAL; -+ -+ if (!ipq_chip->clk_rate) -+ return -EINVAL; -+ -+ if (state->period < DIV64_U64_ROUND_UP(NSEC_PER_SEC, -+ ipq_chip->clk_rate)) -+ return -ERANGE; -+ -+ period_ns = min(state->period, IPQ_PWM_MAX_PERIOD_NS); -+ duty_ns = min(state->duty_cycle, period_ns); -+ -+ pwm_div = IPQ_PWM_MAX_DIV - 1; -+ pre_div = mul_u64_u64_div_u64(period_ns, ipq_chip->clk_rate, -+ (u64)NSEC_PER_SEC * (pwm_div + 1)); -+ pre_div = (pre_div > 0) ? pre_div - 1 : 0; -+ -+ if (pre_div > IPQ_PWM_MAX_DIV) -+ pre_div = IPQ_PWM_MAX_DIV; -+ -+ /* -+ * high duration = pwm duty * (pwm div + 1) -+ * pwm duty = duty_ns / period_ns -+ */ -+ hi_dur = mul_u64_u64_div_u64(duty_ns, ipq_chip->clk_rate, -+ (u64)(pre_div + 1) * NSEC_PER_SEC); -+ -+ val = FIELD_PREP(IPQ_PWM_REG0_HI_DURATION, hi_dur) | -+ FIELD_PREP(IPQ_PWM_REG0_PWM_DIV, pwm_div); -+ ipq_pwm_reg_write(pwm, IPQ_PWM_REG0, val); -+ -+ val = FIELD_PREP(IPQ_PWM_REG1_PRE_DIV, pre_div); -+ ipq_pwm_reg_write(pwm, IPQ_PWM_REG1, val); -+ -+ /* PWM enable toggle needs a separate write to REG1 */ -+ val |= IPQ_PWM_REG1_UPDATE; -+ if (state->enabled) -+ val |= IPQ_PWM_REG1_ENABLE; -+ ipq_pwm_reg_write(pwm, IPQ_PWM_REG1, val); -+ -+ return 0; -+} -+ -+static int ipq_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, -+ struct pwm_state *state) -+{ -+ struct ipq_pwm_chip *ipq_chip = ipq_pwm_from_chip(chip); -+ unsigned int pre_div, pwm_div, hi_dur; -+ u64 effective_div, hi_div; -+ u32 reg0, reg1; -+ -+ reg1 = ipq_pwm_reg_read(pwm, IPQ_PWM_REG1); -+ state->enabled = reg1 & IPQ_PWM_REG1_ENABLE; -+ -+ if (!state->enabled) -+ return 0; -+ -+ reg0 = ipq_pwm_reg_read(pwm, IPQ_PWM_REG0); -+ -+ state->polarity = PWM_POLARITY_NORMAL; -+ -+ pwm_div = FIELD_GET(IPQ_PWM_REG0_PWM_DIV, reg0); -+ hi_dur = FIELD_GET(IPQ_PWM_REG0_HI_DURATION, reg0); -+ pre_div = FIELD_GET(IPQ_PWM_REG1_PRE_DIV, reg1); -+ -+ effective_div = (u64)(pre_div + 1) * (pwm_div + 1); -+ state->period = DIV64_U64_ROUND_UP(effective_div * NSEC_PER_SEC, -+ ipq_chip->clk_rate); -+ -+ hi_div = hi_dur * (pre_div + 1); -+ state->duty_cycle = DIV64_U64_ROUND_UP(hi_div * NSEC_PER_SEC, -+ ipq_chip->clk_rate); -+ -+ /* -+ * ensure a valid config is passed back to PWM core in case duty_cycle -+ * is > period (>100%) -+ */ -+ state->duty_cycle = min(state->duty_cycle, state->period); -+ -+ return 0; -+} -+ -+static const struct pwm_ops ipq_pwm_ops = { -+ .apply = ipq_pwm_apply, -+ .get_state = ipq_pwm_get_state, -+}; -+ -+static int ipq_pwm_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct ipq_pwm_chip *pwm; -+ struct pwm_chip *chip; -+ struct clk *clk; -+ int ret; -+ -+ chip = devm_pwmchip_alloc(dev, 4, sizeof(*pwm)); -+ if (IS_ERR(chip)) -+ return PTR_ERR(chip); -+ pwm = ipq_pwm_from_chip(chip); -+ -+ pwm->mem = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(pwm->mem)) -+ return dev_err_probe(dev, PTR_ERR(pwm->mem), -+ "Failed to acquire resource\n"); -+ -+ clk = devm_clk_get_enabled(dev, NULL); -+ if (IS_ERR(clk)) -+ return dev_err_probe(dev, PTR_ERR(clk), -+ "Failed to get clock\n"); -+ -+ ret = devm_clk_rate_exclusive_get(dev, clk); -+ if (ret) -+ return dev_err_probe(dev, ret, "Failed to lock clock rate\n"); -+ -+ pwm->clk_rate = clk_get_rate(clk); -+ -+ chip->ops = &ipq_pwm_ops; -+ -+ ret = devm_pwmchip_add(dev, chip); -+ if (ret < 0) -+ return dev_err_probe(dev, ret, "Failed to add pwm chip\n"); -+ -+ return 0; -+} -+ -+static const struct of_device_id pwm_ipq_dt_match[] = { -+ { .compatible = "qcom,ipq6018-pwm", }, -+ {} -+}; -+MODULE_DEVICE_TABLE(of, pwm_ipq_dt_match); -+ -+static struct platform_driver ipq_pwm_driver = { -+ .driver = { -+ .name = "ipq-pwm", -+ .of_match_table = pwm_ipq_dt_match, -+ }, -+ .probe = ipq_pwm_probe, -+}; -+ -+module_platform_driver(ipq_pwm_driver); -+ -+MODULE_LICENSE("GPL"); diff --git a/target/linux/qualcommbe/patches-6.12/0376-arm64-dts-qcom-ipq9574-add-pwm-node.patch b/target/linux/qualcommbe/patches-6.12/0376-arm64-dts-qcom-ipq9574-add-pwm-node.patch deleted file mode 100644 index 011433c6dd..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0376-arm64-dts-qcom-ipq9574-add-pwm-node.patch +++ /dev/null @@ -1,144 +0,0 @@ -From patchwork Wed Feb 4 11:25:12 2026 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: George Moussalem via B4 Relay - -X-Patchwork-Id: 2192912 -Return-Path: - -X-Original-To: incoming@patchwork.ozlabs.org -Delivered-To: patchwork-incoming@legolas.ozlabs.org -Authentication-Results: legolas.ozlabs.org; - dkim=pass (2048-bit key; - unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 - header.s=k20201202 header.b=eBdXYFei; - dkim-atps=neutral -Authentication-Results: legolas.ozlabs.org; - spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org - (client-ip=2600:3c04:e001:36c::12fc:5321; helo=tor.lore.kernel.org; - envelope-from=linux-pwm+bounces-8091-incoming=patchwork.ozlabs.org@vger.kernel.org; - receiver=patchwork.ozlabs.org) -Received: from tor.lore.kernel.org (tor.lore.kernel.org - [IPv6:2600:3c04:e001:36c::12fc:5321]) - (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) - key-exchange x25519) - (No client certificate requested) - by legolas.ozlabs.org (Postfix) with ESMTPS id 4f5dN51jvwz1xqf - for ; Wed, 04 Feb 2026 22:26:29 +1100 (AEDT) -Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org - [100.90.174.1]) - by tor.lore.kernel.org (Postfix) with ESMTP id E6ED73028364 - for ; Wed, 4 Feb 2026 11:25:22 +0000 (UTC) -Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) - by smtp.subspace.kernel.org (Postfix) with ESMTP id 7787F3ECBDF; - Wed, 4 Feb 2026 11:25:14 +0000 (UTC) -Authentication-Results: smtp.subspace.kernel.org; - dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org - header.b="eBdXYFei" -X-Original-To: linux-pwm@vger.kernel.org -Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org - [10.30.226.201]) - (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) - (No client certificate requested) - by smtp.subspace.kernel.org (Postfix) with ESMTPS id 488673ECBC5; - Wed, 4 Feb 2026 11:25:14 +0000 (UTC) -Authentication-Results: smtp.subspace.kernel.org; - arc=none smtp.client-ip=10.30.226.201 -ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; - t=1770204314; cv=none; - b=uwndTXZwjatScjw/qfG0MiKqSIzmIqMgv7TVXWmxKetvRuaAg31sb9ZhW77UPjPX/lMOditmtVgqxnruPV2O6MZjPnZYpu9HApUfhtwTIOzw3WjizZC/AgH49PFHOWCDPWcP9WGPKoDjEz3vupzf1ki1h0rXV4pbjkJtO2Dgfg8= -ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; - s=arc-20240116; t=1770204314; c=relaxed/simple; - bh=vE8UXlKfInB73S8Crc3gaHWqLQg+oOyoCtzeWharQS0=; - h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: - In-Reply-To:To:Cc; - b=nr0qlzwFsS+ce2fu7iqjeCzNSpG8h2LgSxcLUcVXPjNCM2Ync4ajZxf9s+2yE/jV1FuPogUTSu/Npx6P4esNTjiZnUNQQGO/vqBBzhAUOsRZh5kDpfIZD4XNW94nSCFEnymaMZDVMojvZSF25aKaWLbrWAehNVPyQMhyGyXG2kg= -ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; - dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org - header.b=eBdXYFei; arc=none smtp.client-ip=10.30.226.201 -Received: by smtp.kernel.org (Postfix) with ESMTPS id 1FBA8C16AAE; - Wed, 4 Feb 2026 11:25:14 +0000 (UTC) -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; - s=k20201202; t=1770204314; - bh=vE8UXlKfInB73S8Crc3gaHWqLQg+oOyoCtzeWharQS0=; - h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; - b=eBdXYFeiLIl+QGeTfz6IIUeYBuEEDl+b419qodE2EVomGdqaNo6884pycBeWBvZMh - haX7oelDQSKnWGiF9sQjVUxz4Bay2BEZVQ1GmcghWtGQg7w+d4/fdfvByLW08F//at - iN1OoKPRpYgIVaVKk7kEOMlXr20t38YcZLXpVfFG+fIWwnxTLMzJ8Gau5rLyluyr8P - eM9GvY4qwgMgvdyujRQepS7Oi+ovHftu/43TRRxbdoIE8N8kI7jYvsCdHJ61HDu2ls - NNNef1ZfWkcdGaVDLNWZmQ6VTGMTNKrX1uWcdOfsGts6/lMd7pc+dMVMn4md9rJWnb - Ul0Go0aD9V1TQ== -Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org - (localhost.localdomain [127.0.0.1]) - by smtp.lore.kernel.org (Postfix) with ESMTP id 0DE25E95389; - Wed, 4 Feb 2026 11:25:14 +0000 (UTC) -From: George Moussalem via B4 Relay - -Date: Wed, 04 Feb 2026 15:25:12 +0400 -Subject: [PATCH v20 6/6] arm64: dts: qcom: ipq9574: add pwm node -Precedence: bulk -X-Mailing-List: linux-pwm@vger.kernel.org -List-Id: -List-Subscribe: -List-Unsubscribe: -MIME-Version: 1.0 -Message-Id: <20260204-ipq-pwm-v20-6-91733011a3d1@outlook.com> -References: <20260204-ipq-pwm-v20-0-91733011a3d1@outlook.com> -In-Reply-To: <20260204-ipq-pwm-v20-0-91733011a3d1@outlook.com> -To: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , - Rob Herring , Krzysztof Kozlowski , - Conor Dooley , Baruch Siach , - Bjorn Andersson , - Konrad Dybcio -Cc: linux-arm-msm@vger.kernel.org, linux-pwm@vger.kernel.org, - devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, - George Moussalem , - Dmitry Baryshkov -X-Mailer: b4 0.14.2 -X-Developer-Signature: v=1; a=ed25519-sha256; t=1770204310; l=1234; - i=george.moussalem@outlook.com; s=20250321; h=from:subject:message-id; - bh=1ixhFwq2rEjXYJIhs5+j+ngAUcQh5KQa6+Qdzh8kp4o=; - b=ky+nnCBbPuFce/HNZnz6s4ubdKccwoR4mGT7VVjp1Q+YR30lXS7xluR+rnmLy73TfU2J3/6kO - 144Si65ChORDD0KZk1dvy+masC3Igfhy8O3qYSqMdoqSlttNJsS5eZR -X-Developer-Key: i=george.moussalem@outlook.com; a=ed25519; - pk=/PuRTSI9iYiHwcc6Nrde8qF4ZDhJBlUgpHdhsIjnqIk= -X-Endpoint-Received: by B4 Relay for george.moussalem@outlook.com/20250321 - with auth_id=364 -X-Original-From: George Moussalem -Reply-To: george.moussalem@outlook.com - -From: George Moussalem - -Describe the PWM block on IPQ9574. - -Although PWM is in the TCSR area, make pwm its own node as simple-mfd -has been removed from the bindings and as such hardware components -should have its own node. - -Reviewed-by: Dmitry Baryshkov -Signed-off-by: George Moussalem -Reviewed-by: Konrad Dybcio ---- - arch/arm64/boot/dts/qcom/ipq9574.dtsi | 10 ++++++++++ - 1 file changed, 10 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi -@@ -469,6 +469,16 @@ - reg = <0x01937000 0x21000>; - }; - -+ pwm: pwm@1941010 { -+ compatible = "qcom,ipq9574-pwm", "qcom,ipq6018-pwm"; -+ reg = <0x01941010 0x20>; -+ clocks = <&gcc GCC_ADSS_PWM_CLK>; -+ assigned-clocks = <&gcc GCC_ADSS_PWM_CLK>; -+ assigned-clock-rates = <100000000>; -+ #pwm-cells = <3>; -+ status = "disabled"; -+ }; -+ - sdhc_1: mmc@7804000 { - compatible = "qcom,ipq9574-sdhci", "qcom,sdhci-msm-v5"; - reg = <0x07804000 0x1000>, diff --git a/target/linux/qualcommbe/patches-6.18/0312-net-phy-qca808x-Add-QCA8084-SerDes-speed-config.patch b/target/linux/qualcommbe/patches-6.18/0312-net-phy-qca808x-Add-QCA8084-SerDes-speed-config.patch index 9d83ce9883..09822dac36 100644 --- a/target/linux/qualcommbe/patches-6.18/0312-net-phy-qca808x-Add-QCA8084-SerDes-speed-config.patch +++ b/target/linux/qualcommbe/patches-6.18/0312-net-phy-qca808x-Add-QCA8084-SerDes-speed-config.patch @@ -13,8 +13,8 @@ Signed-off-by: Alexandru Gagniuc --- drivers/net/phy/qcom/qca8084_serdes.c | 159 ++++++++++++++++++++++++++ drivers/net/phy/qcom/qca8084_serdes.h | 3 + - drivers/net/phy/qcom/qca808x.c | 15 ++- - 3 files changed, 175 insertions(+), 2 deletions(-) + drivers/net/phy/qcom/qca808x.c | 16 ++- + 3 files changed, 176 insertions(+), 2 deletions(-) --- a/drivers/net/phy/qcom/qca8084_serdes.c +++ b/drivers/net/phy/qcom/qca8084_serdes.c @@ -102,7 +102,7 @@ Signed-off-by: Alexandru Gagniuc + unsigned long rate; + + for (i = 0; i < QCA8084_CHANNEL_MAX; i++) { -+ xpcs_ch = &(xpcs_data->xpcs_ch[channel]); ++ xpcs_ch = &xpcs_data->xpcs_ch[i]; + if (channel == xpcs_ch->ch_id) + break; + } @@ -222,7 +222,7 @@ Signed-off-by: Alexandru Gagniuc int ret; /* Assert the FIFO between PHY and MAC. */ -@@ -1028,14 +1029,24 @@ static void qca8084_link_change_notify(s +@@ -1028,14 +1029,25 @@ static void qca8084_link_change_notify(s } } @@ -233,8 +233,9 @@ Signed-off-by: Alexandru Gagniuc */ - if (phydev->interface == PHY_INTERFACE_MODE_10G_QXGMII) + if (phydev->interface == PHY_INTERFACE_MODE_10G_QXGMII) { -+ shared_priv = phy_package_get_priv(phydev); + struct qca808x_priv *priv = phydev->priv; ++ ++ shared_priv = phy_package_get_priv(phydev); + phy_modify_mmd(phydev, MDIO_MMD_AN, QCA8084_MMD7_IPG_OP, QCA8084_IPG_10_TO_11_EN, diff --git a/target/linux/qualcommbe/patches-6.18/0342-net-qualcomm-Update-IPQ9574-PPE-driver.patch b/target/linux/qualcommbe/patches-6.18/0342-net-qualcomm-Update-IPQ9574-PPE-driver.patch index 24d89dcc47..72f91a80be 100644 --- a/target/linux/qualcommbe/patches-6.18/0342-net-qualcomm-Update-IPQ9574-PPE-driver.patch +++ b/target/linux/qualcommbe/patches-6.18/0342-net-qualcomm-Update-IPQ9574-PPE-driver.patch @@ -2288,7 +2288,7 @@ Signed-off-by: Alexandru Gagniuc - if (ret) - goto error; + for (i = PPE_PORT_CLK_RST_MAC; i < PPE_PORT_CLK_RST_MAX; i++) { -+ ret = reset_control_assert(ppe_port->rstcs[PPE_PORT_CLK_RST_MAC]); ++ ret = reset_control_assert(ppe_port->rstcs[i]); + if (ret) + return ret; + } @@ -2300,7 +2300,7 @@ Signed-off-by: Alexandru Gagniuc - return ret; + for (i = PPE_PORT_CLK_RST_MAC; i < PPE_PORT_CLK_RST_MAX; i++) { -+ ret = reset_control_deassert(ppe_port->rstcs[PPE_PORT_CLK_RST_MAC]); ++ ret = reset_control_deassert(ppe_port->rstcs[i]); + if (ret) + return ret; + } diff --git a/target/linux/qualcommbe/patches-6.18/0403-pwm-fix-period-calculation.patch b/target/linux/qualcommbe/patches-6.18/0403-pwm-fix-period-calculation.patch new file mode 100644 index 0000000000..2606b767fc --- /dev/null +++ b/target/linux/qualcommbe/patches-6.18/0403-pwm-fix-period-calculation.patch @@ -0,0 +1,165 @@ +From 314b696c26589f53cd9c1d1ca35edcfaddd362fb Mon Sep 17 00:00:00 2001 +From: Kenneth Kasilag +Date: Sun, 21 Jun 2026 23:26:43 +0000 +Subject: [PATCH] qualcommbe: fix pwm period calculation + +During testing on the Askey SBE1V1K, it was noticed that only very low +PWM frequencies would work, and 100% duty cycles also did not work. + +Comparing the proposed upstream pwm-ipq driver to the downstream vendor +driver, `ipq_pwm_apply()` fixed pwm_div at its maximum and derived only +pre_div from the requested period. Since the period spans +`(pre_div + 1) * (pwm_div + 1)` input clocks, pinning pwm_div near its +maximum forces pre_div towards zero for short periods: once pre_div +rounds to 0 the shortest representable period is +`(pwm_div + 1) / clk_rate` (~2.7 ms, i.e. ~366 Hz, at a 24 MHz clock), +and any shorter request is silently stretched to that. The high +duration then truncates to 0, so the output collapses to ~0% duty. + +Since 4-wire fans commonly expect a ~25kHz PWM, it was effectively +unusable, since every duty cycle programs a ~zero high time. + +Search for the (pre_div, pwm_div) pair whose period best approximates +the request instead of fixing pwm_div. Starting pre_div at the smallest +value that keeps pwm_div within its field and stopping once pre_div +exceeds pwm_div bounds the loop and keeps pwm_div as large as possible +for fine duty resolution. For a 25 kHz request at 24 MHz this selects +pre_div = 0, pwm_div = 959, giving full 0..960 duty resolution. + +While reworking the high-duration computation, round it to nearest +rather than truncating, so mid-range duty cycles are not biased low, and +clamp it to pwm_div + 1. Rounding, or a 100% duty request, could +otherwise push hi_dur past the period length and overflow the 16-bit +HI_DURATION field. + +Also compute hi_div in `get_state()` in 64-bit; `hi_dur * (pre_div + 1)` +can exceed 32 bits before the existing promotion. + +Fixes: 01fb4a6daadb ("qualcommbe: update pwm patches and add missing symbol") +Signed-off-by: Kenneth Kasilag +--- + drivers/pwm/pwm-ipq.c | 122 ++++++++++++++---- + 1 file changed, 108 insertions(+), 14 deletions(-) + +--- a/drivers/pwm/pwm-ipq.c ++++ b/drivers/pwm/pwm-ipq.c +@@ -89,10 +89,10 @@ static int ipq_pwm_apply(struct pwm_chip + const struct pwm_state *state) + { + struct ipq_pwm_chip *ipq_chip = ipq_pwm_from_chip(chip); +- unsigned int pre_div, pwm_div; +- u64 period_ns, duty_ns; ++ unsigned int pre_div, pwm_div, best_pre_div, best_pwm_div; ++ u64 period_ns, duty_ns, period_rate, min_diff; + unsigned long val = 0; +- unsigned long hi_dur; ++ u64 hi_dur; + + if (state->polarity != PWM_POLARITY_NORMAL) + return -EINVAL; +@@ -107,20 +107,86 @@ static int ipq_pwm_apply(struct pwm_chip + period_ns = min(state->period, IPQ_PWM_MAX_PERIOD_NS); + duty_ns = min(state->duty_cycle, period_ns); + +- pwm_div = IPQ_PWM_MAX_DIV - 1; +- pre_div = mul_u64_u64_div_u64(period_ns, ipq_chip->clk_rate, +- (u64)NSEC_PER_SEC * (pwm_div + 1)); +- pre_div = (pre_div > 0) ? pre_div - 1 : 0; ++ /* ++ * The period spans (pre_div + 1) * (pwm_div + 1) input clocks. Rather ++ * than fixing pwm_div at its maximum (which gives usable duty ++ * resolution only for long periods and collapses to ~0% for short ++ * periods) search for the (pre_div, pwm_div) split whose period best ++ * approximates the request while leaving pwm_div large enough to ++ * resolve the duty cycle. ++ */ ++ if (ipq_chip->clk_rate > 16ULL * GIGA) ++ return -EINVAL; ++ period_rate = period_ns * ipq_chip->clk_rate; ++ ++ best_pre_div = IPQ_PWM_MAX_DIV; ++ best_pwm_div = IPQ_PWM_MAX_DIV; ++ min_diff = period_rate; ++ ++ /* ++ * Smaller pre_div than this cannot represent the period (pwm_div would ++ * have to exceed its field), so start the search there. ++ */ ++ pre_div = div64_u64(period_rate, ++ (u64)NSEC_PER_SEC * (IPQ_PWM_MAX_DIV + 1)); ++ ++ for (; pre_div <= IPQ_PWM_MAX_DIV; pre_div++) { ++ u64 remainder; ++ ++ pwm_div = div64_u64_rem(period_rate, ++ (u64)NSEC_PER_SEC * (pre_div + 1), ++ &remainder); ++ /* pwm_div is unsigned; the swap check below catches underflow */ ++ pwm_div--; ++ ++ /* ++ * Swapping pre_div and pwm_div yields the same period but a ++ * larger pwm_div gives finer duty resolution, so once pre_div ++ * exceeds pwm_div every further candidate is strictly worse. ++ */ ++ if (pre_div > pwm_div) ++ break; ++ ++ /* need room for 100% duty, where hi_dur == pwm_div + 1 */ ++ if (pwm_div > IPQ_PWM_MAX_DIV - 1) ++ continue; ++ ++ if (remainder < min_diff) { ++ best_pre_div = pre_div; ++ best_pwm_div = pwm_div; ++ min_diff = remainder; ++ ++ if (min_diff == 0) ++ break; ++ } ++ } + +- if (pre_div > IPQ_PWM_MAX_DIV) +- pre_div = IPQ_PWM_MAX_DIV; ++ pre_div = best_pre_div; ++ pwm_div = best_pwm_div; ++ ++ /* ++ * If the search found no usable candidate, best_pwm_div is left at ++ * IPQ_PWM_MAX_DIV; cap it so pwm_div + 1 still fits the 16-bit field ++ * and 100% duty remains expressible. ++ */ ++ if (pwm_div > IPQ_PWM_MAX_DIV - 1) ++ pwm_div = IPQ_PWM_MAX_DIV - 1; + + /* +- * high duration = pwm duty * (pwm div + 1) +- * pwm duty = duty_ns / period_ns ++ * high duration = duty_ratio * (pwm_div + 1) ++ * = duty_ns * clk_rate / ((pre_div + 1) * NSEC_PER_SEC) ++ * ++ * Round to nearest to avoid biasing every duty cycle low, then clamp ++ * to (pwm_div + 1): rounding or a 100% request can otherwise push ++ * hi_dur past the period, overflowing the 16-bit HI_DURATION field ++ * (which would alias a full-on request down to a near-zero high time) ++ * and asking the hardware to stay high beyond one period. pwm_div is ++ * at most IPQ_PWM_MAX_DIV - 1, so pwm_div + 1 always fits the field. + */ +- hi_dur = mul_u64_u64_div_u64(duty_ns, ipq_chip->clk_rate, +- (u64)(pre_div + 1) * NSEC_PER_SEC); ++ hi_dur = DIV64_U64_ROUND_CLOSEST(duty_ns * ipq_chip->clk_rate, ++ (u64)(pre_div + 1) * NSEC_PER_SEC); ++ if (hi_dur > (u64)pwm_div + 1) ++ hi_dur = (u64)pwm_div + 1; + + val = FIELD_PREP(IPQ_PWM_REG0_HI_DURATION, hi_dur) | + FIELD_PREP(IPQ_PWM_REG0_PWM_DIV, pwm_div); +@@ -164,7 +230,7 @@ static int ipq_pwm_get_state(struct pwm_ + state->period = DIV64_U64_ROUND_UP(effective_div * NSEC_PER_SEC, + ipq_chip->clk_rate); + +- hi_div = hi_dur * (pre_div + 1); ++ hi_div = (u64)hi_dur * (pre_div + 1); + state->duty_cycle = DIV64_U64_ROUND_UP(hi_div * NSEC_PER_SEC, + ipq_chip->clk_rate); + diff --git a/target/linux/ramips/dts/mt7621_asus_rt-ac85u.dts b/target/linux/ramips/dts/mt7621_asus_rt-ac85u.dts new file mode 100644 index 0000000000..92bca2e14b --- /dev/null +++ b/target/linux/ramips/dts/mt7621_asus_rt-ac85u.dts @@ -0,0 +1,233 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "mt7621.dtsi" + +#include +#include +#include + +/ { + compatible = "asus,rt-ac85u", "mediatek,mt7621-soc"; + model = "ASUS RT-AC85U"; + + aliases { + led-boot = &led_power; + led-failsafe = &led_power; + led-running = &led_power; + led-upgrade = &led_power; + label-mac-device = &gmac0; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&gpio 16 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + wps { + label = "wps"; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_power: power { + function = LED_FUNCTION_POWER; + color = ; + gpios = <&gpio 6 GPIO_ACTIVE_LOW>; + }; + + wifi2g { + color = ; + function = LED_FUNCTION_WLAN_2GHZ; + gpios = <&gpio 4 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy0tpt"; + }; + + wifi5g { + color = ; + function = LED_FUNCTION_WLAN_5GHZ; + gpios = <&gpio 7 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy1tpt"; + }; + + wan { + color = ; + function = LED_FUNCTION_WAN; + gpios = <&gpio 13 GPIO_ACTIVE_LOW>; + }; + + lan { + color = ; + function = LED_FUNCTION_LAN; + gpios = <&gpio 14 GPIO_ACTIVE_LOW>; + }; + + usb { + color = ; + function = LED_FUNCTION_USB; + gpios = <&gpio 15 GPIO_ACTIVE_LOW>; + }; + + wps { + color = ; + function = LED_FUNCTION_WPS; + gpios = <&gpio 12 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&nand { + status = "okay"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0xe0000>; + read-only; + }; + + partition@e0000 { + label = "u-boot-env"; + reg = <0xe0000 0x100000>; + read-only; + }; + + partition@1e0000 { + label = "factory"; + reg = <0x1e0000 0x100000>; + 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>; + }; + + macaddr_factory_e000: macaddr@e000 { + reg = <0xe000 0x6>; + }; + }; + }; + + partition@2e0000 { + label = "factory2"; + reg = <0x2e0000 0x100000>; + read-only; + }; + + partition@3e0000 { + label = "kernel"; + reg = <0x3e0000 0x400000>; + }; + + partition@7e0000 { + label = "ubi"; + reg = <0x7e0000 0x2e00000>; + }; + + partition@35e0000 { + label = "firmware2"; + reg = <0x35e0000 0x3200000>; + }; + }; +}; + +&pcie { + status = "okay"; +}; + +&pcie0 { + wifi0: wifi@0,0 { + compatible = "mediatek,mt76"; + reg = <0x0000 0 0 0 0>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; + ieee80211-freq-limit = <2400000 2500000>; + }; +}; + +&pcie1 { + wifi1: wifi@0,0 { + compatible = "mediatek,mt76"; + reg = <0x0000 0 0 0 0>; + nvmem-cells = <&eeprom_factory_8000>; + nvmem-cell-names = "eeprom"; + ieee80211-freq-limit = <5000000 6000000>; + }; +}; + + +&gmac0 { + nvmem-cells = <&macaddr_factory_e000>; + nvmem-cell-names = "mac-address"; +}; + +&gmac1 { + status = "okay"; + label = "wan"; + phy-handle = <ðphy4>; + + nvmem-cells = <&macaddr_factory_e000>; + nvmem-cell-names = "mac-address"; +}; + +ðphy4 { + /delete-property/ interrupts; +}; + +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + + port@4 { + status = "disabled"; + }; + }; +}; + +&state_default { + gpio { + groups = "uart2", "uart3", "i2c"; + function = "gpio"; + }; +}; + +&xhci { + status = "okay"; +}; diff --git a/target/linux/ramips/dts/mt7621_plasmacloud_pax1800-lite.dts b/target/linux/ramips/dts/mt7621_plasmacloud_pax1800-lite.dts index b1e29e276a..c0395a2c1d 100644 --- a/target/linux/ramips/dts/mt7621_plasmacloud_pax1800-lite.dts +++ b/target/linux/ramips/dts/mt7621_plasmacloud_pax1800-lite.dts @@ -154,13 +154,11 @@ partition@0 { label = "firmware1"; reg = <0x0 0x4000000>; - compatible = "linux,ubi"; }; partition@4000000 { label = "firmware2"; reg = <0x4000000 0x4000000>; - compatible = "linux,ubi"; }; }; }; diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk index f71c7b73bf..4495f9f4b0 100644 --- a/target/linux/ramips/image/mt7621.mk +++ b/target/linux/ramips/image/mt7621.mk @@ -458,6 +458,16 @@ define Device/asus_rt-ac85p endef TARGET_DEVICES += asus_rt-ac85p +define Device/asus_rt-ac85u + $(Device/nand) + DEVICE_VENDOR := ASUS + DEVICE_MODEL := RT-AC85U + DEVICE_DTS := mt7621_asus_rt-ac85u + IMAGE_SIZE := 51200k + DEVICE_PACKAGES := kmod-usb3 kmod-mt7615-firmware uboot-envtools +endef +TARGET_DEVICES += asus_rt-ac85u + define Device/asus_rt-n56u-b1 $(Device/dsa-migration) $(Device/uimage-lzma-loader) diff --git a/target/linux/ramips/mt7621/base-files/lib/upgrade/platform.sh b/target/linux/ramips/mt7621/base-files/lib/upgrade/platform.sh index 106f8043eb..1e6938004f 100644 --- a/target/linux/ramips/mt7621/base-files/lib/upgrade/platform.sh +++ b/target/linux/ramips/mt7621/base-files/lib/upgrade/platform.sh @@ -73,6 +73,7 @@ platform_do_upgrade() { arcadyan,we420223-99|\ asus,rt-ac65p|\ asus,rt-ac85p|\ + asus,rt-ac85u|\ asus,rt-ax53u|\ asus,rt-ax54|\ asus,4g-ax56|\ 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 a85fbfc173..95ea56a268 100644 --- a/target/linux/realtek/base-files/etc/board.d/02_network +++ b/target/linux/realtek/base-files/etc/board.d/02_network @@ -64,6 +64,7 @@ realtek_setup_macs() netgear,gs308t-v1|\ netgear,gs310tp-v1|\ tplink,sg2008p-v1|\ + tplink,sg2008p-v3|\ tplink,sg2210p-v3|\ tplink,sg2452p-v4|\ tplink,t1600g-28ts-v3|\ @@ -99,10 +100,13 @@ realtek_setup_macs() ;; hasivo,f1100w-4sx-4xgt|\ hasivo,f1100w-4sx-4xgt-512mb|\ + hasivo,f5800w-12s-plus|\ tplink,tl-st1008f-v2|\ - zyxel,xgs1010-12-a1) + zyxel,xgs1010-12-a1|\ + zyxel,xgs1010-12-b1) lan_mac=$(mtd_get_mac_ascii u-boot-env ethaddr) - [ -z "$lan_mac" ] || [ "$lan_mac" = "00:e0:4c:00:00:00" ] && lan_mac=$(macaddr_random) + mac_prefix=$(echo "$lan_mac" | cut -d: -f1-5) + [ -z "$lan_mac" ] || [ "$mac_prefix" = "00:e0:4c:00:00" ] && lan_mac=$(macaddr_random) lan_mac_start=$lan_mac eth0_mac=$lan_mac ;; diff --git a/target/linux/realtek/base-files/etc/init.d/i2c_poe b/target/linux/realtek/base-files/etc/init.d/i2c_poe new file mode 100755 index 0000000000..99b612e71f --- /dev/null +++ b/target/linux/realtek/base-files/etc/init.d/i2c_poe @@ -0,0 +1,26 @@ +#!/bin/sh /etc/rc.common + +START=10 + +mp3924_auto_mode() { + local i2c_addr=0x21 + + # Set power limit to 60 Watts. + i2cset -y 0 ${i2c_addr?} 0x54 0x00 # PMAX[0] = 0 + i2cset -y 0 ${i2c_addr?} 0x55 0x4b # PMAX[1-8] = 0x4b + i2cset -y -m 0x04 0 ${i2c_addr?} 0x0f 0x04 # PMAXEN = 1 + + # Set all ports to AUTO mode. + i2cset -y 0 ${i2c_addr?} 0x03 0xff # MODE = AUTO + i2cset -y -m 0x0f 0 ${i2c_addr?} 0x0c 0x0f # 2EVNTEN = 1 + i2cset -y -m 0x0f 0 ${i2c_addr?} 0x07 0x0f # DISEN = 1 + i2cset -y 0 ${i2c_addr?} 0x06 0xff # DETEN = 1, CLSEN = 1 +} + +boot() { + case $(board_name) in + tplink,sg2008p-v3) + mp3924_auto_mode + ;; + esac +} diff --git a/target/linux/realtek/base-files/etc/uci-defaults/99_fwenv-store-ethaddr b/target/linux/realtek/base-files/etc/uci-defaults/99_fwenv-store-ethaddr index 3d9e795311..5a8e3a8ae1 100644 --- a/target/linux/realtek/base-files/etc/uci-defaults/99_fwenv-store-ethaddr +++ b/target/linux/realtek/base-files/etc/uci-defaults/99_fwenv-store-ethaddr @@ -11,48 +11,57 @@ BOARD_CFG=/etc/board.json # Some devices make it hard or impossible to acquire a usable ethaddr / MAC address # of the device. Some store it in weird places, some ship with only the common -# Realtek dummy ethaddr, and some are outright broken. +# Realtek dummy ethaddr, and some are outright broken. Often the MAC address +# isn't printed on the case label either. # # For these devices, we generate a random ethaddr in /etc/board.d/02_network, -# which is stored in /etc/board.json. Here we take this random ethaddr and -# persist it in the U-Boot environment, so that it survives sysupgrades. +# which is saved in /etc/board.json. +# +# Here we take this random ethaddr and store it in the U-Boot environment, +# so that it survives sysupgrades and factory resets. + +store_board_ethaddr() { + local board_ethaddr + json_init + json_load_file "$BOARD_CFG" + json_select network_device + json_select eth0 + json_get_var board_ethaddr macaddr + json_cleanup + [ -n "$board_ethaddr" ] && fw_setenv ethaddr "$board_ethaddr" +} case "$(board_name)" in +# F1100W-4SX-4XGT and its variants ship with the dummy ethaddr in the u-boot +# environment, and the real ethaddr stored in RUNTIME/RUNTIME2 JFFS2 partitions, +# which would be annoying to deal with. Also ethaddr isn't printed on the case. +# +# F5800W-12S+ same as F1100W, except the MAC address ends with :10, not :00. +# +# TL-ST1008F v2 ships with the dummy ethaddr because it's sold as unmanaged. +# +# We store the random ethaddr if the currently stored ethaddr is empty or dummy. hasivo,f1100w-4sx-4xgt|\ hasivo,f1100w-4sx-4xgt-512mb|\ +hasivo,f5800w-12s-plus|\ tplink,tl-st1008f-v2) env_ethaddr=$(macaddr_canonicalize "$(fw_printenv -n ethaddr 2>/dev/null)") + ethaddr_prefix=$(echo "$env_ethaddr" | cut -d: -f1-5) - # F1100W-4SX-4XGT and its variants ship with the dummy ethaddr in the u-boot - # environment, and the real ethaddr stored in RUNTIME/RUNTIME2 JFFS2 partitions, - # which would be annoying to deal with. Also ethaddr isn't printed on the case. - # - # TL-ST1008F v2 ships with a dummy ethaddr because it's an unmanaged switch. - # - # We persist the random ethaddr if the currently stored ethaddr is empty or dummy. - if [ -z "$env_ethaddr" ] || [ "$env_ethaddr" = "00:e0:4c:00:00:00" ]; then - json_init - json_load_file "$BOARD_CFG" - json_select network_device - json_select eth0 - json_get_var board_ethaddr macaddr - [ -n "$board_ethaddr" ] && fw_setenv ethaddr "$board_ethaddr" + if [ -z "$env_ethaddr" ] || [ "$ethaddr_prefix" = "00:e0:4c:00:00" ]; then + store_board_ethaddr fi ;; -zyxel,xgs1010-12-a1) +# This device ships with an empty environment (invalid CRC). If it is still in +# that state, we don't want to modify it, because that would write the defaults +# of the userspace U-Boot tools (which differ from the ones in the bootloader). +# Thus, we don't do anything here if the ethaddr variable is empty. +zyxel,xgs1010-12-a1|\ +zyxel,xgs1010-12-b1) env_ethaddr=$(macaddr_canonicalize "$(fw_printenv -n ethaddr 2>/dev/null)") - # This device ships with an empty environment (invalid CRC). If it is still in - # that state, we don't want to modify it, because that would write the defaults - # of the userspace U-Boot tools (which differ from the ones in the bootloader). - # Thus, we don't do anything here if the ethaddr variable is empty. if [ "$env_ethaddr" = "00:e0:4c:00:00:00" ]; then - json_init - json_load_file "$BOARD_CFG" - json_select network_device - json_select eth0 - json_get_var board_ethaddr macaddr - [ -n "$board_ethaddr" ] && fw_setenv ethaddr "$board_ethaddr" + store_board_ethaddr fi ;; esac diff --git a/target/linux/realtek/base-files/lib/upgrade/platform.sh b/target/linux/realtek/base-files/lib/upgrade/platform.sh index df128a825f..6df1d5cc52 100644 --- a/target/linux/realtek/base-files/lib/upgrade/platform.sh +++ b/target/linux/realtek/base-files/lib/upgrade/platform.sh @@ -36,6 +36,7 @@ platform_do_upgrade() { platform_do_upgrade_dualboot_plasmacloud "$1" ;; tplink,sg2008p-v1|\ + tplink,sg2008p-v3|\ tplink,sg2210p-v3) tplink_sg2xxx_fix_mtdparts default_do_upgrade "$1" diff --git a/target/linux/realtek/dts/rtl8380_tplink_sg2008p-v3.dts b/target/linux/realtek/dts/rtl8380_tplink_sg2008p-v3.dts new file mode 100644 index 0000000000..24efd6bd03 --- /dev/null +++ b/target/linux/realtek/dts/rtl8380_tplink_sg2008p-v3.dts @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "rtl8380_tplink_sg2xxx.dtsi" + +/ { + compatible = "tplink,sg2008p-v3", "realtek,rtl838x-soc"; + model = "TP-Link SG2008P v3"; +}; + +&gpio0 { + poe-enable { + gpio-hog; + gpios = <5 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "poe-enable"; + }; +}; + +&tps23861_20 { + status = "disabled"; +}; + +&tps23861_28 { + status = "disabled"; +}; + +&port24 { + status = "disabled"; +}; + +&port26 { + status = "disabled"; +}; diff --git a/target/linux/realtek/dts/rtl9302_zyxel_xgs1010-12-a1.dts b/target/linux/realtek/dts/rtl9302_zyxel_xgs1010-12-a1.dts index 7a5d2f4b3d..a1f19a9aa6 100644 --- a/target/linux/realtek/dts/rtl9302_zyxel_xgs1010-12-a1.dts +++ b/target/linux/realtek/dts/rtl9302_zyxel_xgs1010-12-a1.dts @@ -1,106 +1,11 @@ // SPDX-License-Identifier: GPL-2.0-or-later /dts-v1/; -#include "rtl9302_zyxel_xgs1x10-12-common.dtsi" +#include "rtl9302_zyxel_xgs1010-12-common.dtsi" / { compatible = "zyxel,xgs1010-12-a1", "realtek,rtl930x-soc"; model = "Zyxel XGS1010-12 A1"; - - virtual_flash { - compatible = "mtd-concat"; - - devices = <&fwconcat0 &fwconcat1 &fwconcat2>; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "firmware"; - reg = <0x0 0x0>; - compatible = "openwrt,uimage", "denx,uimage"; - openwrt,ih-magic = <0x93001010>; - }; - }; - }; -}; - -&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 0xe0000>; - read-only; - }; - - partition@e0000 { - label = "u-boot-env"; - reg = <0xe0000 0x10000>; - }; - - partition@f0000 { - label = "u-boot-env2"; - reg = <0xf0000 0x10000>; - read-only; - }; - - /* - * If additional space is needed in the future, the JFFS2 partitions could - * be added to the concatenated firmware partition. They are only reserved - * for now to allow running the XGS1210-12 firmware, which can be useful - * as a reference during development. - */ - - partition@100000 { - label = "jffs2-cfg"; - reg = <0x100000 0x100000>; - }; - - partition@200000 { - label = "jffs2-log"; - reg = <0x200000 0x100000>; - }; - - fwconcat1: partition@300000 { - label = "fwconcat1"; - reg = <0x300000 0x510000>; - }; - - partition@810000 { - reg = <0x810000 0x10000>; - label = "htp-log"; - read-only; - }; - - fwconcat2: partition@820000 { - label = "fwconcat2"; - reg = <0x820000 0xd0000>; - }; - - partition@8f0000 { - reg = <0x8f0000 0x10000>; - label = "htp-flash-test"; - read-only; - }; - - fwconcat0: partition@900000 { - label = "fwconcat0"; - reg = <0x900000 0x700000>; - }; - }; - }; }; &mdio_bus1 { diff --git a/target/linux/realtek/dts/rtl9302_zyxel_xgs1010-12-b1.dts b/target/linux/realtek/dts/rtl9302_zyxel_xgs1010-12-b1.dts new file mode 100644 index 0000000000..7437890749 --- /dev/null +++ b/target/linux/realtek/dts/rtl9302_zyxel_xgs1010-12-b1.dts @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/dts-v1/; + +#include "rtl9302_zyxel_xgs1010-12-common.dtsi" + +/ { + compatible = "zyxel,xgs1010-12-b1", "realtek,rtl930x-soc"; + model = "Zyxel XGS1010-12 B1"; +}; + +&mdio_bus1 { + PHY_C45(24, 1) +}; + +&mdio_bus2 { + PHY_C45(25, 2) +}; diff --git a/target/linux/realtek/dts/rtl9302_zyxel_xgs1010-12-common.dtsi b/target/linux/realtek/dts/rtl9302_zyxel_xgs1010-12-common.dtsi new file mode 100644 index 0000000000..bb510c3849 --- /dev/null +++ b/target/linux/realtek/dts/rtl9302_zyxel_xgs1010-12-common.dtsi @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/dts-v1/; + +#include "rtl9302_zyxel_xgs1x10-12-common.dtsi" + +/ { + virtual_flash { + compatible = "mtd-concat"; + + devices = <&fwconcat0 &fwconcat1 &fwconcat2>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "firmware"; + reg = <0x0 0x0>; + compatible = "openwrt,uimage", "denx,uimage"; + openwrt,ih-magic = <0x93001010>; + }; + }; + }; +}; + +&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 0xe0000>; + read-only; + }; + + partition@e0000 { + label = "u-boot-env"; + reg = <0xe0000 0x10000>; + }; + + partition@f0000 { + label = "u-boot-env2"; + reg = <0xf0000 0x10000>; + read-only; + }; + + /* + * If additional space is needed in the future, the JFFS2 partitions could + * be added to the concatenated firmware partition. They are only reserved + * for now to allow running the XGS1210-12 firmware, which can be useful + * as a reference during development. + */ + + partition@100000 { + label = "jffs2-cfg"; + reg = <0x100000 0x100000>; + }; + + partition@200000 { + label = "jffs2-log"; + reg = <0x200000 0x100000>; + }; + + fwconcat1: partition@300000 { + label = "fwconcat1"; + reg = <0x300000 0x510000>; + }; + + partition@810000 { + reg = <0x810000 0x10000>; + label = "htp-log"; + read-only; + }; + + fwconcat2: partition@820000 { + label = "fwconcat2"; + reg = <0x820000 0xd0000>; + }; + + partition@8f0000 { + reg = <0x8f0000 0x10000>; + label = "htp-flash-test"; + read-only; + }; + + fwconcat0: partition@900000 { + label = "fwconcat0"; + reg = <0x900000 0x700000>; + }; + }; + }; +}; diff --git a/target/linux/realtek/dts/rtl9303_hasivo_f1100w-4sx-4xgt-common.dtsi b/target/linux/realtek/dts/rtl9303_hasivo_f1100w-4sx-4xgt-common.dtsi index 38be37061d..99f5b24d09 100644 --- a/target/linux/realtek/dts/rtl9303_hasivo_f1100w-4sx-4xgt-common.dtsi +++ b/target/linux/realtek/dts/rtl9303_hasivo_f1100w-4sx-4xgt-common.dtsi @@ -55,7 +55,6 @@ compatible = "sff,sfp"; i2c-bus = <&i2c0>; mod-def0-gpios = <&gpio0 0 GPIO_ACTIVE_LOW>; - maximum-power-milliwatt = <2000>; #thermal-sensor-cells = <0>; }; @@ -63,7 +62,6 @@ compatible = "sff,sfp"; i2c-bus = <&i2c1>; mod-def0-gpios = <&gpio0 1 GPIO_ACTIVE_LOW>; - maximum-power-milliwatt = <2000>; #thermal-sensor-cells = <0>; }; @@ -71,7 +69,6 @@ compatible = "sff,sfp"; i2c-bus = <&i2c2>; mod-def0-gpios = <&gpio0 2 GPIO_ACTIVE_LOW>; - maximum-power-milliwatt = <2000>; #thermal-sensor-cells = <0>; }; @@ -79,7 +76,6 @@ compatible = "sff,sfp"; i2c-bus = <&i2c3>; mod-def0-gpios = <&gpio0 3 GPIO_ACTIVE_LOW>; - maximum-power-milliwatt = <2000>; #thermal-sensor-cells = <0>; }; }; diff --git a/target/linux/realtek/dts/rtl9303_nicgiga_s100-0800s-m.dts b/target/linux/realtek/dts/rtl9303_nicgiga_s100-0800s-m.dts new file mode 100644 index 0000000000..924802baa6 --- /dev/null +++ b/target/linux/realtek/dts/rtl9303_nicgiga_s100-0800s-m.dts @@ -0,0 +1,287 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "rtl930x.dtsi" + +#include +#include + +/ { + compatible = "nicgiga,s100-0800s-m", "realtek,rtl930x-soc"; + model = "NicGiga S100-0800S-M"; + + memory@0 { + device_type = "memory"; + reg = <0x00000000 0x10000000>, /* first 256 MiB */ + <0x20000000 0x10000000>; /* remaining 256 MiB */ + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + led_set { + compatible = "realtek,rtl9300-leds"; + active-low; + + /* One green LED per SFP cage, lit on link + activity at any speed. */ + led_set0 = <(RTL93XX_LED_SET_10G | RTL93XX_LED_SET_5G | RTL93XX_LED_SET_2P5G | + RTL93XX_LED_SET_1G | RTL93XX_LED_SET_100M | RTL93XX_LED_SET_10M | + RTL93XX_LED_SET_LINK | RTL93XX_LED_SET_ACT)>; + }; + + i2c_gpio { + compatible = "i2c-gpio"; + #address-cells = <1>; + #size-cells = <0>; + i2c-gpio,delay-us = <2>; + scl-gpios = <&gpio0 22 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio0 23 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + + gpioexp0: i2c@38 { + reg = <0x38>; + compatible = "nxp,pca9534"; + gpio-controller; + #gpio-cells = <2>; + }; + }; + + /* + * The related TP-Link TL-ST1008F v2 (same RTL9303 reference design) + * routes the SFP cage MOD_ABS lines to gpio0 pins 0-7, but on this + * board those pins read stuck-low under OpenWrt (an empty cage still + * reads "present"), and the PCA9534 expander is fully consumed by + * TX_DISABLE. No mod-def0-gpio is therefore wired up; module presence + * is instead detected by polling the SFP EEPROM over I2C, which also + * handles runtime hot-insertion and removal. + */ + sfp0: sfp-p1 { + compatible = "sff,sfp"; + i2c-bus = <&i2c0>; + tx-disable-gpio = <&gpioexp0 0 GPIO_ACTIVE_HIGH>; + maximum-power-milliwatt = <2900>; + #thermal-sensor-cells = <0>; + }; + + sfp1: sfp-p2 { + compatible = "sff,sfp"; + i2c-bus = <&i2c1>; + tx-disable-gpio = <&gpioexp0 1 GPIO_ACTIVE_HIGH>; + maximum-power-milliwatt = <1500>; + #thermal-sensor-cells = <0>; + }; + + sfp2: sfp-p3 { + compatible = "sff,sfp"; + i2c-bus = <&i2c2>; + tx-disable-gpio = <&gpioexp0 2 GPIO_ACTIVE_HIGH>; + maximum-power-milliwatt = <1500>; + #thermal-sensor-cells = <0>; + }; + + sfp3: sfp-p4 { + compatible = "sff,sfp"; + i2c-bus = <&i2c3>; + tx-disable-gpio = <&gpioexp0 3 GPIO_ACTIVE_HIGH>; + maximum-power-milliwatt = <2000>; + #thermal-sensor-cells = <0>; + }; + + sfp4: sfp-p5 { + compatible = "sff,sfp"; + i2c-bus = <&i2c4>; + tx-disable-gpio = <&gpioexp0 4 GPIO_ACTIVE_HIGH>; + maximum-power-milliwatt = <2000>; + #thermal-sensor-cells = <0>; + }; + + sfp5: sfp-p6 { + compatible = "sff,sfp"; + i2c-bus = <&i2c5>; + tx-disable-gpio = <&gpioexp0 5 GPIO_ACTIVE_HIGH>; + maximum-power-milliwatt = <1500>; + #thermal-sensor-cells = <0>; + }; + + sfp6: sfp-p7 { + compatible = "sff,sfp"; + i2c-bus = <&i2c6>; + tx-disable-gpio = <&gpioexp0 6 GPIO_ACTIVE_HIGH>; + maximum-power-milliwatt = <1500>; + #thermal-sensor-cells = <0>; + }; + + sfp7: sfp-p8 { + compatible = "sff,sfp"; + i2c-bus = <&i2c7>; + tx-disable-gpio = <&gpioexp0 7 GPIO_ACTIVE_HIGH>; + maximum-power-milliwatt = <2900>; + #thermal-sensor-cells = <0>; + }; + + watchdog { + compatible = "linux,wdt-gpio"; + gpios = <&gpio0 21 GPIO_ACTIVE_HIGH>; + hw_algo = "toggle"; + hw_margin_ms = <1200>; + always-running; + }; +}; + +&i2c_mst1 { + status = "okay"; + + /* SDA0-7 correspond to GPIO9-16 */ + i2c0: i2c@0 { reg = <0>; }; + i2c1: i2c@1 { reg = <1>; }; + i2c2: i2c@2 { reg = <2>; }; + i2c3: i2c@3 { reg = <3>; }; + i2c4: i2c@4 { reg = <4>; }; + i2c5: i2c@5 { reg = <5>; }; + i2c6: i2c@6 { reg = <6>; }; + i2c7: i2c@7 { reg = <7>; }; +}; + +&spi0 { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <100000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0xe0000>; + read-only; + }; + + partition@e0000 { + label = "u-boot-env"; + reg = <0xe0000 0x10000>; + + nvmem-layout { + compatible = "u-boot,env"; + + macaddr_ubootenv_ethaddr: ethaddr { + #nvmem-cell-cells = <1>; + }; + }; + }; + + partition@f0000 { + label = "u-boot-env2"; + reg = <0xf0000 0x10000>; + read-only; + }; + + partition@100000 { + label = "jffs2-cfg"; + reg = <0x100000 0x100000>; + }; + + partition@200000 { + label = "jffs2-log"; + reg = <0x200000 0x100000>; + }; + + partition@300000 { + compatible = "openwrt,uimage", "denx,uimage"; + reg = <0x300000 0x1d00000>; + label = "firmware"; + openwrt,ih-magic = <0x93030000>; + }; + }; + }; +}; + +&switch0 { + ethernet-ports { + #address-cells = <1>; + #size-cells = <0>; + + SWITCH_PORT_SFP(0, 1, 2, 0, 0) + SWITCH_PORT_SFP(8, 2, 3, 0, 1) + SWITCH_PORT_SFP(16, 3, 4, 0, 2) + SWITCH_PORT_SFP(20, 4, 5, 0, 3) + SWITCH_PORT_SFP(24, 5, 6, 0, 4) + SWITCH_PORT_SFP(25, 6, 7, 0, 5) + SWITCH_PORT_SFP(26, 7, 8, 0, 6) + SWITCH_PORT_SFP(27, 8, 9, 0, 7) + + port@1c { + ethernet = <ðernet0>; + reg = <28>; + phy-mode = "internal"; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + }; +}; + +ðernet0 { + nvmem-cells = <&macaddr_ubootenv_ethaddr 0>; + nvmem-cell-names = "mac-address"; +}; + +&port0 { + nvmem-cells = <&macaddr_ubootenv_ethaddr 1>; + nvmem-cell-names = "mac-address"; +}; + +&port8 { + nvmem-cells = <&macaddr_ubootenv_ethaddr 2>; + nvmem-cell-names = "mac-address"; +}; + +&port16 { + nvmem-cells = <&macaddr_ubootenv_ethaddr 3>; + nvmem-cell-names = "mac-address"; +}; + +&port20 { + nvmem-cells = <&macaddr_ubootenv_ethaddr 4>; + nvmem-cell-names = "mac-address"; +}; + +&port24 { + nvmem-cells = <&macaddr_ubootenv_ethaddr 5>; + nvmem-cell-names = "mac-address"; +}; + +&port25 { + nvmem-cells = <&macaddr_ubootenv_ethaddr 6>; + nvmem-cell-names = "mac-address"; +}; + +&port26 { + nvmem-cells = <&macaddr_ubootenv_ethaddr 7>; + nvmem-cell-names = "mac-address"; +}; + +&port27 { + nvmem-cells = <&macaddr_ubootenv_ethaddr 8>; + nvmem-cell-names = "mac-address"; +}; + +&thermal_zones { + sfp-thermal { + polling-delay-passive = <10000>; + polling-delay = <10000>; + thermal-sensors = <&sfp0>, <&sfp1>, <&sfp2>, <&sfp3>, <&sfp4>, <&sfp5>, <&sfp6>, <&sfp7>; + trips { + sfp-crit { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; +}; diff --git a/target/linux/realtek/dts/rtl9313_hasivo_f5800w-12s-plus.dts b/target/linux/realtek/dts/rtl9313_hasivo_f5800w-12s-plus.dts new file mode 100644 index 0000000000..0619fa78f9 --- /dev/null +++ b/target/linux/realtek/dts/rtl9313_hasivo_f5800w-12s-plus.dts @@ -0,0 +1,334 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/dts-v1/; + +#include "rtl931x.dtsi" + +#include +#include +#include +#include + +/ { + compatible = "hasivo,f5800w-12s-plus", "realtek,rtl9313-soc"; + model = "Hasivo F5800W-12S+"; + + memory@0 { + device_type = "memory"; + reg = <0x00000000 0x10000000>, /* 256 MiB lowmem */ + <0x90000000 0x10000000>; /* 256 MiB highmem */ + }; + + chosen { + stdout-path = "serial0:38400n8"; + }; + + keys { + compatible = "gpio-keys"; + + button-reset { + label = "reset"; + gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + led_set { + compatible = "realtek,rtl9300-leds"; + active-low; + + led_set1 = < + ( // Green lower row - 2.5G/1G link + RTL93XX_LED_SET_2P5G | + RTL93XX_LED_SET_1G | + RTL93XX_LED_SET_LINK | + RTL93XX_LED_SET_ACT + ) + ( // Green upper row - 10G link + RTL93XX_LED_SET_10G | + RTL93XX_LED_SET_LINK | + RTL93XX_LED_SET_ACT + )>; + }; + + i2c_sys: i2c-system { + compatible = "i2c-gpio"; + #address-cells = <1>; + #size-cells = <0>; + + pinctrl-names = "default"; + pinctrl-0 = <&pinmux_disable_jtag>; + + scl-gpios = <&gpio0 4 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio0 3 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + i2c-gpio,delay-us = <28>; + + rtc@51 { + compatible = "nxp,pcf8563"; + reg = <0x51>; + }; + + mcu_mgmt: mcu@6f { + compatible = "hasivo,stc8-mfd", "syscon"; + reg = <0x6f>; + + mcu_wdt: watchdog { + compatible = "hasivo,mcu-wdt"; + }; + + sensor { + compatible = "hasivo,mcu-sensor"; + }; + }; + }; + + sfp1: sfp-p1 { + compatible = "sff,sfp"; + i2c-bus = <&i2c1_sda0>; + los-gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&gpio0 9 GPIO_ACTIVE_LOW>; + tx-disable-gpios = <&gpio0 10 GPIO_ACTIVE_HIGH>; + }; + + sfp2: sfp-p2 { + compatible = "sff,sfp"; + i2c-bus = <&i2c1_sda1>; + los-gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&gpio0 12 GPIO_ACTIVE_LOW>; + tx-disable-gpios = <&gpio0 27 GPIO_ACTIVE_HIGH>; + }; + + sfp3: sfp-p3 { + compatible = "sff,sfp"; + i2c-bus = <&i2c1_sda2>; + los-gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&gpio0 29 GPIO_ACTIVE_LOW>; + tx-disable-gpios = <&gpio0 30 GPIO_ACTIVE_HIGH>; + }; + + sfp4: sfp-p4 { + compatible = "sff,sfp"; + i2c-bus = <&i2c1_sda3>; + los-gpios = <&gpio0 18 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>; + tx-disable-gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>; + }; + + sfp5: sfp-p5 { + compatible = "sff,sfp"; + i2c-bus = <&i2c1_sda4>; + los-gpios = <&gpio0 19 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&gpio1 3 GPIO_ACTIVE_LOW>; + tx-disable-gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>; + }; + + sfp6: sfp-p6 { + compatible = "sff,sfp"; + i2c-bus = <&i2c1_sda5>; + los-gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&gpio1 8 GPIO_ACTIVE_LOW>; + tx-disable-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>; + }; + + sfp7: sfp-p7 { + compatible = "sff,sfp"; + i2c-bus = <&i2c2_sda6>; + los-gpios = <&gpio0 21 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&gpio1 11 GPIO_ACTIVE_LOW>; + tx-disable-gpios = <&gpio1 12 GPIO_ACTIVE_HIGH>; + }; + + sfp8: sfp-p8 { + compatible = "sff,sfp"; + i2c-bus = <&i2c2_sda7>; + los-gpios = <&gpio0 22 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&gpio1 32 GPIO_ACTIVE_LOW>; + tx-disable-gpios = <&gpio1 33 GPIO_ACTIVE_HIGH>; + }; + + sfp9: sfp-p9 { + compatible = "sff,sfp"; + i2c-bus = <&i2c2_sda8>; + los-gpios = <&gpio0 23 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&gpio1 36 GPIO_ACTIVE_LOW>; + tx-disable-gpios = <&gpio2 0 GPIO_ACTIVE_HIGH>; + }; + + sfp10: sfp-p10 { + compatible = "sff,sfp"; + i2c-bus = <&i2c2_sda9>; + los-gpios = <&gpio0 24 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&gpio2 2 GPIO_ACTIVE_LOW>; + tx-disable-gpios = <&gpio2 3 GPIO_ACTIVE_HIGH>; + }; + + sfp11: sfp-p11 { + compatible = "sff,sfp"; + i2c-bus = <&i2c2_sda10>; + los-gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>; + tx-disable-gpios = <&gpio2 6 GPIO_ACTIVE_HIGH>; + }; + + sfp12: sfp-p12 { + compatible = "sff,sfp"; + i2c-bus = <&i2c2_sda11>; + los-gpios = <&gpio0 26 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&gpio2 8 GPIO_ACTIVE_LOW>; + tx-disable-gpios = <&gpio2 9 GPIO_ACTIVE_HIGH>; + }; +}; + +&i2c_mst1 { + status = "okay"; + + i2c1_sda0: i2c@0 { reg = <0>; }; + i2c1_sda1: i2c@1 { reg = <1>; }; + i2c1_sda2: i2c@2 { reg = <2>; }; + i2c1_sda3: i2c@3 { reg = <3>; }; + i2c1_sda4: i2c@4 { reg = <4>; }; + i2c1_sda5: i2c@5 { reg = <5>; }; +}; + +&i2c_mst2 { + status = "okay"; + + i2c2_sda6: i2c@6 { reg = <6>; }; + i2c2_sda7: i2c@7 { reg = <7>; }; + i2c2_sda8: i2c@8 { reg = <8>; }; + i2c2_sda9: i2c@9 { reg = <9>; }; + i2c2_sda10: i2c@a { reg = <10>; }; + i2c2_sda11: i2c@b { reg = <11>; }; +}; + +&mdio_aux { + status = "okay"; + + gpio1: gpio@0 { + compatible = "realtek,rtl8231"; + reg = <0>; + + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&gpio1 0 0 37>; + + led-controller { + compatible = "realtek,rtl8231-leds"; + status = "disabled"; + }; + }; + + gpio2: gpio@1 { + compatible = "realtek,rtl8231"; + reg = <1>; + + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&gpio2 0 0 37>; + + led-controller { + compatible = "realtek,rtl8231-leds"; + status = "disabled"; + }; + }; +}; + +&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>; + + /* stock is LOADER */ + partition@0 { + label = "u-boot"; + reg = <0x0000000 0x00e0000>; + read-only; + }; + + /* stock is BDINFO */ + partition@e0000 { + label = "u-boot-env"; + reg = <0x00e0000 0x0010000>; + }; + + /* stock is SYSINFO */ + partition@f0000 { + label = "u-boot-env2"; + reg = <0x00f0000 0x0010000>; + }; + + /* stock is CFG JFFS2 */ + partition@100000 { + label = "jffs"; + reg = <0x0100000 0x0100000>; + }; + + /* stock is LOG JFFS2 */ + partition@200000 { + label = "jffs2"; + reg = <0x0200000 0x0100000>; + }; + + /* stock is RUNTIME and RUNTIME2 + * RUNTIME is <0x0300000 0x0700000> + * RUNTIME2 is <0x0a00000 0x1600000> + */ + partition@300000 { + compatible = "openwrt,uimage", "denx,uimage"; + label = "firmware"; + reg = <0x0300000 0x1d00000>; + }; + }; + }; +}; + +&switch0 { + ethernet-ports { + #address-cells = <1>; + #size-cells = <0>; + + SWITCH_PORT_SFP(0, 1, 2, 1, 1) + SWITCH_PORT_SFP(8, 2, 3, 1, 2) + SWITCH_PORT_SFP(16, 3, 4, 1, 3) + SWITCH_PORT_SFP(24, 4, 5, 1, 4) + SWITCH_PORT_SFP(32, 5, 6, 1, 5) + SWITCH_PORT_SFP(40, 6, 7, 1, 6) + SWITCH_PORT_SFP(48, 7, 8, 1, 7) + SWITCH_PORT_SFP(50, 8, 9, 1, 8) + SWITCH_PORT_SFP(52, 9, 10, 1, 9) + SWITCH_PORT_SFP(53, 10, 11, 1, 10) + SWITCH_PORT_SFP(54, 11, 12, 1, 11) + SWITCH_PORT_SFP(55, 12, 13, 1, 12) + + /* CPU port */ + port@56 { + ethernet = <ðernet0>; + reg = <56>; + phy-mode = "internal"; + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + }; +}; + +&serdes2 { tx-polarity = ; }; +&serdes3 { tx-polarity = ; }; +&serdes4 { tx-polarity = ; }; +&serdes5 { tx-polarity = ; }; +&serdes6 { tx-polarity = ; }; +&serdes7 { tx-polarity = ; }; +&serdes8 { tx-polarity = ; }; +&serdes9 { tx-polarity = ; }; +&serdes10 { tx-polarity = ; }; +&serdes11 { tx-polarity = ; }; +&serdes12 { tx-polarity = ; }; +&serdes13 { tx-polarity = ; }; diff --git a/target/linux/realtek/dts/rtl9313_xikestor_sks8300-12x-v1.dts b/target/linux/realtek/dts/rtl9313_xikestor_sks8300-12x-v1.dts index d18883b3cf..65e883c4e3 100644 --- a/target/linux/realtek/dts/rtl9313_xikestor_sks8300-12x-v1.dts +++ b/target/linux/realtek/dts/rtl9313_xikestor_sks8300-12x-v1.dts @@ -90,7 +90,6 @@ los-gpio = <&gpio1 0 GPIO_ACTIVE_HIGH>; mod-def0-gpio = <&gpio1 1 GPIO_ACTIVE_LOW>; tx-disable-gpio = <&gpio1 2 GPIO_ACTIVE_HIGH>; - #thermal-sensor-cells = <0>; }; sfp2: sfp-p2 { @@ -99,7 +98,6 @@ los-gpio = <&gpio1 3 GPIO_ACTIVE_HIGH>; mod-def0-gpio = <&gpio1 4 GPIO_ACTIVE_LOW>; tx-disable-gpio = <&gpio1 5 GPIO_ACTIVE_HIGH>; - #thermal-sensor-cells = <0>; }; sfp3: sfp-p3 { @@ -108,7 +106,6 @@ los-gpio = <&gpio1 6 GPIO_ACTIVE_HIGH>; mod-def0-gpio = <&gpio1 7 GPIO_ACTIVE_LOW>; tx-disable-gpio = <&gpio1 8 GPIO_ACTIVE_HIGH>; - #thermal-sensor-cells = <0>; }; sfp4: sfp-p4 { @@ -117,7 +114,6 @@ los-gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>; mod-def0-gpio = <&gpio1 10 GPIO_ACTIVE_LOW>; tx-disable-gpio = <&gpio1 11 GPIO_ACTIVE_HIGH>; - #thermal-sensor-cells = <0>; }; sfp5: sfp-p5 { @@ -126,7 +122,6 @@ los-gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>; mod-def0-gpio = <&gpio1 13 GPIO_ACTIVE_LOW>; tx-disable-gpio = <&gpio1 14 GPIO_ACTIVE_HIGH>; - #thermal-sensor-cells = <0>; }; sfp6: sfp-p6 { @@ -135,7 +130,6 @@ los-gpio = <&gpio1 21 GPIO_ACTIVE_HIGH>; mod-def0-gpio = <&gpio1 22 GPIO_ACTIVE_LOW>; tx-disable-gpio = <&gpio1 23 GPIO_ACTIVE_HIGH>; - #thermal-sensor-cells = <0>; }; sfp7: sfp-p7 { @@ -144,7 +138,6 @@ los-gpio = <&gpio1 24 GPIO_ACTIVE_HIGH>; mod-def0-gpio = <&gpio1 25 GPIO_ACTIVE_LOW>; tx-disable-gpio = <&gpio1 26 GPIO_ACTIVE_HIGH>; - #thermal-sensor-cells = <0>; }; sfp8: sfp-p8 { @@ -153,7 +146,6 @@ los-gpio = <&gpio1 27 GPIO_ACTIVE_HIGH>; mod-def0-gpio = <&gpio1 28 GPIO_ACTIVE_LOW>; tx-disable-gpio = <&gpio1 29 GPIO_ACTIVE_HIGH>; - #thermal-sensor-cells = <0>; }; sfp9: sfp-p9 { @@ -162,7 +154,6 @@ los-gpio = <&gpio2 3 GPIO_ACTIVE_HIGH>; mod-def0-gpio = <&gpio2 4 GPIO_ACTIVE_LOW>; tx-disable-gpio = <&gpio2 5 GPIO_ACTIVE_HIGH>; - #thermal-sensor-cells = <0>; }; sfp10: sfp-p10 { @@ -171,7 +162,6 @@ los-gpio = <&gpio2 0 GPIO_ACTIVE_HIGH>; mod-def0-gpio = <&gpio2 1 GPIO_ACTIVE_LOW>; tx-disable-gpio = <&gpio2 2 GPIO_ACTIVE_HIGH>; - #thermal-sensor-cells = <0>; }; sfp11: sfp-p11 { @@ -180,7 +170,6 @@ los-gpio = <&gpio2 9 GPIO_ACTIVE_HIGH>; mod-def0-gpio = <&gpio2 10 GPIO_ACTIVE_LOW>; tx-disable-gpio = <&gpio2 11 GPIO_ACTIVE_HIGH>; - #thermal-sensor-cells = <0>; }; sfp12: sfp-p12 { @@ -189,7 +178,6 @@ los-gpio = <&gpio2 6 GPIO_ACTIVE_HIGH>; mod-def0-gpio = <&gpio2 7 GPIO_ACTIVE_LOW>; tx-disable-gpio = <&gpio2 8 GPIO_ACTIVE_HIGH>; - #thermal-sensor-cells = <0>; }; }; diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/Makefile b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/Makefile index 1511dae8ea..21b681918f 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/Makefile +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/Makefile @@ -1,3 +1,3 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_NET_DSA_RTL83XX) += rtl_otto_dsa.o -rtl_otto_dsa-objs := common.o dsa.o rtl838x.o rtl839x.o rtl930x.o rtl931x.o debugfs.o qos.o tc.o +rtl_otto_dsa-objs := common.o dsa.o rtl838x.o rtl839x.o rtl930x.o rtl931x.o debugfs.o qos.o tc.o l3.o diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/common.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/common.c index 88e7984b8b..75529ac5f5 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/common.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/common.c @@ -14,6 +14,7 @@ #include #include +#include "l3.h" #include "rtl-otto.h" int rtldsa_port_get_stp_state(struct rtl838x_switch_priv *priv, int port) @@ -695,7 +696,7 @@ int rtl83xx_packet_cntr_alloc(struct rtl838x_switch_priv *priv) * Called from the L3 layer * The index in the L2 hash table is filled into nh->l2_id; */ -static int rtl83xx_l2_nexthop_add(struct rtl838x_switch_priv *priv, struct rtl83xx_nexthop *nh) +int rtl83xx_l2_nexthop_add(struct rtl838x_switch_priv *priv, struct otto_l3_nexthop *nh) { struct rtl838x_l2_entry e; u64 seed = priv->r->l2_hash_seed(nh->mac, nh->rvid); @@ -762,7 +763,7 @@ static int rtl83xx_l2_nexthop_add(struct rtl838x_switch_priv *priv, struct rtl83 * If it was static, the entire entry is removed, otherwise the nexthop bit is cleared * and we wait until the entry ages out */ -static int rtl83xx_l2_nexthop_rm(struct rtl838x_switch_priv *priv, struct rtl83xx_nexthop *nh) +int rtl83xx_l2_nexthop_rm(struct rtl838x_switch_priv *priv, struct otto_l3_nexthop *nh) { struct rtl838x_l2_entry e; u32 key = nh->l2_id >> 2; @@ -808,689 +809,6 @@ int rtl83xx_port_is_under(const struct net_device *dev, struct rtl838x_switch_pr return -EINVAL; } -static const struct rhashtable_params route_ht_params = { - .key_len = sizeof(u32), - .key_offset = offsetof(struct rtl83xx_route, gw_ip), - .head_offset = offsetof(struct rtl83xx_route, linkage), -}; - -/* Updates an L3 next hop entry in the ROUTING table */ -static int rtl83xx_l3_nexthop_update(struct rtl838x_switch_priv *priv, __be32 ip_addr, u64 mac) -{ - struct rtl83xx_route *r; - struct rhlist_head *tmp, *list; - - rcu_read_lock(); - list = rhltable_lookup(&priv->routes, &ip_addr, route_ht_params); - if (!list) { - rcu_read_unlock(); - return -ENOENT; - } - - rhl_for_each_entry_rcu(r, tmp, list, linkage) { - pr_debug("%s: Setting up fwding: ip %pI4, GW mac %016llx\n", - __func__, &ip_addr, mac); - - /* Reads the ROUTING table entry associated with the route */ - priv->r->route_read(r->id, r); - pr_debug("Route with id %d to %pI4 / %d\n", r->id, &r->dst_ip, r->prefix_len); - - r->nh.mac = r->nh.gw = mac; - r->nh.port = priv->r->port_ignore; - r->nh.id = r->id; - - /* Do we need to explicitly add a DMAC entry with the route's nh index? */ - if (priv->r->set_l3_egress_mac) - priv->r->set_l3_egress_mac(r->id, mac); - - /* Update ROUTING table: map gateway-mac and switch-mac id to route id */ - rtl83xx_l2_nexthop_add(priv, &r->nh); - - r->attr.valid = true; - r->attr.action = ROUTE_ACT_FORWARD; - r->attr.type = 0; - r->attr.hit = false; /* Reset route-used indicator */ - - /* Add PIE entry with dst_ip and prefix_len */ - r->pr.dip = r->dst_ip; - r->pr.dip_m = inet_make_mask(r->prefix_len); - - if (r->is_host_route) { - int slot = priv->r->find_l3_slot(r, false); - - pr_info("%s: Got slot for route: %d\n", __func__, slot); - priv->r->host_route_write(slot, r); - } else { - priv->r->route_write(r->id, r); - r->pr.fwd_sel = true; - r->pr.fwd_data = r->nh.l2_id; - r->pr.fwd_act = PIE_ACT_ROUTE_UC; - } - - if (priv->r->set_l3_nexthop) - priv->r->set_l3_nexthop(r->nh.id, r->nh.l2_id, r->nh.if_id); - - if (r->pr.id < 0) { - r->pr.packet_cntr = rtl83xx_packet_cntr_alloc(priv); - if (r->pr.packet_cntr >= 0) { - pr_info("Using packet counter %d\n", r->pr.packet_cntr); - r->pr.log_sel = true; - r->pr.log_data = r->pr.packet_cntr; - } - priv->r->pie_rule_add(priv, &r->pr); - } else { - int pkts = priv->r->packet_cntr_read(r->pr.packet_cntr); - - pr_debug("%s: total packets: %d\n", __func__, pkts); - - priv->r->pie_rule_write(priv, r->pr.id, &r->pr); - } - } - rcu_read_unlock(); - - return 0; -} - -static int rtl83xx_port_ipv4_resolve(struct rtl838x_switch_priv *priv, - struct net_device *dev, __be32 ip_addr) -{ - struct neighbour *n = neigh_lookup(&arp_tbl, &ip_addr, dev); - int err = 0; - u64 mac; - - if (!n) { - n = neigh_create(&arp_tbl, &ip_addr, dev); - if (IS_ERR(n)) - return PTR_ERR(n); - } - - /* If the neigh is already resolved, then go ahead and - * install the entry, otherwise start the ARP process to - * resolve the neigh. - */ - if (n->nud_state & NUD_VALID) { - mac = ether_addr_to_u64(n->ha); - pr_info("%s: resolved mac: %016llx\n", __func__, mac); - rtl83xx_l3_nexthop_update(priv, ip_addr, mac); - } else { - pr_info("%s: need to wait\n", __func__); - neigh_event_send(n, NULL); - } - - neigh_release(n); - - return err; -} - -struct rtl83xx_walk_data { - struct rtl838x_switch_priv *priv; - int port; -}; - -static int rtl83xx_port_lower_walk(struct net_device *lower, struct netdev_nested_priv *_priv) -{ - struct rtl83xx_walk_data *data = (struct rtl83xx_walk_data *)_priv->data; - struct rtl838x_switch_priv *priv = data->priv; - int ret = 0; - int index; - - index = rtl83xx_port_is_under(lower, priv); - data->port = index; - if (index >= 0) { - pr_debug("Found DSA-port, index %d\n", index); - ret = 1; - } - - return ret; -} - -static int rtl83xx_port_dev_lower_find(struct net_device *dev, struct rtl838x_switch_priv *priv) -{ - struct rtl83xx_walk_data data; - struct netdev_nested_priv _priv; - - data.priv = priv; - data.port = 0; - _priv.data = (void *)&data; - - netdev_walk_all_lower_dev(dev, rtl83xx_port_lower_walk, &_priv); - - return data.port; -} - -static struct rtl83xx_route *rtl83xx_route_alloc(struct rtl838x_switch_priv *priv, u32 ip) -{ - struct rtl83xx_route *r; - int idx = 0, err; - - mutex_lock(&priv->reg_mutex); - - idx = find_first_zero_bit(priv->route_use_bm, MAX_ROUTES); - pr_debug("%s id: %d, ip %pI4\n", __func__, idx, &ip); - - r = kzalloc(sizeof(*r), GFP_KERNEL); - if (!r) { - mutex_unlock(&priv->reg_mutex); - return r; - } - - r->id = idx; - r->gw_ip = ip; - r->pr.id = -1; /* We still need to allocate a rule in HW */ - r->is_host_route = false; - - err = rhltable_insert(&priv->routes, &r->linkage, route_ht_params); - if (err) { - pr_err("Could not insert new rule\n"); - mutex_unlock(&priv->reg_mutex); - goto out_free; - } - - set_bit(idx, priv->route_use_bm); - - mutex_unlock(&priv->reg_mutex); - - return r; - -out_free: - kfree(r); - - return NULL; -} - -static struct rtl83xx_route *rtl83xx_host_route_alloc(struct rtl838x_switch_priv *priv, u32 ip) -{ - struct rtl83xx_route *r; - int idx = 0, err; - - mutex_lock(&priv->reg_mutex); - - idx = find_first_zero_bit(priv->host_route_use_bm, MAX_HOST_ROUTES); - pr_debug("%s id: %d, ip %pI4\n", __func__, idx, &ip); - - r = kzalloc(sizeof(*r), GFP_KERNEL); - if (!r) { - mutex_unlock(&priv->reg_mutex); - return r; - } - - /* We require a unique route ID irrespective of whether it is a prefix or host - * route (on RTL93xx) as we use this ID to associate a DMAC and next-hop entry - */ - r->id = idx + MAX_ROUTES; - - r->gw_ip = ip; - r->pr.id = -1; /* We still need to allocate a rule in HW */ - r->is_host_route = true; - - err = rhltable_insert(&priv->routes, &r->linkage, route_ht_params); - if (err) { - pr_err("Could not insert new rule\n"); - mutex_unlock(&priv->reg_mutex); - goto out_free; - } - - set_bit(idx, priv->host_route_use_bm); - - mutex_unlock(&priv->reg_mutex); - - return r; - -out_free: - kfree(r); - - return NULL; -} - -static void rtl83xx_route_rm(struct rtl838x_switch_priv *priv, struct rtl83xx_route *r) -{ - int id; - - if (rhltable_remove(&priv->routes, &r->linkage, route_ht_params)) - dev_warn(priv->dev, "Could not remove route\n"); - - if (r->is_host_route) { - id = priv->r->find_l3_slot(r, false); - pr_debug("%s: Got id for host route: %d\n", __func__, id); - r->attr.valid = false; - priv->r->host_route_write(id, r); - clear_bit(r->id - MAX_ROUTES, priv->host_route_use_bm); - } else { - /* If there is a HW representation of the route, delete it */ - if (priv->r->route_lookup_hw) { - id = priv->r->route_lookup_hw(r); - pr_info("%s: Got id for prefix route: %d\n", __func__, id); - r->attr.valid = false; - priv->r->route_write(id, r); - } - clear_bit(r->id, priv->route_use_bm); - } - - kfree(r); -} - -static int rtldsa_fib4_check(struct rtl838x_switch_priv *priv, - struct fib_entry_notifier_info *info, - enum fib_event_type event) -{ - struct net_device *ndev = fib_info_nh(info->fi, 0)->fib_nh_dev; - int vlan = is_vlan_dev(ndev) ? vlan_dev_vlan_id(ndev) : 0; - struct fib_nh *nh = fib_info_nh(info->fi, 0); - char gw_message[32] = ""; - - if (nh->fib_nh_gw4) - snprintf(gw_message, sizeof(gw_message), "via %pI4 ", &nh->fib_nh_gw4); - - dev_info(priv->dev, "%s IPv4 route %pI4/%d %s(VLAN %d, MAC %pM)\n", - event == FIB_EVENT_ENTRY_ADD ? "add" : "delete", - &info->dst, info->dst_len, gw_message, vlan, ndev->dev_addr); - - if ((info->type == RTN_BROADCAST) || ipv4_is_loopback(info->dst) || !info->dst) { - dev_warn(priv->dev, "skip loopback/broadcast addresses and default routes\n"); - return -EINVAL; - } - - return 0; -} - -static int rtldsa_fib4_del(struct rtl838x_switch_priv *priv, - struct fib_entry_notifier_info *info) -{ - struct fib_nh *nh = fib_info_nh(info->fi, 0); - struct rhlist_head *tmp, *list; - struct rtl83xx_route *route; - - if (rtldsa_fib4_check(priv, info, FIB_EVENT_ENTRY_DEL)) - return 0; - - rcu_read_lock(); - list = rhltable_lookup(&priv->routes, &nh->fib_nh_gw4, route_ht_params); - if (!list) { - rcu_read_unlock(); - dev_err(priv->dev, "no such gateway: %pI4\n", &nh->fib_nh_gw4); - return -ENOENT; - } - rhl_for_each_entry_rcu(route, tmp, list, linkage) { - if (route->dst_ip == info->dst && route->prefix_len == info->dst_len) { - dev_info(priv->dev, "found a route with id %d, nh-id %d\n", - route->id, route->nh.id); - break; - } - } - rcu_read_unlock(); - - rtl83xx_l2_nexthop_rm(priv, &route->nh); - - dev_info(priv->dev, "releasing packet counter %d\n", route->pr.packet_cntr); - set_bit(route->pr.packet_cntr, priv->packet_cntr_use_bm); - priv->r->pie_rule_rm(priv, &route->pr); - - rtl83xx_route_rm(priv, route); - - nh->fib_nh_flags &= ~RTNH_F_OFFLOAD; - - return 0; -} - -/* On the RTL93xx, an L3 termination endpoint MAC address on which the router waits - * for packets to be routed needs to be allocated. - */ -static int rtl83xx_alloc_router_mac(struct rtl838x_switch_priv *priv, u64 mac) -{ - int free_mac = -1; - struct rtl93xx_rt_mac m; - - mutex_lock(&priv->reg_mutex); - for (int i = 0; i < MAX_ROUTER_MACS; i++) { - priv->r->get_l3_router_mac(i, &m); - if (free_mac < 0 && !m.valid) { - free_mac = i; - continue; - } - if (m.valid && m.mac == mac) { - free_mac = i; - break; - } - } - - if (free_mac < 0) { - pr_err("No free router MACs, cannot offload\n"); - mutex_unlock(&priv->reg_mutex); - return -1; - } - - m.valid = true; - m.mac = mac; - m.p_type = 0; /* An individual port, not a trunk port */ - m.p_id = 0x3f; /* Listen on any port */ - m.p_id_mask = 0; - m.vid = 0; /* Listen on any VLAN... */ - m.vid_mask = 0; /* ... so mask needs to be 0 */ - m.mac_mask = 0xffffffffffffULL; /* We want an exact match of the interface MAC */ - m.action = L3_FORWARD; /* Route the packet */ - priv->r->set_l3_router_mac(free_mac, &m); - - mutex_unlock(&priv->reg_mutex); - - return 0; -} - -static int rtl83xx_alloc_egress_intf(struct rtl838x_switch_priv *priv, u64 mac, int vlan) -{ - int free_mac = -1; - struct rtl838x_l3_intf intf; - u64 m; - - mutex_lock(&priv->reg_mutex); - for (int i = 0; i < MAX_SMACS; i++) { - m = priv->r->get_l3_egress_mac(L3_EGRESS_DMACS + i); - if (free_mac < 0 && !m) { - free_mac = i; - continue; - } - if (m == mac) { - mutex_unlock(&priv->reg_mutex); - return i; - } - } - - if (free_mac < 0) { - pr_err("No free egress interface, cannot offload\n"); - return -1; - } - - /* Set up default egress interface 1 */ - intf.vid = vlan; - intf.smac_idx = free_mac; - intf.ip4_mtu_id = 1; - intf.ip6_mtu_id = 1; - intf.ttl_scope = 1; /* TTL */ - intf.hl_scope = 1; /* Hop Limit */ - intf.ip4_icmp_redirect = intf.ip6_icmp_redirect = 2; /* FORWARD */ - intf.ip4_pbr_icmp_redirect = intf.ip6_pbr_icmp_redirect = 2; /* FORWARD; */ - priv->r->set_l3_egress_intf(free_mac, &intf); - - priv->r->set_l3_egress_mac(L3_EGRESS_DMACS + free_mac, mac); - - mutex_unlock(&priv->reg_mutex); - - return free_mac; -} - -static int rtldsa_fib4_add(struct rtl838x_switch_priv *priv, - struct fib_entry_notifier_info *info) -{ - struct net_device *ndev = fib_info_nh(info->fi, 0)->fib_nh_dev; - int vlan = is_vlan_dev(ndev) ? vlan_dev_vlan_id(ndev) : 0; - struct fib_nh *nh = fib_info_nh(info->fi, 0); - struct rtl83xx_route *route; - int port; - - if (rtldsa_fib4_check(priv, info, FIB_EVENT_ENTRY_ADD)) - return 0; - - port = rtl83xx_port_dev_lower_find(ndev, priv); - if (port < 0) { - dev_err(priv->dev, "lower interface %s not found\n", ndev->name); - return -ENODEV; - } - - /* Allocate route or host-route entry (if hardware supports this) */ - if (info->dst_len == 32 && priv->r->host_route_write) - route = rtl83xx_host_route_alloc(priv, nh->fib_nh_gw4); - else - route = rtl83xx_route_alloc(priv, nh->fib_nh_gw4); - - if (route) - dev_info(priv->dev, "route hashtable extended for gw %pI4\n", &nh->fib_nh_gw4); - else { - dev_err(priv->dev, "could not extend route hashtable for gw %pI4\n", &nh->fib_nh_gw4); - return -ENOSPC; - } - - route->dst_ip = info->dst; - route->prefix_len = info->dst_len; - route->nh.rvid = vlan; - - if (priv->r->set_l3_router_mac) { - u64 mac = ether_addr_to_u64(ndev->dev_addr); - - pr_debug("Local route and router MAC %pM\n", ndev->dev_addr); - if (rtl83xx_alloc_router_mac(priv, mac)) - goto out_free_rt; - - /* vid = 0: Do not care about VID */ - route->nh.if_id = rtl83xx_alloc_egress_intf(priv, mac, vlan); - if (route->nh.if_id < 0) - goto out_free_rmac; - - if (!nh->fib_nh_gw4) { - int slot; - - route->nh.mac = mac; - route->nh.port = priv->r->port_ignore; - route->attr.valid = true; - route->attr.action = ROUTE_ACT_TRAP2CPU; - route->attr.type = 0; - - slot = priv->r->find_l3_slot(route, false); - pr_debug("%s: Got slot for route: %d\n", __func__, slot); - priv->r->host_route_write(slot, route); - } - } - - /* We need to resolve the mac address of the GW */ - if (nh->fib_nh_gw4) - rtl83xx_port_ipv4_resolve(priv, ndev, nh->fib_nh_gw4); - - nh->fib_nh_flags |= RTNH_F_OFFLOAD; - - return 0; - -out_free_rmac: -out_free_rt: - return 0; -} - -static int rtl83xx_fib6_add(struct rtl838x_switch_priv *priv, - struct fib6_entry_notifier_info *info) -{ - pr_debug("In %s\n", __func__); -/* nh->fib_nh_flags |= RTNH_F_OFFLOAD; */ - - return 0; -} - -struct net_event_work { - struct work_struct work; - struct rtl838x_switch_priv *priv; - u64 mac; - u32 gw_addr; -}; - -static void rtl83xx_net_event_work_do(struct work_struct *work) -{ - struct net_event_work *net_work = - container_of(work, struct net_event_work, work); - struct rtl838x_switch_priv *priv = net_work->priv; - - rtl83xx_l3_nexthop_update(priv, net_work->gw_addr, net_work->mac); - - kfree(net_work); -} - -static int rtl83xx_netevent_event(struct notifier_block *this, - unsigned long event, void *ptr) -{ - struct rtl838x_switch_priv *priv; - struct net_device *dev; - struct neighbour *n = ptr; - int err, port; - struct net_event_work *net_work; - - priv = container_of(this, struct rtl838x_switch_priv, ne_nb); - - switch (event) { - case NETEVENT_NEIGH_UPDATE: - /* ignore events for HW with missing L3 offloading implementation */ - if (!priv->r->l3_setup) - return NOTIFY_DONE; - - if (n->tbl != &arp_tbl) - return NOTIFY_DONE; - dev = n->dev; - port = rtl83xx_port_dev_lower_find(dev, priv); - if (port < 0 || !(n->nud_state & NUD_VALID)) { - pr_debug("%s: Neigbour invalid, not updating\n", __func__); - return NOTIFY_DONE; - } - - net_work = kzalloc(sizeof(*net_work), GFP_ATOMIC); - if (!net_work) - return NOTIFY_BAD; - - INIT_WORK(&net_work->work, rtl83xx_net_event_work_do); - net_work->priv = priv; - - net_work->mac = ether_addr_to_u64(n->ha); - net_work->gw_addr = *(__be32 *)n->primary_key; - - pr_debug("%s: updating neighbour on port %d, mac %016llx\n", - __func__, port, net_work->mac); - queue_work(priv->wq, &net_work->work); - if (err) - netdev_warn(dev, "failed to handle neigh update (err %d)\n", err); - break; - } - - return NOTIFY_DONE; -} - -struct rtl83xx_fib_event_work { - struct work_struct work; - union { - struct fib_entry_notifier_info fen_info; - struct fib6_entry_notifier_info fen6_info; - struct fib_rule_notifier_info fr_info; - }; - struct rtl838x_switch_priv *priv; - bool is_fib6; - unsigned long event; -}; - -static void rtl83xx_fib_event_work_do(struct work_struct *work) -{ - struct rtl83xx_fib_event_work *fib_work = - container_of(work, struct rtl83xx_fib_event_work, work); - struct rtl838x_switch_priv *priv = fib_work->priv; - struct fib_rule *rule; - int err; - - /* Protect internal structures from changes */ - rtnl_lock(); - pr_debug("%s: doing work, event %ld\n", __func__, fib_work->event); - switch (fib_work->event) { - case FIB_EVENT_ENTRY_ADD: - case FIB_EVENT_ENTRY_REPLACE: - case FIB_EVENT_ENTRY_APPEND: - if (fib_work->is_fib6) - err = rtl83xx_fib6_add(priv, &fib_work->fen6_info); - else - err = rtldsa_fib4_add(priv, &fib_work->fen_info); - if (err) - dev_err(priv->dev, "fib_add() failed\n"); - - fib_info_put(fib_work->fen_info.fi); - break; - case FIB_EVENT_ENTRY_DEL: - err = rtldsa_fib4_del(priv, &fib_work->fen_info); - if (err) - dev_err(priv->dev, "fib_del() failed\n"); - - fib_info_put(fib_work->fen_info.fi); - break; - case FIB_EVENT_RULE_ADD: - case FIB_EVENT_RULE_DEL: - rule = fib_work->fr_info.rule; - if (!fib4_rule_default(rule)) - pr_err("%s: FIB4 default rule failed\n", __func__); - fib_rule_put(rule); - break; - } - rtnl_unlock(); - kfree(fib_work); -} - -/* Called with rcu_read_lock() */ -static int rtl83xx_fib_event(struct notifier_block *this, unsigned long event, void *ptr) -{ - struct fib_notifier_info *info = ptr; - struct rtl838x_switch_priv *priv; - struct rtl83xx_fib_event_work *fib_work; - - if ((info->family != AF_INET && info->family != AF_INET6 && - info->family != RTNL_FAMILY_IPMR && - info->family != RTNL_FAMILY_IP6MR)) - return NOTIFY_DONE; - - priv = container_of(this, struct rtl838x_switch_priv, fib_nb); - - /* ignore FIB events for HW with missing L3 offloading implementation */ - if (!priv->r->l3_setup) - return NOTIFY_DONE; - - fib_work = kzalloc(sizeof(*fib_work), GFP_ATOMIC); - if (!fib_work) - return NOTIFY_BAD; - - INIT_WORK(&fib_work->work, rtl83xx_fib_event_work_do); - fib_work->priv = priv; - fib_work->event = event; - fib_work->is_fib6 = false; - - switch (event) { - case FIB_EVENT_ENTRY_ADD: - case FIB_EVENT_ENTRY_REPLACE: - case FIB_EVENT_ENTRY_APPEND: - case FIB_EVENT_ENTRY_DEL: - pr_debug("%s: FIB_ENTRY ADD/DEL, event %ld\n", __func__, event); - if (info->family == AF_INET) { - struct fib_entry_notifier_info *fen_info = ptr; - - if (fen_info->fi->fib_nh_is_v6) { - NL_SET_ERR_MSG_MOD(info->extack, - "IPv6 gateway with IPv4 route is not supported"); - kfree(fib_work); - return notifier_from_errno(-EINVAL); - } - - memcpy(&fib_work->fen_info, ptr, sizeof(fib_work->fen_info)); - /* Take referece on fib_info to prevent it from being - * freed while work is queued. Release it afterwards. - */ - fib_info_hold(fib_work->fen_info.fi); - - } else if (info->family == AF_INET6) { - //struct fib6_entry_notifier_info *fen6_info = ptr; - pr_warn("%s: FIB_RULE ADD/DEL for IPv6 not supported\n", __func__); - kfree(fib_work); - return NOTIFY_DONE; - } - break; - - case FIB_EVENT_RULE_ADD: - case FIB_EVENT_RULE_DEL: - pr_debug("%s: FIB_RULE ADD/DEL, event: %ld\n", __func__, event); - memcpy(&fib_work->fr_info, ptr, sizeof(fib_work->fr_info)); - fib_rule_get(fib_work->fr_info.rule); - break; - } - - queue_work(priv->wq, &fib_work->work); - - return NOTIFY_DONE; -} - static irqreturn_t rtldsa_switch_irq(int irq, void *dev_id) { struct rtl838x_switch_priv *priv; @@ -1661,29 +979,9 @@ static int rtl83xx_sw_probe(struct platform_device *pdev) for (int i = 0; i < 4; i++) priv->mirror_group_ports[i] = -1; - /* Initialize hash table for L3 routing */ - rhltable_init(&priv->routes, &route_ht_params); - - /* Register netevent notifier callback to catch notifications about neighboring - * changes to update nexthop entries for L3 routing. - */ - priv->ne_nb.notifier_call = rtl83xx_netevent_event; - if (register_netevent_notifier(&priv->ne_nb)) { - priv->ne_nb.notifier_call = NULL; - dev_err(dev, "Failed to register netevent notifier\n"); - goto err_register_ne_nb; - } - - priv->fib_nb.notifier_call = rtl83xx_fib_event; - - /* Register Forwarding Information Base notifier to offload routes where - * possible - * Only FIBs pointing to our own netdevs are programmed into - * the device, so no need to pass a callback. - */ - err = register_fib_notifier(&init_net, &priv->fib_nb, NULL, NULL); + err = otto_l3_probe(dev, priv); if (err) - goto err_register_fib_nb; + goto err_register_l3; /* TODO: put this into l2_setup() */ switch (soc_info.family) { @@ -1708,9 +1006,7 @@ static int rtl83xx_sw_probe(struct platform_device *pdev) return 0; -err_register_fib_nb: - unregister_netevent_notifier(&priv->ne_nb); -err_register_ne_nb: +err_register_l3: dsa_switch_shutdown(priv->ds); err_register_switch: destroy_workqueue(priv->wq); @@ -1757,8 +1053,7 @@ static void rtl83xx_sw_remove(struct platform_device *pdev) * work items to avoid them still accessing the DSA structures * when they are getting shut down. */ - unregister_fib_notifier(&init_net, &priv->fib_nb); - unregister_netevent_notifier(&priv->ne_nb); + otto_l3_remove(priv); cancel_delayed_work_sync(&priv->counters_work); dsa_switch_shutdown(priv->ds); diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c new file mode 100644 index 0000000000..1d8390da3c --- /dev/null +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c @@ -0,0 +1,1180 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "l3.h" +#include "rtl-otto.h" + +struct otto_l3_net_event_work { + struct work_struct work; + struct otto_l3_ctrl *ctrl; + u64 mac; + u32 gw_addr; +}; + +struct otto_l3_fib_event_work { + struct work_struct work; + struct otto_l3_ctrl *ctrl; + union { + struct fib_entry_notifier_info fen_info; + struct fib6_entry_notifier_info fen6_info; + struct fib_rule_notifier_info fr_info; + }; + bool is_fib6; + unsigned long event; +}; + +struct otto_l3_walk_data { + struct otto_l3_ctrl *ctrl; + int port; +}; + +static void otto_l3_838x_route_read(struct otto_l3_ctrl *ctrl, int idx, struct otto_l3_route *rt) +{ + struct table_reg *r = rtl_table_get(RTL8380_TBL_1, 2); + + rtl_table_read(r, idx); + + /* The table has a size of 2 registers */ + rt->nh.gw = sw_r32(rtl_table_data(r, 0)); + rt->nh.gw <<= 32; + rt->nh.gw |= sw_r32(rtl_table_data(r, 1)); + + rtl_table_release(r); +} + +static void otto_l3_838x_route_write(struct otto_l3_ctrl *ctrl, int idx, struct otto_l3_route *rt) +{ + struct table_reg *r = rtl_table_get(RTL8380_TBL_1, 2); + + sw_w32(rt->nh.gw >> 32, rtl_table_data(r, 0)); + sw_w32(rt->nh.gw, rtl_table_data(r, 1)); + rtl_table_write(r, idx); + + rtl_table_release(r); +} + +static void otto_l3_839x_route_read(struct otto_l3_ctrl *ctrl, int idx, struct otto_l3_route *rt) +{ + struct table_reg *r = rtl_table_get(RTL8390_TBL_1, 2); + u64 v; + + rtl_table_read(r, idx); + + /* The table has a size of 2 registers */ + v = sw_r32(rtl_table_data(r, 0)); + v <<= 32; + v |= sw_r32(rtl_table_data(r, 1)); + rt->switch_mac_id = (v >> 12) & 0xf; + rt->nh.gw = v >> 16; + + rtl_table_release(r); +} + +static void otto_l3_839x_route_write(struct otto_l3_ctrl *ctrl, int idx, struct otto_l3_route *rt) +{ + struct table_reg *r = rtl_table_get(RTL8390_TBL_1, 2); + u32 v; + + sw_w32(rt->nh.gw >> 16, rtl_table_data(r, 0)); + v = rt->nh.gw << 16; + v |= rt->switch_mac_id << 12; + sw_w32(v, rtl_table_data(r, 1)); + rtl_table_write(r, idx); + + rtl_table_release(r); +} + +/* + * Reads a MAC entry for L3 termination as entry point for routing from the hardware table. + * idx is the index into the L3_ROUTER_MAC table + */ +__maybe_unused +static void otto_l3_930x_get_router_mac(struct otto_l3_ctrl *ctrl, + u32 idx, struct otto_l3_router_mac *m) +{ + struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 0); + u32 v, w; + + rtl_table_read(r, idx); + /* The table has a size of 7 registers, 64 entries */ + v = sw_r32(rtl_table_data(r, 0)); + w = sw_r32(rtl_table_data(r, 3)); + m->valid = !!(v & BIT(20)); + if (!m->valid) + goto out; + + m->p_type = !!(v & BIT(19)); + m->p_id = (v >> 13) & 0x3f; /* trunk id of port */ + m->vid = v & 0xfff; + m->vid_mask = w & 0xfff; + m->action = sw_r32(rtl_table_data(r, 6)) & 0x7; + m->mac_mask = ((((u64)sw_r32(rtl_table_data(r, 5))) << 32) & 0xffffffffffffULL) | + (sw_r32(rtl_table_data(r, 4))); + m->mac = ((((u64)sw_r32(rtl_table_data(r, 1))) << 32) & 0xffffffffffffULL) | + (sw_r32(rtl_table_data(r, 2))); + /* Bits L3_INTF and BMSK_L3_INTF are 0 */ + +out: + rtl_table_release(r); +} + +/* + * Writes a MAC entry for L3 termination as entry point for routing into the hardware table + * idx is the index into the L3_ROUTER_MAC table + */ +__maybe_unused +static void otto_l3_930x_set_router_mac(struct otto_l3_ctrl *ctrl, + u32 idx, struct otto_l3_router_mac *m) +{ + struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 0); + u32 v, w; + + /* The table has a size of 7 registers, 64 entries */ + v = BIT(20); /* mac entry valid, port type is 0: individual */ + v |= (m->p_id & 0x3f) << 13; + v |= (m->vid & 0xfff); /* Set the interface_id to the vlan id */ + + w = m->vid_mask; + w |= (m->p_id_mask & 0x3f) << 13; + + sw_w32(v, rtl_table_data(r, 0)); + sw_w32(w, rtl_table_data(r, 3)); + + /* Set MAC address, L3_INTF (bit 12 in register 1) needs to be 0 */ + sw_w32((u32)(m->mac), rtl_table_data(r, 2)); + sw_w32(m->mac >> 32, rtl_table_data(r, 1)); + + /* Set MAC address mask, BMSK_L3_INTF (bit 12 in register 5) needs to be 0 */ + sw_w32((u32)(m->mac_mask >> 32), rtl_table_data(r, 4)); + sw_w32((u32)m->mac_mask, rtl_table_data(r, 5)); + + sw_w32(m->action & 0x7, rtl_table_data(r, 6)); + + dev_dbg(ctrl->dev, "writing index %d: %08x %08x %08x %08x %08x %08x %08x\n", idx, + sw_r32(rtl_table_data(r, 0)), sw_r32(rtl_table_data(r, 1)), sw_r32(rtl_table_data(r, 2)), + sw_r32(rtl_table_data(r, 3)), sw_r32(rtl_table_data(r, 4)), sw_r32(rtl_table_data(r, 5)), + sw_r32(rtl_table_data(r, 6)) + ); + rtl_table_write(r, idx); + rtl_table_release(r); +} + +/* Destination MAC and L3 egress interface ID of a nexthop entry from the SoC's L3_NEXTHOP table */ +__maybe_unused +static void otto_l3_930x_get_nexthop(struct otto_l3_ctrl *ctrl, + int idx, u16 *dmac_id, u16 *interface) +{ + struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 3); + u32 v; + + rtl_table_read(r, idx); + /* The table has a size of 1 register */ + v = sw_r32(rtl_table_data(r, 0)); + rtl_table_release(r); + + *dmac_id = (v >> 7) & 0x7fff; + *interface = v & 0x7f; +} + +/* + * Set the destination MAC and L3 egress interface ID for a nexthop entry in the SoC's L3_NEXTHOP + * table. The nexthop entry is identified by idx. dmac_id is the reference to the L2 entry in the + * L2 forwarding table, special values are + * 0x7ffe: TRAP2CPU + * 0x7ffd: TRAP2MASTERCPU + * 0x7fff: DMAC_ID_DROP + */ +__maybe_unused +static void otto_l3_930x_set_nexthop(struct otto_l3_ctrl *ctrl, + int idx, u16 dmac_id, u16 interface) +{ + /* Access L3_NEXTHOP table (3) via register RTL9300_TBL_1 */ + struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 3); + + dev_dbg(ctrl->dev, "Writing to L3_NEXTHOP table, index %d, dmac_id %d, interface %d\n", + idx, dmac_id, interface); + sw_w32(((dmac_id & 0x7fff) << 7) | (interface & 0x7f), rtl_table_data(r, 0)); + + dev_dbg(ctrl->dev, "value at index 0: %08x\n", sw_r32(rtl_table_data(r, 0))); + rtl_table_write(r, idx); + rtl_table_release(r); +} + + +/* Read a prefix route entry from the L3_PREFIX_ROUTE_IPUC table + * We currently only support IPv4 and IPv6 unicast route + */ +__maybe_unused +static void otto_l3_930x_route_read(struct otto_l3_ctrl *ctrl, int idx, struct otto_l3_route *rt) +{ + struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 2); + bool host_route, default_route; + struct in6_addr ip6_m; + u32 v, ip4_m; + + dev_dbg(ctrl->dev, "%s\n", __func__); + + rtl_table_read(r, idx); + /* The table has a size of 11 registers */ + rt->attr.valid = !!(sw_r32(rtl_table_data(r, 0)) & BIT(31)); + if (!rt->attr.valid) + goto out; + + rt->attr.type = (sw_r32(rtl_table_data(r, 0)) >> 29) & 0x3; + + v = sw_r32(rtl_table_data(r, 10)); + host_route = !!(v & BIT(21)); + default_route = !!(v & BIT(20)); + rt->prefix_len = -1; + dev_dbg(ctrl->dev, "host route %d, default_route %d\n", host_route, default_route); + + switch (rt->attr.type) { + case 0: /* IPv4 Unicast route */ + rt->dst_ip = sw_r32(rtl_table_data(r, 4)); + ip4_m = sw_r32(rtl_table_data(r, 9)); + dev_dbg(ctrl->dev, "Read ip4 mask: %08x\n", ip4_m); + rt->prefix_len = host_route ? 32 : -1; + rt->prefix_len = (rt->prefix_len < 0 && default_route) ? 0 : -1; + if (rt->prefix_len < 0) + rt->prefix_len = inet_mask_len(ip4_m); + break; + case 2: /* IPv6 Unicast route */ + ipv6_addr_set(&rt->dst_ip6, + sw_r32(rtl_table_data(r, 1)), sw_r32(rtl_table_data(r, 2)), + sw_r32(rtl_table_data(r, 3)), sw_r32(rtl_table_data(r, 4))); + ipv6_addr_set(&ip6_m, + sw_r32(rtl_table_data(r, 6)), sw_r32(rtl_table_data(r, 7)), + sw_r32(rtl_table_data(r, 8)), sw_r32(rtl_table_data(r, 9))); + rt->prefix_len = host_route ? 128 : 0; + rt->prefix_len = (rt->prefix_len < 0 && default_route) ? 0 : -1; + if (rt->prefix_len < 0) + rt->prefix_len = find_last_bit((unsigned long *)&ip6_m.s6_addr32, + 128); + break; + case 1: /* IPv4 Multicast route */ + case 3: /* IPv6 Multicast route */ + dev_warn(ctrl->dev, "route type not supported\n"); + goto out; + } + + rt->attr.hit = !!(v & BIT(22)); + rt->attr.action = (v >> 18) & 3; + rt->nh.id = (v >> 7) & 0x7ff; + rt->attr.ttl_dec = !!(v & BIT(6)); + rt->attr.ttl_check = !!(v & BIT(5)); + rt->attr.dst_null = !!(v & BIT(4)); + rt->attr.qos_as = !!(v & BIT(3)); + rt->attr.qos_prio = v & 0x7; + dev_dbg(ctrl->dev, "index %d is valid: %d\n", idx, rt->attr.valid); + dev_dbg(ctrl->dev, "next_hop: %d, hit: %d, action :%d, ttl_dec %d, ttl_check %d, dst_null %d\n", + rt->nh.id, rt->attr.hit, rt->attr.action, + rt->attr.ttl_dec, rt->attr.ttl_check, rt->attr.dst_null); + dev_dbg(ctrl->dev, "GW: %pI4, prefix_len: %d\n", &rt->dst_ip, rt->prefix_len); +out: + rtl_table_release(r); +} + +__maybe_unused +static void otto_l3_930x_net6_mask(int prefix_len, struct in6_addr *ip6_m) +{ + int o, b; + /* Define network mask */ + o = prefix_len >> 3; + b = prefix_len & 0x7; + memset(ip6_m->s6_addr, 0xff, o); + ip6_m->s6_addr[o] |= b ? 0xff00 >> b : 0x00; +} + +/* + * Look up the index of a prefix route in the routing table CAM for unicast IPv4/6 routes + * using hardware offload. + */ +__maybe_unused +static int otto_l3_930x_route_lookup_hw(struct otto_l3_ctrl *ctrl, struct otto_l3_route *rt) +{ + struct in6_addr ip6_m; + u32 ip4_m, v; + + if (rt->attr.type == 1 || rt->attr.type == 3) /* Hardware only supports UC routes */ + return -1; + + sw_w32_mask(0x3 << 19, rt->attr.type, RTL930X_L3_HW_LU_KEY_CTRL); + if (rt->attr.type) { /* IPv6 */ + otto_l3_930x_net6_mask(rt->prefix_len, &ip6_m); + for (int i = 0; i < 4; i++) + sw_w32(rt->dst_ip6.s6_addr32[0] & ip6_m.s6_addr32[0], + RTL930X_L3_HW_LU_KEY_IP_CTRL + (i << 2)); + } else { /* IPv4 */ + ip4_m = inet_make_mask(rt->prefix_len); + sw_w32(0, RTL930X_L3_HW_LU_KEY_IP_CTRL); + sw_w32(0, RTL930X_L3_HW_LU_KEY_IP_CTRL + 4); + sw_w32(0, RTL930X_L3_HW_LU_KEY_IP_CTRL + 8); + v = rt->dst_ip & ip4_m; + dev_dbg(ctrl->dev, "searching for %pI4\n", &v); + sw_w32(v, RTL930X_L3_HW_LU_KEY_IP_CTRL + 12); + } + + /* Execute CAM lookup in SoC */ + sw_w32(BIT(15), RTL930X_L3_HW_LU_CTRL); + + /* Wait until execute bit clears and result is ready */ + do { + v = sw_r32(RTL930X_L3_HW_LU_CTRL); + } while (v & BIT(15)); + + dev_dbg(ctrl->dev, "found: %d, index: %d\n", !!(v & BIT(14)), v & 0x1ff); + + /* Test if search successful (BIT 14 set) */ + if (v & BIT(14)) + return v & 0x1ff; + + return -1; +} + +/* Write a prefix route into the routing table CAM at position idx + * Currently only IPv4 and IPv6 unicast routes are supported + */ +__maybe_unused +static void otto_l3_930x_route_write(struct otto_l3_ctrl *ctrl, int idx, struct otto_l3_route *rt) +{ + /* Access L3_PREFIX_ROUTE_IPUC table (2) via register RTL9300_TBL_1 */ + /* The table has a size of 11 registers (20 for MC) */ + struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 2); + struct in6_addr ip6_m; + u32 v, ip4_m; + + dev_dbg(ctrl->dev, "%s\n", __func__); + dev_dbg(ctrl->dev, "index %d is valid: %d\n", idx, rt->attr.valid); + dev_dbg(ctrl->dev, "nexthop: %d, hit: %d, action :%d, ttl_dec %d, ttl_check %d, dst_null %d\n", + rt->nh.id, rt->attr.hit, rt->attr.action, + rt->attr.ttl_dec, rt->attr.ttl_check, rt->attr.dst_null); + dev_dbg(ctrl->dev, "GW: %pI4, prefix_len: %d\n", &rt->dst_ip, rt->prefix_len); + + v = rt->attr.valid ? BIT(31) : 0; + v |= (rt->attr.type & 0x3) << 29; + sw_w32(v, rtl_table_data(r, 0)); + + v = rt->attr.hit ? BIT(22) : 0; + v |= (rt->attr.action & 0x3) << 18; + v |= (rt->nh.id & 0x7ff) << 7; + v |= rt->attr.ttl_dec ? BIT(6) : 0; + v |= rt->attr.ttl_check ? BIT(5) : 0; + v |= rt->attr.dst_null ? BIT(6) : 0; + v |= rt->attr.qos_as ? BIT(6) : 0; + v |= rt->attr.qos_prio & 0x7; + v |= rt->prefix_len == 0 ? BIT(20) : 0; /* set default route bit */ + + /* set bit mask for entry type always to 0x3 */ + sw_w32(0x3 << 29, rtl_table_data(r, 5)); + + switch (rt->attr.type) { + case 0: /* IPv4 Unicast route */ + sw_w32(0, rtl_table_data(r, 1)); + sw_w32(0, rtl_table_data(r, 2)); + sw_w32(0, rtl_table_data(r, 3)); + sw_w32(rt->dst_ip, rtl_table_data(r, 4)); + + v |= rt->prefix_len == 32 ? BIT(21) : 0; /* set host-route bit */ + ip4_m = inet_make_mask(rt->prefix_len); + sw_w32(0, rtl_table_data(r, 6)); + sw_w32(0, rtl_table_data(r, 7)); + sw_w32(0, rtl_table_data(r, 8)); + sw_w32(ip4_m, rtl_table_data(r, 9)); + break; + case 2: /* IPv6 Unicast route */ + sw_w32(rt->dst_ip6.s6_addr32[0], rtl_table_data(r, 1)); + sw_w32(rt->dst_ip6.s6_addr32[1], rtl_table_data(r, 2)); + sw_w32(rt->dst_ip6.s6_addr32[2], rtl_table_data(r, 3)); + sw_w32(rt->dst_ip6.s6_addr32[3], rtl_table_data(r, 4)); + + v |= rt->prefix_len == 128 ? BIT(21) : 0; /* set host-route bit */ + + otto_l3_930x_net6_mask(rt->prefix_len, &ip6_m); + + sw_w32(ip6_m.s6_addr32[0], rtl_table_data(r, 6)); + sw_w32(ip6_m.s6_addr32[1], rtl_table_data(r, 7)); + sw_w32(ip6_m.s6_addr32[2], rtl_table_data(r, 8)); + sw_w32(ip6_m.s6_addr32[3], rtl_table_data(r, 9)); + break; + case 1: /* IPv4 Multicast route */ + case 3: /* IPv6 Multicast route */ + dev_warn(ctrl->dev, "route type not supported\n"); + rtl_table_release(r); + return; + } + sw_w32(v, rtl_table_data(r, 10)); + + dev_dbg(ctrl->dev, "%08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x\n", + sw_r32(rtl_table_data(r, 0)), sw_r32(rtl_table_data(r, 1)), sw_r32(rtl_table_data(r, 2)), + sw_r32(rtl_table_data(r, 3)), sw_r32(rtl_table_data(r, 4)), sw_r32(rtl_table_data(r, 5)), + sw_r32(rtl_table_data(r, 6)), sw_r32(rtl_table_data(r, 7)), sw_r32(rtl_table_data(r, 8)), + sw_r32(rtl_table_data(r, 9)), sw_r32(rtl_table_data(r, 10))); + + rtl_table_write(r, idx); + rtl_table_release(r); +} + +static int otto_l3_port_lower_walk(struct net_device *lower, struct netdev_nested_priv *_priv) +{ + struct otto_l3_walk_data *data = (struct otto_l3_walk_data *)_priv->data; + struct rtl838x_switch_priv *priv = data->ctrl->priv; + struct otto_l3_ctrl *ctrl = data->ctrl; + int ret = 0; + int index; + + index = rtl83xx_port_is_under(lower, priv); + data->port = index; + if (index >= 0) { + dev_dbg(ctrl->dev, "Found DSA-port, index %d\n", index); + ret = 1; + } + + return ret; +} + +static int otto_l3_port_dev_lower_find(struct net_device *dev, struct otto_l3_ctrl *ctrl) +{ + struct otto_l3_walk_data data; + struct netdev_nested_priv _priv; + + data.ctrl = ctrl; + data.port = 0; + _priv.data = (void *)&data; + + netdev_walk_all_lower_dev(dev, otto_l3_port_lower_walk, &_priv); + + return data.port; +} + +/* On the RTL93xx, an L3 termination endpoint MAC address on which the router waits + * for packets to be routed needs to be allocated. + */ +static int otto_l3_alloc_router_mac(struct otto_l3_ctrl *ctrl, u64 mac) +{ + struct rtl838x_switch_priv *priv = ctrl->priv; + struct otto_l3_router_mac m; + int free_mac = -1; + + mutex_lock(&priv->reg_mutex); + for (int i = 0; i < MAX_ROUTER_MACS; i++) { + ctrl->cfg->get_router_mac(ctrl, i, &m); + if (free_mac < 0 && !m.valid) { + free_mac = i; + continue; + } + if (m.valid && m.mac == mac) { + free_mac = i; + break; + } + } + + if (free_mac < 0) { + dev_err(ctrl->dev, "No free router MACs, cannot offload\n"); + mutex_unlock(&priv->reg_mutex); + return -1; + } + + m.valid = true; + m.mac = mac; + m.p_type = 0; /* An individual port, not a trunk port */ + m.p_id = 0x3f; /* Listen on any port */ + m.p_id_mask = 0; + m.vid = 0; /* Listen on any VLAN... */ + m.vid_mask = 0; /* ... so mask needs to be 0 */ + m.mac_mask = 0xffffffffffffULL; /* We want an exact match of the interface MAC */ + m.action = L3_FORWARD; /* Route the packet */ + ctrl->cfg->set_router_mac(ctrl, free_mac, &m); + + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +static int otto_l3_alloc_egress_intf(struct otto_l3_ctrl *ctrl, u64 mac, int vlan) +{ + struct rtl838x_switch_priv *priv = ctrl->priv; + struct rtl838x_l3_intf intf; + int free_mac = -1; + u64 m; + + mutex_lock(&priv->reg_mutex); + for (int i = 0; i < MAX_SMACS; i++) { + m = priv->r->get_l3_egress_mac(L3_EGRESS_DMACS + i); + if (free_mac < 0 && !m) { + free_mac = i; + continue; + } + if (m == mac) { + mutex_unlock(&priv->reg_mutex); + return i; + } + } + + if (free_mac < 0) { + dev_err(ctrl->dev, "No free egress interface, cannot offload\n"); + return -1; + } + + /* Set up default egress interface 1 */ + intf.vid = vlan; + intf.smac_idx = free_mac; + intf.ip4_mtu_id = 1; + intf.ip6_mtu_id = 1; + intf.ttl_scope = 1; /* TTL */ + intf.hl_scope = 1; /* Hop Limit */ + intf.ip4_icmp_redirect = intf.ip6_icmp_redirect = 2; /* FORWARD */ + intf.ip4_pbr_icmp_redirect = intf.ip6_pbr_icmp_redirect = 2; /* FORWARD; */ + priv->r->set_l3_egress_intf(free_mac, &intf); + + priv->r->set_l3_egress_mac(L3_EGRESS_DMACS + free_mac, mac); + + mutex_unlock(&priv->reg_mutex); + + return free_mac; +} + +/* Updates an L3 next hop entry in the ROUTING table */ +static int otto_l3_nexthop_update(struct otto_l3_ctrl *ctrl, __be32 ip_addr, u64 mac) +{ + struct rtl838x_switch_priv *priv = ctrl->priv; + struct rhlist_head *tmp, *list; + struct otto_l3_route *r; + + rcu_read_lock(); + list = rhltable_lookup(&ctrl->routes, &ip_addr, otto_l3_route_ht_params); + if (!list) { + rcu_read_unlock(); + return -ENOENT; + } + + rhl_for_each_entry_rcu(r, tmp, list, linkage) { + dev_dbg(ctrl->dev, "%s: Setting up fwding: ip %pI4, GW mac %016llx\n", + __func__, &ip_addr, mac); + + /* Reads the ROUTING table entry associated with the route */ + ctrl->cfg->route_read(ctrl, r->id, r); + dev_dbg(ctrl->dev, "Route with id %d to %pI4 / %d\n", + r->id, &r->dst_ip, r->prefix_len); + + r->nh.mac = r->nh.gw = mac; + r->nh.port = priv->r->port_ignore; + r->nh.id = r->id; + + /* Do we need to explicitly add a DMAC entry with the route's nh index? */ + if (priv->r->set_l3_egress_mac) + priv->r->set_l3_egress_mac(r->id, mac); + + /* Update ROUTING table: map gateway-mac and switch-mac id to route id */ + rtl83xx_l2_nexthop_add(priv, &r->nh); + + r->attr.valid = true; + r->attr.action = ROUTE_ACT_FORWARD; + r->attr.type = 0; + r->attr.hit = false; /* Reset route-used indicator */ + + /* Add PIE entry with dst_ip and prefix_len */ + r->pr.dip = r->dst_ip; + r->pr.dip_m = inet_make_mask(r->prefix_len); + + if (r->is_host_route) { + int slot = priv->r->find_l3_slot(r, false); + + dev_info(ctrl->dev, "Got slot for route: %d\n", slot); + priv->r->host_route_write(slot, r); + } else { + ctrl->cfg->route_write(ctrl, r->id, r); + r->pr.fwd_sel = true; + r->pr.fwd_data = r->nh.l2_id; + r->pr.fwd_act = PIE_ACT_ROUTE_UC; + } + + if (ctrl->cfg->set_nexthop) + ctrl->cfg->set_nexthop(ctrl, r->nh.id, r->nh.l2_id, r->nh.if_id); + + if (r->pr.id < 0) { + r->pr.packet_cntr = rtl83xx_packet_cntr_alloc(priv); + if (r->pr.packet_cntr >= 0) { + dev_info(ctrl->dev, "Using packet counter %d\n", + r->pr.packet_cntr); + r->pr.log_sel = true; + r->pr.log_data = r->pr.packet_cntr; + } + priv->r->pie_rule_add(priv, &r->pr); + } else { + int pkts = priv->r->packet_cntr_read(r->pr.packet_cntr); + + dev_dbg(ctrl->dev, "total packets: %d\n", pkts); + + priv->r->pie_rule_write(priv, r->pr.id, &r->pr); + } + } + rcu_read_unlock(); + + return 0; +} + +static int otto_l3_port_ipv4_resolve(struct otto_l3_ctrl *ctrl, + struct net_device *dev, __be32 ip_addr) +{ + struct neighbour *n = neigh_lookup(&arp_tbl, &ip_addr, dev); + int err = 0; + u64 mac; + + if (!n) { + n = neigh_create(&arp_tbl, &ip_addr, dev); + if (IS_ERR(n)) + return PTR_ERR(n); + } + + /* If the neigh is already resolved, then go ahead and + * install the entry, otherwise start the ARP process to + * resolve the neigh. + */ + if (n->nud_state & NUD_VALID) { + mac = ether_addr_to_u64(n->ha); + dev_info(ctrl->dev, "resolved mac: %016llx\n", mac); + otto_l3_nexthop_update(ctrl, ip_addr, mac); + } else { + dev_info(ctrl->dev, "need to wait\n"); + neigh_event_send(n, NULL); + } + + neigh_release(n); + + return err; +} + +static void otto_l3_route_remove(struct otto_l3_ctrl *ctrl, struct otto_l3_route *r) +{ + struct rtl838x_switch_priv *priv = ctrl->priv; + int id; + + if (rhltable_remove(&ctrl->routes, &r->linkage, otto_l3_route_ht_params)) + dev_warn(ctrl->dev, "Could not remove route\n"); + + if (r->is_host_route) { + id = priv->r->find_l3_slot(r, false); + dev_dbg(ctrl->dev, "Got id for host route: %d\n", id); + r->attr.valid = false; + priv->r->host_route_write(id, r); + clear_bit(r->id - MAX_ROUTES, priv->host_route_use_bm); + } else { + /* If there is a HW representation of the route, delete it */ + if (ctrl->cfg->route_lookup_hw) { + id = ctrl->cfg->route_lookup_hw(ctrl, r); + dev_info(ctrl->dev, "Got id for prefix route: %d\n", id); + r->attr.valid = false; + ctrl->cfg->route_write(ctrl, id, r); + } + clear_bit(r->id, priv->route_use_bm); + } + + kfree(r); +} + +static struct otto_l3_route *otto_l3_host_route_alloc(struct otto_l3_ctrl *ctrl, u32 ip) +{ + struct rtl838x_switch_priv *priv = ctrl->priv; + struct otto_l3_route *r; + int idx = 0, err; + + mutex_lock(&priv->reg_mutex); + + idx = find_first_zero_bit(priv->host_route_use_bm, MAX_HOST_ROUTES); + dev_dbg(ctrl->dev, "id: %d, ip %pI4\n", idx, &ip); + + r = kzalloc(sizeof(*r), GFP_KERNEL); + if (!r) { + mutex_unlock(&priv->reg_mutex); + return r; + } + + /* We require a unique route ID irrespective of whether it is a prefix or host + * route (on RTL93xx) as we use this ID to associate a DMAC and next-hop entry + */ + r->id = idx + MAX_ROUTES; + + r->gw_ip = ip; + r->pr.id = -1; /* We still need to allocate a rule in HW */ + r->is_host_route = true; + + err = rhltable_insert(&ctrl->routes, &r->linkage, otto_l3_route_ht_params); + if (err) { + dev_err(ctrl->dev, "Could not insert new rule\n"); + mutex_unlock(&priv->reg_mutex); + goto out_free; + } + + set_bit(idx, priv->host_route_use_bm); + + mutex_unlock(&priv->reg_mutex); + + return r; + +out_free: + kfree(r); + + return NULL; +} + +static struct otto_l3_route *otto_l3_route_alloc(struct otto_l3_ctrl *ctrl, u32 ip) +{ + struct rtl838x_switch_priv *priv = ctrl->priv; + struct otto_l3_route *r; + int idx = 0, err; + + mutex_lock(&priv->reg_mutex); + + idx = find_first_zero_bit(priv->route_use_bm, MAX_ROUTES); + dev_dbg(ctrl->dev, "id: %d, ip %pI4\n", idx, &ip); + + r = kzalloc(sizeof(*r), GFP_KERNEL); + if (!r) { + mutex_unlock(&priv->reg_mutex); + return r; + } + + r->id = idx; + r->gw_ip = ip; + r->pr.id = -1; /* We still need to allocate a rule in HW */ + r->is_host_route = false; + + err = rhltable_insert(&ctrl->routes, &r->linkage, otto_l3_route_ht_params); + if (err) { + dev_err(ctrl->dev, "Could not insert new rule\n"); + mutex_unlock(&priv->reg_mutex); + goto out_free; + } + + set_bit(idx, priv->route_use_bm); + + mutex_unlock(&priv->reg_mutex); + + return r; + +out_free: + kfree(r); + + return NULL; +} + +static int otto_l3_fib_check_v4(struct otto_l3_ctrl *ctrl, + struct fib_entry_notifier_info *info, + enum fib_event_type event) +{ + struct net_device *ndev = fib_info_nh(info->fi, 0)->fib_nh_dev; + int vlan = is_vlan_dev(ndev) ? vlan_dev_vlan_id(ndev) : 0; + struct fib_nh *nh = fib_info_nh(info->fi, 0); + char gw_message[32] = ""; + + if (nh->fib_nh_gw4) + snprintf(gw_message, sizeof(gw_message), "via %pI4 ", &nh->fib_nh_gw4); + + dev_info(ctrl->dev, "%s IPv4 route %pI4/%d %s(VLAN %d, MAC %pM)\n", + event == FIB_EVENT_ENTRY_ADD ? "add" : "delete", + &info->dst, info->dst_len, gw_message, vlan, ndev->dev_addr); + + if ((info->type == RTN_BROADCAST) || ipv4_is_loopback(info->dst) || !info->dst) { + dev_warn(ctrl->dev, "skip loopback/broadcast addresses and default routes\n"); + return -EINVAL; + } + + return 0; +} + +static int otto_l3_fib_add_v4(struct otto_l3_ctrl *ctrl, struct fib_entry_notifier_info *info) +{ + struct net_device *ndev = fib_info_nh(info->fi, 0)->fib_nh_dev; + int vlan = is_vlan_dev(ndev) ? vlan_dev_vlan_id(ndev) : 0; + struct rtl838x_switch_priv *priv = ctrl->priv; + struct fib_nh *nh = fib_info_nh(info->fi, 0); + struct otto_l3_route *route; + int port; + + if (otto_l3_fib_check_v4(ctrl, info, FIB_EVENT_ENTRY_ADD)) + return 0; + + port = otto_l3_port_dev_lower_find(ndev, ctrl); + if (port < 0) { + dev_err(ctrl->dev, "lower interface %s not found\n", ndev->name); + return -ENODEV; + } + + /* Allocate route or host-route entry (if hardware supports this) */ + if (info->dst_len == 32 && priv->r->host_route_write) + route = otto_l3_host_route_alloc(ctrl, nh->fib_nh_gw4); + else + route = otto_l3_route_alloc(ctrl, nh->fib_nh_gw4); + + if (route) + dev_info(ctrl->dev, "route hashtable extended for gw %pI4\n", &nh->fib_nh_gw4); + else { + dev_err(ctrl->dev, "could not extend route hashtable for gw %pI4\n", + &nh->fib_nh_gw4); + return -ENOSPC; + } + + route->dst_ip = info->dst; + route->prefix_len = info->dst_len; + route->nh.rvid = vlan; + + if (ctrl->cfg->set_router_mac) { + u64 mac = ether_addr_to_u64(ndev->dev_addr); + + dev_dbg(ctrl->dev, "Local route and router MAC %pM\n", ndev->dev_addr); + if (otto_l3_alloc_router_mac(ctrl, mac)) + goto out_free_rt; + + /* vid = 0: Do not care about VID */ + route->nh.if_id = otto_l3_alloc_egress_intf(ctrl, mac, vlan); + if (route->nh.if_id < 0) + goto out_free_rmac; + + if (!nh->fib_nh_gw4) { + int slot; + + route->nh.mac = mac; + route->nh.port = priv->r->port_ignore; + route->attr.valid = true; + route->attr.action = ROUTE_ACT_TRAP2CPU; + route->attr.type = 0; + + slot = priv->r->find_l3_slot(route, false); + dev_dbg(ctrl->dev, "Got slot for route: %d\n", slot); + priv->r->host_route_write(slot, route); + } + } + + /* We need to resolve the mac address of the GW */ + if (nh->fib_nh_gw4) + otto_l3_port_ipv4_resolve(ctrl, ndev, nh->fib_nh_gw4); + + nh->fib_nh_flags |= RTNH_F_OFFLOAD; + + return 0; + +out_free_rmac: +out_free_rt: + return 0; +} + +static int otto_l3_fib_del_v4(struct otto_l3_ctrl *ctrl, struct fib_entry_notifier_info *info) +{ + struct rtl838x_switch_priv *priv = ctrl->priv; + struct fib_nh *nh = fib_info_nh(info->fi, 0); + struct rhlist_head *tmp, *list; + struct otto_l3_route *route; + + if (otto_l3_fib_check_v4(ctrl, info, FIB_EVENT_ENTRY_DEL)) + return 0; + + rcu_read_lock(); + list = rhltable_lookup(&ctrl->routes, &nh->fib_nh_gw4, otto_l3_route_ht_params); + if (!list) { + rcu_read_unlock(); + dev_err(ctrl->dev, "no such gateway: %pI4\n", &nh->fib_nh_gw4); + return -ENOENT; + } + rhl_for_each_entry_rcu(route, tmp, list, linkage) { + if (route->dst_ip == info->dst && route->prefix_len == info->dst_len) { + dev_info(ctrl->dev, "found a route with id %d, nh-id %d\n", + route->id, route->nh.id); + break; + } + } + rcu_read_unlock(); + + rtl83xx_l2_nexthop_rm(priv, &route->nh); + + dev_info(ctrl->dev, "releasing packet counter %d\n", route->pr.packet_cntr); + set_bit(route->pr.packet_cntr, priv->packet_cntr_use_bm); + priv->r->pie_rule_rm(priv, &route->pr); + + otto_l3_route_remove(ctrl, route); + + nh->fib_nh_flags &= ~RTNH_F_OFFLOAD; + + return 0; +} + +static int otto_l3_fib_add_v6(struct otto_l3_ctrl *ctrl, struct fib6_entry_notifier_info *info) +{ + dev_dbg(ctrl->dev, "In %s\n", __func__); +/* nh->fib_nh_flags |= RTNH_F_OFFLOAD; */ + + return 0; +} + +static void otto_l3_fib_event_work_do(struct work_struct *work) +{ + struct otto_l3_fib_event_work *fib_work = + container_of(work, struct otto_l3_fib_event_work, work); + struct otto_l3_ctrl *ctrl = fib_work->ctrl; + struct fib_rule *rule; + int err; + + /* Protect internal structures from changes */ + rtnl_lock(); + dev_dbg(ctrl->dev, "doing work, event %ld\n", fib_work->event); + switch (fib_work->event) { + case FIB_EVENT_ENTRY_ADD: + case FIB_EVENT_ENTRY_REPLACE: + case FIB_EVENT_ENTRY_APPEND: + if (fib_work->is_fib6) + err = otto_l3_fib_add_v6(ctrl, &fib_work->fen6_info); + else + err = otto_l3_fib_add_v4(ctrl, &fib_work->fen_info); + if (err) + dev_err(ctrl->dev, "fib_add() failed\n"); + + fib_info_put(fib_work->fen_info.fi); + break; + case FIB_EVENT_ENTRY_DEL: + err = otto_l3_fib_del_v4(ctrl, &fib_work->fen_info); + if (err) + dev_err(ctrl->dev, "fib_del() failed\n"); + + fib_info_put(fib_work->fen_info.fi); + break; + case FIB_EVENT_RULE_ADD: + case FIB_EVENT_RULE_DEL: + rule = fib_work->fr_info.rule; + if (!fib4_rule_default(rule)) + dev_err(ctrl->dev, "FIB4 default rule failed\n"); + fib_rule_put(rule); + break; + } + rtnl_unlock(); + kfree(fib_work); +} + + +/* Called with rcu_read_lock() */ +static int otto_l3_fib_notifier(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct otto_l3_ctrl *ctrl = container_of(this, struct otto_l3_ctrl, fib_nb); + struct rtl838x_switch_priv *priv = ctrl->priv; + struct otto_l3_fib_event_work *fib_work; + struct fib_notifier_info *info = ptr; + + if ((info->family != AF_INET && info->family != AF_INET6 && + info->family != RTNL_FAMILY_IPMR && + info->family != RTNL_FAMILY_IP6MR)) + return NOTIFY_DONE; + + /* ignore FIB events for HW with missing L3 offloading implementation */ + if (!priv->r->l3_setup) + return NOTIFY_DONE; + + fib_work = kzalloc(sizeof(*fib_work), GFP_ATOMIC); + if (!fib_work) + return NOTIFY_BAD; + + INIT_WORK(&fib_work->work, otto_l3_fib_event_work_do); + fib_work->ctrl = ctrl; + fib_work->event = event; + fib_work->is_fib6 = false; + + switch (event) { + case FIB_EVENT_ENTRY_ADD: + case FIB_EVENT_ENTRY_REPLACE: + case FIB_EVENT_ENTRY_APPEND: + case FIB_EVENT_ENTRY_DEL: + dev_dbg(ctrl->dev, "FIB_ENTRY ADD/DEL, event %ld\n", event); + if (info->family == AF_INET) { + struct fib_entry_notifier_info *fen_info = ptr; + + if (fen_info->fi->fib_nh_is_v6) { + NL_SET_ERR_MSG_MOD(info->extack, + "IPv6 gateway with IPv4 route is not supported"); + kfree(fib_work); + return notifier_from_errno(-EINVAL); + } + + memcpy(&fib_work->fen_info, ptr, sizeof(fib_work->fen_info)); + /* Take referece on fib_info to prevent it from being + * freed while work is queued. Release it afterwards. + */ + fib_info_hold(fib_work->fen_info.fi); + + } else if (info->family == AF_INET6) { + //struct fib6_entry_notifier_info *fen6_info = ptr; + dev_warn(ctrl->dev, "FIB_RULE ADD/DEL for IPv6 not supported\n"); + kfree(fib_work); + return NOTIFY_DONE; + } + break; + + case FIB_EVENT_RULE_ADD: + case FIB_EVENT_RULE_DEL: + dev_dbg(ctrl->dev, "FIB_RULE ADD/DEL, event: %ld\n", event); + memcpy(&fib_work->fr_info, ptr, sizeof(fib_work->fr_info)); + fib_rule_get(fib_work->fr_info.rule); + break; + } + + queue_work(priv->wq, &fib_work->work); + + return NOTIFY_DONE; +} + +static void otto_l3_net_event_work_do(struct work_struct *work) +{ + struct otto_l3_net_event_work *net_work = + container_of(work, struct otto_l3_net_event_work, work); + + otto_l3_nexthop_update(net_work->ctrl, net_work->gw_addr, net_work->mac); + + kfree(net_work); +} + +static int otto_l3_netevent_notifier(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct otto_l3_ctrl *ctrl = container_of(this, struct otto_l3_ctrl, ne_nb); + struct rtl838x_switch_priv *priv = ctrl->priv; + struct otto_l3_net_event_work *net_work; + struct neighbour *n = ptr; + struct net_device *dev; + int err, port; + + switch (event) { + case NETEVENT_NEIGH_UPDATE: + /* ignore events for HW with missing L3 offloading implementation */ + if (!priv->r->l3_setup) + return NOTIFY_DONE; + + if (n->tbl != &arp_tbl) + return NOTIFY_DONE; + dev = n->dev; + port = otto_l3_port_dev_lower_find(dev, ctrl); + if (port < 0 || !(n->nud_state & NUD_VALID)) { + dev_dbg(ctrl->dev, "Neigbour invalid, not updating\n"); + return NOTIFY_DONE; + } + + net_work = kzalloc(sizeof(*net_work), GFP_ATOMIC); + if (!net_work) + return NOTIFY_BAD; + + INIT_WORK(&net_work->work, otto_l3_net_event_work_do); + net_work->ctrl = ctrl; + + net_work->mac = ether_addr_to_u64(n->ha); + net_work->gw_addr = *(__be32 *)n->primary_key; + + dev_dbg(ctrl->dev, "updating neighbour on port %d, mac %016llx\n", + port, net_work->mac); + queue_work(priv->wq, &net_work->work); + if (err) + netdev_warn(dev, "failed to handle neigh update (err %d)\n", err); + break; + } + + return NOTIFY_DONE; +} + +const struct otto_l3_config otto_l3_838x_cfg = { + .route_read = otto_l3_838x_route_read, + .route_write = otto_l3_838x_route_write, +}; + +const struct otto_l3_config otto_l3_839x_cfg = { + .route_read = otto_l3_839x_route_read, + .route_write = otto_l3_839x_route_write, +}; + +const struct otto_l3_config otto_l3_930x_cfg = { +#ifdef CONFIG_NET_DSA_RTL83XX_RTL930X_L3_OFFLOAD + .get_router_mac = otto_l3_930x_get_router_mac, + .set_router_mac = otto_l3_930x_set_router_mac, + .get_nexthop = otto_l3_930x_get_nexthop, + .set_nexthop = otto_l3_930x_set_nexthop, + .route_lookup_hw = otto_l3_930x_route_lookup_hw, + .route_read = otto_l3_930x_route_read, + .route_write = otto_l3_930x_route_write, +#endif +}; + +const struct otto_l3_config otto_l3_931x_cfg = { +}; + +static const struct of_device_id otto_l3_of_ids[] = { + { .compatible = "realtek,rtl8380-switch", .data = &otto_l3_838x_cfg, }, + { .compatible = "realtek,rtl8392-switch", .data = &otto_l3_839x_cfg, }, + { .compatible = "realtek,rtl9301-switch", .data = &otto_l3_930x_cfg, }, + { .compatible = "realtek,rtl9311-switch", .data = &otto_l3_931x_cfg, }, + { /* sentinel */ } +}; + +void otto_l3_remove(struct rtl838x_switch_priv *priv) +{ + struct otto_l3_ctrl *ctrl = priv->l3_ctrl; + + if (ctrl->ne_nb.notifier_call) { + unregister_netevent_notifier(&ctrl->ne_nb); + ctrl->ne_nb.notifier_call = NULL; + } + if (ctrl->fib_nb.notifier_call) { + unregister_fib_notifier(&init_net, &ctrl->fib_nb); + ctrl->fib_nb.notifier_call = NULL; + } +} + +int otto_l3_probe(struct device *dev, struct rtl838x_switch_priv *priv) +{ + const struct of_device_id *match; + struct otto_l3_ctrl *ctrl; + int err; + + ctrl = devm_kzalloc(dev, sizeof(struct otto_l3_ctrl), GFP_KERNEL); + if (!ctrl) + return -ENOMEM; + priv->l3_ctrl = ctrl; + ctrl->priv = priv; + ctrl->dev = priv->dev; + + match = of_match_node(otto_l3_of_ids, dev->of_node); + if (!match) + return dev_err_probe(dev, -EINVAL, "No compatible configuration found\n"); + ctrl->cfg = match->data; + + /* Initialize hash table for L3 routing */ + rhltable_init(&ctrl->routes, &otto_l3_route_ht_params); + + /* + * Register netevent notifier callback to catch notifications about neighboring changes + * to update nexthop entries for L3 routing. + */ + ctrl->ne_nb.notifier_call = otto_l3_netevent_notifier; + err = register_netevent_notifier(&ctrl->ne_nb); + if (err) { + ctrl->ne_nb.notifier_call = NULL; + return dev_err_probe(dev, err, "Failed to register netevent notifier\n"); + } + + /* + * Register Forwarding Information Base notifier to offload routes where possible. Only + * FIBs pointing to our own netdevs are programmed into the device, so no need to pass a + * callback. + */ + ctrl->fib_nb.notifier_call = otto_l3_fib_notifier; + err = register_fib_notifier(&init_net, &ctrl->fib_nb, NULL, NULL); + if (err) { + ctrl->fib_nb.notifier_call = NULL; + otto_l3_remove(priv); + return dev_err_probe(dev, err, "Failed to register fib event notifier\n"); + } + + return 0; +} diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h new file mode 100644 index 0000000000..1440b7c0ed --- /dev/null +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h @@ -0,0 +1,95 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _OTTO_L3_H +#define _OTTO_L3_H + +#include "rtl-otto.h" + +/* An entry in the RTL93XX SoC's ROUTER_MAC tables setting up a termination point + * for the L3 routing system. Packets arriving and matching an entry in this table + * will be considered for routing. + * Mask fields state whether the corresponding data fields matter for matching + */ +struct otto_l3_router_mac { + bool valid; /* Valid or not */ + bool p_type; /* Individual (0) or trunk (1) port */ + bool p_mask; /* Whether the port type is used */ + u8 p_id; + u8 p_id_mask; /* Mask for the port */ + u8 action; /* Routing action performed: 0: FORWARD, 1: DROP, 2: TRAP2CPU */ + /* 3: COPY2CPU, 4: TRAP2MASTERCPU, 5: COPY2MASTERCPU, 6: HARDDROP */ + u16 vid; + u16 vid_mask; + u64 mac; /* MAC address used as source MAC in the routed packet */ + u64 mac_mask; +}; + + +struct otto_l3_config { + void (*get_router_mac)(struct otto_l3_ctrl *ctrl, u32 idx, struct otto_l3_router_mac *m); + void (*set_router_mac)(struct otto_l3_ctrl *ctrl, u32 idx, struct otto_l3_router_mac *m); + void (*get_nexthop)(struct otto_l3_ctrl *ctrl, int idx, u16 *dmac_id, u16 *interface); + void (*set_nexthop)(struct otto_l3_ctrl *ctrl, int idx, u16 dmac_id, u16 interface); + int (*route_lookup_hw)(struct otto_l3_ctrl *ctrl, struct otto_l3_route *rt); + void (*route_read)(struct otto_l3_ctrl *ctrl, int idx, struct otto_l3_route *rt); + void (*route_write)(struct otto_l3_ctrl *ctrl, int idx, struct otto_l3_route *rt); +}; + +struct otto_l3_ctrl { + const struct otto_l3_config *cfg; + struct device *dev; + struct rtl838x_switch_priv *priv; + struct notifier_block fib_nb; + struct notifier_block ne_nb; + struct rhltable routes; +}; + +struct otto_l3_route_attr { + bool valid; + bool hit; + bool ttl_dec; + bool ttl_check; + bool dst_null; + bool qos_as; + u8 qos_prio; + u8 type; + u8 action; +}; + +struct otto_l3_nexthop { + u16 id; /* ID: L3_NEXT_HOP table-index or route-index set in L2_NEXT_HOP */ + u32 dev_id; + u16 port; + u16 vid; /* VLAN-ID for L2 table entry (saved from L2-UC entry) */ + u16 rvid; /* Relay VID/FID for the L2 table entry */ + u64 mac; /* The MAC address of the entry in the L2_NEXT_HOP table */ + u16 mac_id; + u16 l2_id; /* Index of this next hop forwarding entry in L2 FIB table */ + u64 gw; /* The gateway MAC address packets are forwarded to */ + int if_id; /* Interface (into L3_EGR_INTF_IDX) */ +}; + +struct otto_l3_route { + u32 gw_ip; /* IP of the route's gateway */ + u32 dst_ip; /* IP of the destination net */ + struct in6_addr dst_ip6; + int prefix_len; /* Network prefix len of the destination net */ + bool is_host_route; + int id; /* ID number of this route */ + struct rhlist_head linkage; + u16 switch_mac_id; /* Index into switch's own MACs, RTL839X only */ + struct otto_l3_nexthop nh; + struct pie_rule pr; + struct otto_l3_route_attr attr; +}; + +static const struct rhashtable_params otto_l3_route_ht_params = { + .key_len = sizeof(u32), + .key_offset = offsetof(struct otto_l3_route, gw_ip), + .head_offset = offsetof(struct otto_l3_route, linkage), +}; + +int otto_l3_probe(struct device *dev, struct rtl838x_switch_priv *priv); +void otto_l3_remove(struct rtl838x_switch_priv *priv); + +#endif /* _OTTO_L3_H */ diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h index 6ed1ed4fc1..393ad060cb 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h @@ -898,6 +898,8 @@ typedef enum { */ #define RTLDSA_COUNTERS_FAST_POLL_INTERVAL (3 * HZ) +struct otto_l3_route; + enum pbvlan_type { PBVLAN_TYPE_INNER = 0, PBVLAN_TYPE_OUTER, @@ -1283,38 +1285,6 @@ struct rtl838x_l3_intf { u8 ip6_pbr_icmp_redirect; }; -/* An entry in the RTL93XX SoC's ROUTER_MAC tables setting up a termination point - * for the L3 routing system. Packets arriving and matching an entry in this table - * will be considered for routing. - * Mask fields state whether the corresponding data fields matter for matching - */ -struct rtl93xx_rt_mac { - bool valid; /* Valid or not */ - bool p_type; /* Individual (0) or trunk (1) port */ - bool p_mask; /* Whether the port type is used */ - u8 p_id; - u8 p_id_mask; /* Mask for the port */ - u8 action; /* Routing action performed: 0: FORWARD, 1: DROP, 2: TRAP2CPU */ - /* 3: COPY2CPU, 4: TRAP2MASTERCPU, 5: COPY2MASTERCPU, 6: HARDDROP */ - u16 vid; - u16 vid_mask; - u64 mac; /* MAC address used as source MAC in the routed packet */ - u64 mac_mask; -}; - -struct rtl83xx_nexthop { - u16 id; /* ID: L3_NEXT_HOP table-index or route-index set in L2_NEXT_HOP */ - u32 dev_id; - u16 port; - u16 vid; /* VLAN-ID for L2 table entry (saved from L2-UC entry) */ - u16 rvid; /* Relay VID/FID for the L2 table entry */ - u64 mac; /* The MAC address of the entry in the L2_NEXT_HOP table */ - u16 mac_id; - u16 l2_id; /* Index of this next hop forwarding entry in L2 FIB table */ - u64 gw; /* The gateway MAC address packets are forwarded to */ - int if_id; /* Interface (into L3_EGR_INTF_IDX) */ -}; - struct rtl838x_switch_priv; struct rtl83xx_flow { @@ -1326,32 +1296,6 @@ struct rtl83xx_flow { u32 flags; }; -struct rtl93xx_route_attr { - bool valid; - bool hit; - bool ttl_dec; - bool ttl_check; - bool dst_null; - bool qos_as; - u8 qos_prio; - u8 type; - u8 action; -}; - -struct rtl83xx_route { - u32 gw_ip; /* IP of the route's gateway */ - u32 dst_ip; /* IP of the destination net */ - struct in6_addr dst_ip6; - int prefix_len; /* Network prefix len of the destination net */ - bool is_host_route; - int id; /* ID number of this route */ - struct rhlist_head linkage; - u16 switch_mac_id; /* Index into switch's own MACs, RTL839X only */ - struct rtl83xx_nexthop nh; - struct pie_rule pr; - struct rtl93xx_route_attr attr; -}; - /** * struct rtldsa_mirror_config - Mirror configuration for specific group and port */ @@ -1474,18 +1418,11 @@ struct rtldsa_config { void (*l2_learning_setup)(void); u32 (*packet_cntr_read)(int counter); void (*packet_cntr_clear)(int counter); - void (*route_read)(int idx, struct rtl83xx_route *rt); - void (*route_write)(int idx, struct rtl83xx_route *rt); - void (*host_route_write)(int idx, struct rtl83xx_route *rt); + void (*host_route_write)(int idx, struct otto_l3_route *rt); int (*l3_setup)(struct rtl838x_switch_priv *priv); - void (*set_l3_nexthop)(int idx, u16 dmac_id, u16 interface); - void (*get_l3_nexthop)(int idx, u16 *dmac_id, u16 *interface); u64 (*get_l3_egress_mac)(u32 idx); void (*set_l3_egress_mac)(u32 idx, u64 mac); - int (*find_l3_slot)(struct rtl83xx_route *rt, bool must_exist); - int (*route_lookup_hw)(struct rtl83xx_route *rt); - void (*get_l3_router_mac)(u32 idx, struct rtl93xx_rt_mac *m); - void (*set_l3_router_mac)(u32 idx, struct rtl93xx_rt_mac *m); + int (*find_l3_slot)(struct otto_l3_route *rt, bool must_exist); void (*set_l3_egress_intf)(int idx, struct rtl838x_l3_intf *intf); void (*set_receive_management_action)(int port, rma_ctrl_t type, action_type_t action); void (*led_init)(struct rtl838x_switch_priv *priv); @@ -1520,6 +1457,7 @@ struct rtl838x_switch_priv { int link_state_irq; int mirror_group_ports[4]; const struct rtldsa_config *r; + struct otto_l3_ctrl *l3_ctrl; u64 irq_mask; struct dentry *dbgfs_dir; @@ -1540,15 +1478,12 @@ struct rtl838x_switch_priv { /** @lagmembers: Port (bit) is part of any LAG */ u64 lagmembers; struct workqueue_struct *wq; - struct notifier_block ne_nb; - struct notifier_block fib_nb; bool eee_enabled; unsigned long mc_group_bm[MAX_MC_GROUPS >> 5]; struct rhashtable tc_ht; unsigned long pie_use_bm[MAX_PIE_ENTRIES >> 5]; unsigned long octet_cntr_use_bm[MAX_COUNTERS >> 5]; unsigned long packet_cntr_use_bm[MAX_COUNTERS >> 4]; - struct rhltable routes; unsigned long route_use_bm[MAX_ROUTES >> 5]; unsigned long host_route_use_bm[MAX_HOST_ROUTES >> 5]; struct rtl838x_l3_intf *interfaces[MAX_INTERFACES]; @@ -1789,6 +1724,12 @@ void rtldsa_counters_unlock_table(struct rtl838x_switch_priv *priv, int port) void rtldsa_update_counters_atomically(struct rtl838x_switch_priv *priv, int port); + +struct otto_l3_nexthop; +int rtl83xx_l2_nexthop_add(struct rtl838x_switch_priv *priv, struct otto_l3_nexthop *nh); +int rtl83xx_l2_nexthop_rm(struct rtl838x_switch_priv *priv, struct otto_l3_nexthop *nh); + + extern int rtldsa_max_available_queue[]; extern int rtldsa_default_queue_weights[]; diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl838x.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl838x.c index aa118ff7ca..3dd1cc6f13 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl838x.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl838x.c @@ -5,6 +5,7 @@ #include #include +#include "l3.h" #include "rtl-otto.h" #define RTL838X_VLAN_PORT_TAG_STS_UNTAG 0x0 @@ -1627,35 +1628,6 @@ static void rtl838x_packet_cntr_clear(int counter) rtl_table_release(r); } -static void rtl838x_route_read(int idx, struct rtl83xx_route *rt) -{ - /* Read ROUTING table (2) via register RTL8380_TBL_1 */ - struct table_reg *r = rtl_table_get(RTL8380_TBL_1, 2); - - pr_debug("In %s, id %d\n", __func__, idx); - rtl_table_read(r, idx); - - /* The table has a size of 2 registers */ - rt->nh.gw = sw_r32(rtl_table_data(r, 0)); - rt->nh.gw <<= 32; - rt->nh.gw |= sw_r32(rtl_table_data(r, 1)); - - rtl_table_release(r); -} - -static void rtl838x_route_write(int idx, struct rtl83xx_route *rt) -{ - /* Access ROUTING table (2) via register RTL8380_TBL_1 */ - struct table_reg *r = rtl_table_get(RTL8380_TBL_1, 2); - - pr_debug("In %s, id %d, gw: %016llx\n", __func__, idx, rt->nh.gw); - sw_w32(rt->nh.gw >> 32, rtl_table_data(r, 0)); - sw_w32(rt->nh.gw, rtl_table_data(r, 1)); - rtl_table_write(r, idx); - - rtl_table_release(r); -} - static int rtl838x_l3_setup(struct rtl838x_switch_priv *priv) { /* Nothing to be done */ @@ -1875,8 +1847,6 @@ const struct rtldsa_config rtldsa_838x_cfg = { .l2_learning_setup = rtl838x_l2_learning_setup, .packet_cntr_read = rtl838x_packet_cntr_read, .packet_cntr_clear = rtl838x_packet_cntr_clear, - .route_read = rtl838x_route_read, - .route_write = rtl838x_route_write, .l3_setup = rtl838x_l3_setup, .set_receive_management_action = rtl838x_set_receive_management_action, .qos_init = rtldsa_838x_qos_init, diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl839x.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl839x.c index b932cee3b1..857201be29 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl839x.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl839x.c @@ -3,6 +3,7 @@ #include #include +#include "l3.h" #include "rtl-otto.h" #define RTL839X_VLAN_PORT_TAG_STS_UNTAG 0x0 @@ -1532,42 +1533,6 @@ static void rtl839x_packet_cntr_clear(int counter) rtl_table_release(r); } -static void rtl839x_route_read(int idx, struct rtl83xx_route *rt) -{ - u64 v; - /* Read ROUTING table (2) via register RTL8390_TBL_1 */ - struct table_reg *r = rtl_table_get(RTL8390_TBL_1, 2); - - pr_debug("In %s\n", __func__); - rtl_table_read(r, idx); - - /* The table has a size of 2 registers */ - v = sw_r32(rtl_table_data(r, 0)); - v <<= 32; - v |= sw_r32(rtl_table_data(r, 1)); - rt->switch_mac_id = (v >> 12) & 0xf; - rt->nh.gw = v >> 16; - - rtl_table_release(r); -} - -static void rtl839x_route_write(int idx, struct rtl83xx_route *rt) -{ - u32 v; - - /* Read ROUTING table (2) via register RTL8390_TBL_1 */ - struct table_reg *r = rtl_table_get(RTL8390_TBL_1, 2); - - pr_debug("In %s\n", __func__); - sw_w32(rt->nh.gw >> 16, rtl_table_data(r, 0)); - v = rt->nh.gw << 16; - v |= rt->switch_mac_id << 12; - sw_w32(v, rtl_table_data(r, 1)); - rtl_table_write(r, idx); - - rtl_table_release(r); -} - /* Configure the switch's own MAC addresses used when routing packets */ static void rtl839x_setup_port_macs(struct rtl838x_switch_priv *priv) { @@ -1791,8 +1756,6 @@ const struct rtldsa_config rtldsa_839x_cfg = { .l2_learning_setup = rtl839x_l2_learning_setup, .packet_cntr_read = rtl839x_packet_cntr_read, .packet_cntr_clear = rtl839x_packet_cntr_clear, - .route_read = rtl839x_route_read, - .route_write = rtl839x_route_write, .l3_setup = rtl839x_l3_setup, .set_receive_management_action = rtl839x_set_receive_management_action, .qos_init = rtldsa_839x_qos_init, diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c index 3e406824f5..a2acd1bf27 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c @@ -4,6 +4,7 @@ #include #include +#include "l3.h" #include "rtl-otto.h" #define RTL930X_VLAN_PORT_TAG_STS_INTERNAL 0x0 @@ -23,6 +24,11 @@ #define RTL930X_VLAN_PORT_TAG_STS_CTRL_IGR_P_ITAG_KEEP_MASK GENMASK(0, 0) #define RTL930X_LED_GLB_ACTIVE_LOW BIT(22) +#define RTL930X_LED_CLK_SEL_MASK GENMASK(17, 16) +#define RTL930X_LED_CLK_SEL_800NS 0 +#define RTL930X_LED_CLK_SEL_400NS 1 +#define RTL930X_LED_CLK_SEL_200NS 2 +#define RTL930X_LED_CLK_SEL_100NS 3 #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) @@ -1259,92 +1265,10 @@ static u32 rtl930x_l3_hash4(u32 ip, int algorithm, bool move_dip) // return hash; // } -/* Read a prefix route entry from the L3_PREFIX_ROUTE_IPUC table - * We currently only support IPv4 and IPv6 unicast route - */ -static void rtl930x_route_read(int idx, struct rtl83xx_route *rt) -{ - u32 v, ip4_m; - bool host_route, default_route; - struct in6_addr ip6_m; - - /* Read L3_PREFIX_ROUTE_IPUC table (2) via register RTL9300_TBL_1 */ - struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 2); - - rtl_table_read(r, idx); - /* The table has a size of 11 registers */ - rt->attr.valid = !!(sw_r32(rtl_table_data(r, 0)) & BIT(31)); - if (!rt->attr.valid) - goto out; - - rt->attr.type = (sw_r32(rtl_table_data(r, 0)) >> 29) & 0x3; - - v = sw_r32(rtl_table_data(r, 10)); - host_route = !!(v & BIT(21)); - default_route = !!(v & BIT(20)); - rt->prefix_len = -1; - pr_debug("%s: host route %d, default_route %d\n", __func__, host_route, default_route); - - switch (rt->attr.type) { - case 0: /* IPv4 Unicast route */ - rt->dst_ip = sw_r32(rtl_table_data(r, 4)); - ip4_m = sw_r32(rtl_table_data(r, 9)); - pr_debug("%s: Read ip4 mask: %08x\n", __func__, ip4_m); - rt->prefix_len = host_route ? 32 : -1; - rt->prefix_len = (rt->prefix_len < 0 && default_route) ? 0 : -1; - if (rt->prefix_len < 0) - rt->prefix_len = inet_mask_len(ip4_m); - break; - case 2: /* IPv6 Unicast route */ - ipv6_addr_set(&rt->dst_ip6, - sw_r32(rtl_table_data(r, 1)), sw_r32(rtl_table_data(r, 2)), - sw_r32(rtl_table_data(r, 3)), sw_r32(rtl_table_data(r, 4))); - ipv6_addr_set(&ip6_m, - sw_r32(rtl_table_data(r, 6)), sw_r32(rtl_table_data(r, 7)), - sw_r32(rtl_table_data(r, 8)), sw_r32(rtl_table_data(r, 9))); - rt->prefix_len = host_route ? 128 : 0; - rt->prefix_len = (rt->prefix_len < 0 && default_route) ? 0 : -1; - if (rt->prefix_len < 0) - rt->prefix_len = find_last_bit((unsigned long *)&ip6_m.s6_addr32, - 128); - break; - case 1: /* IPv4 Multicast route */ - case 3: /* IPv6 Multicast route */ - pr_warn("%s: route type not supported\n", __func__); - goto out; - } - - rt->attr.hit = !!(v & BIT(22)); - rt->attr.action = (v >> 18) & 3; - rt->nh.id = (v >> 7) & 0x7ff; - rt->attr.ttl_dec = !!(v & BIT(6)); - rt->attr.ttl_check = !!(v & BIT(5)); - rt->attr.dst_null = !!(v & BIT(4)); - rt->attr.qos_as = !!(v & BIT(3)); - rt->attr.qos_prio = v & 0x7; - pr_debug("%s: index %d is valid: %d\n", __func__, idx, rt->attr.valid); - pr_debug("%s: next_hop: %d, hit: %d, action :%d, ttl_dec %d, ttl_check %d, dst_null %d\n", - __func__, rt->nh.id, rt->attr.hit, rt->attr.action, - rt->attr.ttl_dec, rt->attr.ttl_check, rt->attr.dst_null); - pr_debug("%s: GW: %pI4, prefix_len: %d\n", __func__, &rt->dst_ip, rt->prefix_len); -out: - rtl_table_release(r); -} - -static void rtl930x_net6_mask(int prefix_len, struct in6_addr *ip6_m) -{ - int o, b; - /* Define network mask */ - o = prefix_len >> 3; - b = prefix_len & 0x7; - memset(ip6_m->s6_addr, 0xff, o); - ip6_m->s6_addr[o] |= b ? 0xff00 >> b : 0x00; -} - /* Read a host route entry from the table using its index * We currently only support IPv4 and IPv6 unicast route */ -static void rtl930x_host_route_read(int idx, struct rtl83xx_route *rt) +static void rtl930x_host_route_read(int idx, struct otto_l3_route *rt) { u32 v; /* Read L3_HOST_ROUTE_IPUC table (1) via register RTL9300_TBL_1 */ @@ -1396,7 +1320,7 @@ out: /* Write a host route entry from the table using its index * We currently only support IPv4 and IPv6 unicast route */ -static void rtl930x_host_route_write(int idx, struct rtl83xx_route *rt) +static void rtl930x_host_route_write(int idx, struct otto_l3_route *rt) { u32 v; /* Access L3_HOST_ROUTE_IPUC table (1) via register RTL9300_TBL_1 */ @@ -1448,55 +1372,11 @@ out: rtl_table_release(r); } -/* Look up the index of a prefix route in the routing table CAM for unicast IPv4/6 routes - * using hardware offload. - */ -static int rtl930x_route_lookup_hw(struct rtl83xx_route *rt) -{ - u32 ip4_m, v; - struct in6_addr ip6_m; - - if (rt->attr.type == 1 || rt->attr.type == 3) /* Hardware only supports UC routes */ - return -1; - - sw_w32_mask(0x3 << 19, rt->attr.type, RTL930X_L3_HW_LU_KEY_CTRL); - if (rt->attr.type) { /* IPv6 */ - rtl930x_net6_mask(rt->prefix_len, &ip6_m); - for (int i = 0; i < 4; i++) - sw_w32(rt->dst_ip6.s6_addr32[0] & ip6_m.s6_addr32[0], - RTL930X_L3_HW_LU_KEY_IP_CTRL + (i << 2)); - } else { /* IPv4 */ - ip4_m = inet_make_mask(rt->prefix_len); - sw_w32(0, RTL930X_L3_HW_LU_KEY_IP_CTRL); - sw_w32(0, RTL930X_L3_HW_LU_KEY_IP_CTRL + 4); - sw_w32(0, RTL930X_L3_HW_LU_KEY_IP_CTRL + 8); - v = rt->dst_ip & ip4_m; - pr_debug("%s: searching for %pI4\n", __func__, &v); - sw_w32(v, RTL930X_L3_HW_LU_KEY_IP_CTRL + 12); - } - - /* Execute CAM lookup in SoC */ - sw_w32(BIT(15), RTL930X_L3_HW_LU_CTRL); - - /* Wait until execute bit clears and result is ready */ - do { - v = sw_r32(RTL930X_L3_HW_LU_CTRL); - } while (v & BIT(15)); - - pr_debug("%s: found: %d, index: %d\n", __func__, !!(v & BIT(14)), v & 0x1ff); - - /* Test if search successful (BIT 14 set) */ - if (v & BIT(14)) - return v & 0x1ff; - - return -1; -} - -static int rtl930x_find_l3_slot(struct rtl83xx_route *rt, bool must_exist) +static int rtl930x_find_l3_slot(struct otto_l3_route *rt, bool must_exist) { int slot_width, algorithm, addr, idx; u32 hash; - struct rtl83xx_route route_entry; + struct otto_l3_route route_entry; /* IPv6 entries take up 3 slots */ slot_width = (rt->attr.type == 0) || (rt->attr.type == 2) ? 1 : 3; @@ -1526,105 +1406,6 @@ static int rtl930x_find_l3_slot(struct rtl83xx_route *rt, bool must_exist) return -1; } -/* Write a prefix route into the routing table CAM at position idx - * Currently only IPv4 and IPv6 unicast routes are supported - */ -static void rtl930x_route_write(int idx, struct rtl83xx_route *rt) -{ - u32 v, ip4_m; - struct in6_addr ip6_m; - /* Access L3_PREFIX_ROUTE_IPUC table (2) via register RTL9300_TBL_1 */ - /* The table has a size of 11 registers (20 for MC) */ - struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 2); - - pr_debug("%s: index %d is valid: %d\n", __func__, idx, rt->attr.valid); - pr_debug("%s: nexthop: %d, hit: %d, action :%d, ttl_dec %d, ttl_check %d, dst_null %d\n", - __func__, rt->nh.id, rt->attr.hit, rt->attr.action, - rt->attr.ttl_dec, rt->attr.ttl_check, rt->attr.dst_null); - pr_debug("%s: GW: %pI4, prefix_len: %d\n", __func__, &rt->dst_ip, rt->prefix_len); - - v = rt->attr.valid ? BIT(31) : 0; - v |= (rt->attr.type & 0x3) << 29; - sw_w32(v, rtl_table_data(r, 0)); - - v = rt->attr.hit ? BIT(22) : 0; - v |= (rt->attr.action & 0x3) << 18; - v |= (rt->nh.id & 0x7ff) << 7; - v |= rt->attr.ttl_dec ? BIT(6) : 0; - v |= rt->attr.ttl_check ? BIT(5) : 0; - v |= rt->attr.dst_null ? BIT(6) : 0; - v |= rt->attr.qos_as ? BIT(6) : 0; - v |= rt->attr.qos_prio & 0x7; - v |= rt->prefix_len == 0 ? BIT(20) : 0; /* set default route bit */ - - /* set bit mask for entry type always to 0x3 */ - sw_w32(0x3 << 29, rtl_table_data(r, 5)); - - switch (rt->attr.type) { - case 0: /* IPv4 Unicast route */ - sw_w32(0, rtl_table_data(r, 1)); - sw_w32(0, rtl_table_data(r, 2)); - sw_w32(0, rtl_table_data(r, 3)); - sw_w32(rt->dst_ip, rtl_table_data(r, 4)); - - v |= rt->prefix_len == 32 ? BIT(21) : 0; /* set host-route bit */ - ip4_m = inet_make_mask(rt->prefix_len); - sw_w32(0, rtl_table_data(r, 6)); - sw_w32(0, rtl_table_data(r, 7)); - sw_w32(0, rtl_table_data(r, 8)); - sw_w32(ip4_m, rtl_table_data(r, 9)); - break; - case 2: /* IPv6 Unicast route */ - sw_w32(rt->dst_ip6.s6_addr32[0], rtl_table_data(r, 1)); - sw_w32(rt->dst_ip6.s6_addr32[1], rtl_table_data(r, 2)); - sw_w32(rt->dst_ip6.s6_addr32[2], rtl_table_data(r, 3)); - sw_w32(rt->dst_ip6.s6_addr32[3], rtl_table_data(r, 4)); - - v |= rt->prefix_len == 128 ? BIT(21) : 0; /* set host-route bit */ - - rtl930x_net6_mask(rt->prefix_len, &ip6_m); - - sw_w32(ip6_m.s6_addr32[0], rtl_table_data(r, 6)); - sw_w32(ip6_m.s6_addr32[1], rtl_table_data(r, 7)); - sw_w32(ip6_m.s6_addr32[2], rtl_table_data(r, 8)); - sw_w32(ip6_m.s6_addr32[3], rtl_table_data(r, 9)); - break; - case 1: /* IPv4 Multicast route */ - case 3: /* IPv6 Multicast route */ - pr_warn("%s: route type not supported\n", __func__); - rtl_table_release(r); - return; - } - sw_w32(v, rtl_table_data(r, 10)); - - pr_debug("%s: %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x\n", __func__, - sw_r32(rtl_table_data(r, 0)), sw_r32(rtl_table_data(r, 1)), sw_r32(rtl_table_data(r, 2)), - sw_r32(rtl_table_data(r, 3)), sw_r32(rtl_table_data(r, 4)), sw_r32(rtl_table_data(r, 5)), - sw_r32(rtl_table_data(r, 6)), sw_r32(rtl_table_data(r, 7)), sw_r32(rtl_table_data(r, 8)), - sw_r32(rtl_table_data(r, 9)), sw_r32(rtl_table_data(r, 10))); - - rtl_table_write(r, idx); - rtl_table_release(r); -} - -/* Get the destination MAC and L3 egress interface ID of a nexthop entry from - * the SoC's L3_NEXTHOP table - */ -static void rtl930x_get_l3_nexthop(int idx, u16 *dmac_id, u16 *interface) -{ - u32 v; - /* Read L3_NEXTHOP table (3) via register RTL9300_TBL_1 */ - struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 3); - - rtl_table_read(r, idx); - /* The table has a size of 1 register */ - v = sw_r32(rtl_table_data(r, 0)); - rtl_table_release(r); - - *dmac_id = (v >> 7) & 0x7fff; - *interface = v & 0x7f; -} - // Currently not used // static int rtl930x_l3_mtu_del(struct rtl838x_switch_priv *priv, int mtu) // { @@ -1709,27 +1490,6 @@ static void rtl930x_get_l3_nexthop(int idx, u16 *dmac_id, u16 *interface) // } // } -/* Set the destination MAC and L3 egress interface ID for a nexthop entry in the SoC's - * L3_NEXTHOP table. The nexthop entry is identified by idx. - * dmac_id is the reference to the L2 entry in the L2 forwarding table, special values are - * 0x7ffe: TRAP2CPU - * 0x7ffd: TRAP2MASTERCPU - * 0x7fff: DMAC_ID_DROP - */ -static void rtl930x_set_l3_nexthop(int idx, u16 dmac_id, u16 interface) -{ - /* Access L3_NEXTHOP table (3) via register RTL9300_TBL_1 */ - struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 3); - - pr_debug("%s: Writing to L3_NEXTHOP table, index %d, dmac_id %d, interface %d\n", - __func__, idx, dmac_id, interface); - sw_w32(((dmac_id & 0x7fff) << 7) | (interface & 0x7f), rtl_table_data(r, 0)); - - pr_debug("%s: %08x\n", __func__, sw_r32(rtl_table_data(r, 0))); - rtl_table_write(r, idx); - rtl_table_release(r); -} - #endif /* CONFIG_NET_DSA_RTL83XX_RTL930X_L3_OFFLOAD */ static void rtl930x_pie_lookup_enable(struct rtl838x_switch_priv *priv, int index) @@ -2294,79 +2054,6 @@ static void rtl930x_set_l3_egress_intf(int idx, struct rtl838x_l3_intf *intf) rtl_table_release(r); } -/* Reads a MAC entry for L3 termination as entry point for routing - * from the hardware table - * idx is the index into the L3_ROUTER_MAC table - */ -static void rtl930x_get_l3_router_mac(u32 idx, struct rtl93xx_rt_mac *m) -{ - u32 v, w; - /* Read L3_ROUTER_MAC table (0) via register RTL9300_TBL_1 */ - struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 0); - - rtl_table_read(r, idx); - /* The table has a size of 7 registers, 64 entries */ - v = sw_r32(rtl_table_data(r, 0)); - w = sw_r32(rtl_table_data(r, 3)); - m->valid = !!(v & BIT(20)); - if (!m->valid) - goto out; - - m->p_type = !!(v & BIT(19)); - m->p_id = (v >> 13) & 0x3f; /* trunk id of port */ - m->vid = v & 0xfff; - m->vid_mask = w & 0xfff; - m->action = sw_r32(rtl_table_data(r, 6)) & 0x7; - m->mac_mask = ((((u64)sw_r32(rtl_table_data(r, 5))) << 32) & 0xffffffffffffULL) | - (sw_r32(rtl_table_data(r, 4))); - m->mac = ((((u64)sw_r32(rtl_table_data(r, 1))) << 32) & 0xffffffffffffULL) | - (sw_r32(rtl_table_data(r, 2))); - /* Bits L3_INTF and BMSK_L3_INTF are 0 */ - -out: - rtl_table_release(r); -} - -/* Writes a MAC entry for L3 termination as entry point for routing - * into the hardware table - * idx is the index into the L3_ROUTER_MAC table - */ -static void rtl930x_set_l3_router_mac(u32 idx, struct rtl93xx_rt_mac *m) -{ - u32 v, w; - /* Read L3_ROUTER_MAC table (0) via register RTL9300_TBL_1 */ - struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 0); - - /* The table has a size of 7 registers, 64 entries */ - v = BIT(20); /* mac entry valid, port type is 0: individual */ - v |= (m->p_id & 0x3f) << 13; - v |= (m->vid & 0xfff); /* Set the interface_id to the vlan id */ - - w = m->vid_mask; - w |= (m->p_id_mask & 0x3f) << 13; - - sw_w32(v, rtl_table_data(r, 0)); - sw_w32(w, rtl_table_data(r, 3)); - - /* Set MAC address, L3_INTF (bit 12 in register 1) needs to be 0 */ - sw_w32((u32)(m->mac), rtl_table_data(r, 2)); - sw_w32(m->mac >> 32, rtl_table_data(r, 1)); - - /* Set MAC address mask, BMSK_L3_INTF (bit 12 in register 5) needs to be 0 */ - sw_w32((u32)(m->mac_mask >> 32), rtl_table_data(r, 4)); - sw_w32((u32)m->mac_mask, rtl_table_data(r, 5)); - - sw_w32(m->action & 0x7, rtl_table_data(r, 6)); - - pr_debug("%s writing index %d: %08x %08x %08x %08x %08x %08x %08x\n", __func__, idx, - sw_r32(rtl_table_data(r, 0)), sw_r32(rtl_table_data(r, 1)), sw_r32(rtl_table_data(r, 2)), - sw_r32(rtl_table_data(r, 3)), sw_r32(rtl_table_data(r, 4)), sw_r32(rtl_table_data(r, 5)), - sw_r32(rtl_table_data(r, 6)) - ); - rtl_table_write(r, idx); - rtl_table_release(r); -} - /* Get the Destination-MAC of an L3 egress interface or the Source MAC for routed packets * from the SoC's L3_EGR_INTF_MAC table * Indexes 0-2047 are DMACs, 2048+ are SMACs @@ -2611,7 +2298,9 @@ static void rtl930x_led_init(struct rtl838x_switch_priv *priv) struct device *dev = priv->dev; u8 leds_in_set[4] = {}; u32 led_mode = 1; + u32 clk_freq; u32 pm = 0; + int ret; node = of_find_compatible_node(NULL, NULL, "realtek,rtl9300-leds"); if (!node) { @@ -2619,6 +2308,32 @@ static void rtl930x_led_init(struct rtl838x_switch_priv *priv) return; } + ret = of_property_read_u32(node, "clock-frequency", &clk_freq); + if (!ret) { + u8 clk_sel; + + switch (clk_freq) { + case 10000000: + clk_sel = RTL930X_LED_CLK_SEL_100NS; + break; + case 5000000: + clk_sel = RTL930X_LED_CLK_SEL_200NS; + break; + case 1250000: + clk_sel = RTL930X_LED_CLK_SEL_800NS; + break; + default: + dev_warn(dev, "invalid LED clock frequency, falling back to default\n"); + fallthrough; + case 2500000: + clk_sel = RTL930X_LED_CLK_SEL_400NS; + break; + } + + sw_w32_mask(RTL930X_LED_CLK_SEL_MASK, + FIELD_PREP(RTL930X_LED_CLK_SEL_MASK, clk_sel), RTL930X_LED_GLB_CTRL); + } + for (int set = 0; set < 4; set++) { char set_name[16] = {0}; u32 set_config[4]; @@ -2859,18 +2574,11 @@ const struct rtldsa_config rtldsa_930x_cfg = { .packet_cntr_read = rtl930x_packet_cntr_read, .packet_cntr_clear = rtl930x_packet_cntr_clear, #ifdef CONFIG_NET_DSA_RTL83XX_RTL930X_L3_OFFLOAD - .route_read = rtl930x_route_read, - .route_write = rtl930x_route_write, .host_route_write = rtl930x_host_route_write, .l3_setup = rtl930x_l3_setup, - .set_l3_nexthop = rtl930x_set_l3_nexthop, - .get_l3_nexthop = rtl930x_get_l3_nexthop, .get_l3_egress_mac = rtl930x_get_l3_egress_mac, .set_l3_egress_mac = rtl930x_set_l3_egress_mac, .find_l3_slot = rtl930x_find_l3_slot, - .route_lookup_hw = rtl930x_route_lookup_hw, - .get_l3_router_mac = rtl930x_get_l3_router_mac, - .set_l3_router_mac = rtl930x_set_l3_router_mac, .set_l3_egress_intf = rtl930x_set_l3_egress_intf, #endif .led_init = rtl930x_led_init, diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl931x.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl931x.c index d10517c27e..e992c45c22 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl931x.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl931x.c @@ -25,6 +25,12 @@ #define RTL931X_VLAN_PORT_TAG_ITPID_IDX_MASK GENMASK(2, 1) #define RTL931X_VLAN_PORT_TAG_ITPID_KEEP_MASK GENMASK(0, 0) +#define RTL931X_LED_CLK_SEL_MASK GENMASK(16, 15) +#define RTL931X_LED_CLK_SEL_800NS 0 +#define RTL931X_LED_CLK_SEL_400NS 1 +#define RTL931X_LED_CLK_SEL_200NS 2 +#define RTL931X_LED_CLK_SEL_100NS 3 + /* Definition of the RTL931X-specific template field IDs as used in the PIE */ enum template_field_id { TEMPLATE_FIELD_SPM0 = 1, @@ -1603,6 +1609,8 @@ static void rtldsa_931x_led_init(struct rtl838x_switch_priv *priv) struct device *dev = priv->dev; struct device_node *node; u8 leds_in_set[4] = {}; + u32 clk_freq; + int ret; node = of_find_compatible_node(NULL, NULL, "realtek,rtl9300-leds"); if (!node) { @@ -1610,6 +1618,32 @@ static void rtldsa_931x_led_init(struct rtl838x_switch_priv *priv) return; } + ret = of_property_read_u32(node, "clock-frequency", &clk_freq); + if (!ret) { + u8 clk_sel; + + switch (clk_freq) { + case 10000000: + clk_sel = RTL931X_LED_CLK_SEL_100NS; + break; + case 5000000: + clk_sel = RTL931X_LED_CLK_SEL_200NS; + break; + case 1250000: + clk_sel = RTL931X_LED_CLK_SEL_800NS; + break; + default: + dev_warn(dev, "invalid LED clock frequency, falling back to default\n"); + fallthrough; + case 2500000: + clk_sel = RTL931X_LED_CLK_SEL_400NS; + break; + } + + sw_w32_mask(RTL931X_LED_CLK_SEL_MASK, + FIELD_PREP(RTL931X_LED_CLK_SEL_MASK, clk_sel), RTL931X_LED_GLB_CTRL); + } + for (int set = 0; set < 4; set++) { char set_name[16] = {0}; u32 set_config[4]; diff --git a/target/linux/realtek/files-6.18/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-6.18/drivers/net/ethernet/rtl838x_eth.c index 06fe6f7ed0..0dfd36a82f 100644 --- a/target/linux/realtek/files-6.18/drivers/net/ethernet/rtl838x_eth.c +++ b/target/linux/realtek/files-6.18/drivers/net/ethernet/rtl838x_eth.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -113,6 +114,7 @@ struct rteth_ctrl { struct phylink_config phylink_config; const struct rteth_config *r; u32 lastEvent; + struct metadata_dst *dsa_meta[RTETH_931X_CPU_PORT]; /* receive handling */ dma_addr_t rx_data_dma; spinlock_t rx_lock; @@ -123,34 +125,34 @@ struct rteth_ctrl { struct rteth_tx *tx_data; }; -static void rteth_838x_create_tx_header(struct rteth_packet *h, unsigned int dest_port, int prio) +static void rteth_838x_create_tx_header(struct rteth_packet *h, unsigned int port, int prio) { /* cpu_tag[0] is reserved on the RTL83XX SoCs */ h->cpu_tag[1] = 0x0400; /* BIT 10: RTL8380_CPU_TAG */ h->cpu_tag[2] = 0x0200; /* Set only AS_DPM, to enable DPM settings below */ h->cpu_tag[3] = 0x0000; - h->cpu_tag[4] = BIT(dest_port) >> 16; - h->cpu_tag[5] = BIT(dest_port) & 0xffff; + h->cpu_tag[4] = BIT(port) >> 16; + h->cpu_tag[5] = BIT(port) & 0xffff; /* Set internal priority (PRI) and enable (AS_PRI) */ if (prio >= 0) h->cpu_tag[2] |= ((prio & 0x7) | BIT(3)) << 12; } -static void rteth_839x_create_tx_header(struct rteth_packet *h, unsigned int dest_port, int prio) +static void rteth_839x_create_tx_header(struct rteth_packet *h, unsigned int port, int prio) { /* cpu_tag[0] is reserved on the RTL83XX SoCs */ h->cpu_tag[1] = 0x0100; /* RTL8390_CPU_TAG marker */ h->cpu_tag[2] = BIT(4); /* AS_DPM flag */ h->cpu_tag[3] = h->cpu_tag[4] = h->cpu_tag[5] = 0; /* h->cpu_tag[1] |= BIT(1) | BIT(0); */ /* Bypass filter 1/2 */ - if (dest_port >= 32) { - dest_port -= 32; - h->cpu_tag[2] |= (BIT(dest_port) >> 16) & 0xf; - h->cpu_tag[3] = BIT(dest_port) & 0xffff; + if (port >= 32) { + port -= 32; + h->cpu_tag[2] |= (BIT(port) >> 16) & 0xf; + h->cpu_tag[3] = BIT(port) & 0xffff; } else { - h->cpu_tag[4] = BIT(dest_port) >> 16; - h->cpu_tag[5] = BIT(dest_port) & 0xffff; + h->cpu_tag[4] = BIT(port) >> 16; + h->cpu_tag[5] = BIT(port) & 0xffff; } /* Set internal priority (PRI) and enable (AS_PRI) */ @@ -158,7 +160,7 @@ static void rteth_839x_create_tx_header(struct rteth_packet *h, unsigned int des h->cpu_tag[2] |= ((prio & 0x7) | BIT(3)) << 8; } -static void rteth_93xx_create_tx_header(struct rteth_packet *h, unsigned int dest_port, int prio) +static void rteth_93xx_create_tx_header(struct rteth_packet *h, unsigned int port, int prio) { h->cpu_tag[0] = 0x8000; /* CPU tag marker */ h->cpu_tag[1] = FIELD_PREP(RTL93XX_CPU_TAG1_FWD_MASK, RTL93XX_CPU_TAG1_FWD_PHYSICAL) | @@ -166,10 +168,10 @@ static void rteth_93xx_create_tx_header(struct rteth_packet *h, unsigned int des h->cpu_tag[2] = (prio >= 0) ? (BIT(5) | (prio & 0x1f)) << 8 : 0; h->cpu_tag[3] = 0; - h->cpu_tag[4] = BIT_ULL(dest_port) >> 48; - h->cpu_tag[5] = BIT_ULL(dest_port) >> 32; - h->cpu_tag[6] = BIT_ULL(dest_port) >> 16; - h->cpu_tag[7] = BIT_ULL(dest_port) & 0xffff; + h->cpu_tag[4] = BIT_ULL(port) >> 48; + h->cpu_tag[5] = BIT_ULL(port) >> 32; + h->cpu_tag[6] = BIT_ULL(port) >> 16; + h->cpu_tag[7] = BIT_ULL(port) & 0xffff; } static inline void rteth_reenable_irq(struct rteth_ctrl *ctrl, int ring) @@ -1001,25 +1003,32 @@ static void rteth_tx_timeout(struct net_device *dev, unsigned int txqueue) } } -static int rteth_start_xmit(struct sk_buff *skb, struct net_device *dev) +static int rteth_get_dsa_port(struct sk_buff *skb, struct net_device *dev) { struct rteth_ctrl *ctrl = netdev_priv(dev); - int val, slot, len = skb->len, dest_port = -1; - int ring = skb_get_queue_mapping(skb); + u8 *trailer = &skb->data[skb->len - 4]; + + if (netdev_uses_dsa(dev) && + dev->dsa_ptr->tag_ops->proto == DSA_TAG_PROTO_RTL_OTTO && + trailer[0] < ctrl->r->cpu_port && + trailer[1] == 0xab && + trailer[2] == 0xcd && + trailer[3] == 0xef) + return trailer[0]; + + return -1; +} + +static int rteth_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + int port, val, slot, len = skb->len, ring = skb_get_queue_mapping(skb); + struct rteth_ctrl *ctrl = netdev_priv(dev); struct rteth_packet *packet; dma_addr_t packet_dma; - if (netdev_uses_dsa(dev) && - skb->data[len - 4] == 0x80 && - skb->data[len - 3] < ctrl->r->cpu_port && - skb->data[len - 2] == 0x10 && - skb->data[len - 1] == 0x00) { - dest_port = skb->data[len - 3]; - /* space will be reused for 4 byte layer 2 FCS */ - } else { - /* No DSA tag, add space for 4 byte layer 2 FCS */ - len += ETH_FCS_LEN; - } + port = rteth_get_dsa_port(skb, dev); + if (port < 0) + len += ETH_FCS_LEN; /* No reusable 4 byte tag, add space for 4 byte layer 2 FCS */ len = max(ETH_ZLEN + ETH_FCS_LEN, len); if (unlikely(skb_put_padto(skb, len))) { @@ -1056,8 +1065,8 @@ static int rteth_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } - if (dest_port >= 0) - ctrl->r->create_tx_header(packet, dest_port, 0); // TODO ok to set prio to 0? + if (port >= 0) + ctrl->r->create_tx_header(packet, port, 0); // TODO ok to set prio to 0? /* Transfer data and hand packet over to switch */ packet->len = len; @@ -1081,7 +1090,7 @@ static int rteth_start_xmit(struct sk_buff *skb, struct net_device *dev) regmap_write(ctrl->map, ctrl->r->dma_if_ctrl, val | RTETH_TX_TRIGGER(ctrl, ring)); dev->stats.tx_packets++; - dev->stats.tx_bytes += len; + dev->stats.tx_bytes += len - ETH_FCS_LEN; spin_unlock(&ctrl->tx_lock); @@ -1090,11 +1099,10 @@ static int rteth_start_xmit(struct sk_buff *skb, struct net_device *dev) static int rteth_hw_receive(struct net_device *dev, int ring, int budget) { - int slot, len, work_done = 0, rx_packets = 0, rx_bytes = 0; + int slot, work_done = 0, rx_packets = 0, rx_bytes = 0; struct rteth_ctrl *ctrl = netdev_priv(dev); - unsigned int new_offset, old_offset; + unsigned int len, new_offset, old_offset; struct page *old_page, *new_page; - bool dsa = netdev_uses_dsa(dev); struct rteth_packet *packet; dma_addr_t packet_dma; struct sk_buff *skb; @@ -1109,9 +1117,9 @@ static int rteth_hw_receive(struct net_device *dev, int ring, int budget) break; packet = &ctrl->rx_data[ring].packet[slot]; - len = packet->len; + len = packet->len - ETH_FCS_LEN; - if (unlikely(len < ETH_FCS_LEN || len > RING_BUFFER)) { + if (unlikely(len > RING_BUFFER)) { netdev_err(dev, "invalid packet with %d bytes received\n", len); dev->stats.rx_errors++; goto recycle; @@ -1131,9 +1139,6 @@ static int rteth_hw_receive(struct net_device *dev, int ring, int budget) packet->page_offset = new_offset; packet->dma = page_pool_get_dma_addr(new_page) + new_offset + RTETH_SKB_HEADROOM; - if (!dsa) - len -= ETH_FCS_LEN; - page_pool_dma_sync_for_cpu(ctrl->rx_qs[ring].page_pool, old_page, old_offset + RTETH_SKB_HEADROOM, len); @@ -1149,13 +1154,11 @@ static int rteth_hw_receive(struct net_device *dev, int ring, int budget) skb_put(skb, len); ctrl->r->decode_tag(packet, &tag); - if (dsa) { - skb->data[len - 4] = 0x80; - skb->data[len - 3] = tag.port; - skb->data[len - 2] = 0x10; - skb->data[len - 1] = 0x00; + if (netdev_uses_dsa(dev)) { + if (tag.port < ctrl->r->cpu_port) + skb_dst_set_noref(skb, &ctrl->dsa_meta[tag.port]->dst); if (tag.l2_offloaded) - skb->data[len - 3] |= 0x40; + skb->offload_fwd_mark = 1; } skb->protocol = eth_type_trans(skb, dev); @@ -1599,6 +1602,32 @@ static const struct ethtool_ops rteth_ethtool_ops = { .set_link_ksettings = rteth_set_link_ksettings, }; +static int rteth_metadata_dst_alloc(struct rteth_ctrl *ctrl) +{ + struct metadata_dst *md_dst; + + for (int i = 0; i < ARRAY_SIZE(ctrl->dsa_meta); i++) { + md_dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX, GFP_KERNEL); + if (!md_dst) + return -ENOMEM; + + md_dst->u.port_info.port_id = i; + ctrl->dsa_meta[i] = md_dst; + } + + return 0; +} + +static void rteth_metadata_dst_free(struct rteth_ctrl *ctrl) +{ + for (int i = 0; i < ARRAY_SIZE(ctrl->dsa_meta); i++) { + if (!ctrl->dsa_meta[i]) + continue; + + metadata_dst_free(ctrl->dsa_meta[i]); + } +} + static int rteth_probe(struct platform_device *pdev) { struct page_pool_params pp_params = { @@ -1755,6 +1784,10 @@ static int rteth_probe(struct platform_device *pdev) } } + err = rteth_metadata_dst_alloc(ctrl); + if (err) + goto cleanup; + err = register_netdev(dev); if (err) goto cleanup; @@ -1762,6 +1795,7 @@ static int rteth_probe(struct platform_device *pdev) return 0; cleanup: + rteth_metadata_dst_free(ctrl); if (ctrl->phylink) phylink_destroy(ctrl->phylink); for (int i = 0; i < RTETH_RX_RINGS; i++) { @@ -1780,6 +1814,7 @@ static void rteth_remove(struct platform_device *pdev) pr_info("Removing platform driver for rtl838x-eth\n"); unregister_netdev(dev); + rteth_metadata_dst_free(ctrl); if (ctrl->phylink) phylink_destroy(ctrl->phylink); diff --git a/target/linux/realtek/files-6.18/drivers/net/mdio/mdio-realtek-otto.c b/target/linux/realtek/files-6.18/drivers/net/mdio/mdio-realtek-otto.c index c4d425b784..0a4214166f 100644 --- a/target/linux/realtek/files-6.18/drivers/net/mdio/mdio-realtek-otto.c +++ b/target/linux/realtek/files-6.18/drivers/net/mdio/mdio-realtek-otto.c @@ -92,6 +92,7 @@ #define RTMD_PHY_RTL8224 0x001ccad0 #define RTMD_PHY_RTL8226 0x001cc838 #define RTMD_PHY_RTL8261 0x001ccaf3 +#define RTMD_PHY_RTL8264B 0x001cc813 #define RTMD_PHY_MAC_1G 3 #define RTMD_PHY_MAC_2G_PLUS 1 @@ -737,6 +738,7 @@ static int rtmd_get_phy_info(struct rtmd_ctrl *ctrl, int pn, struct rtmd_phy_inf phyinfo->poll_lpa_1000 = RTMD_PHY_POLL_MMD(31, 0xa414, 11); break; case RTMD_PHY_RTL8261: + case RTMD_PHY_RTL8264B: phyinfo->mac_type = RTMD_PHY_MAC_2G_PLUS; phyinfo->has_giga_lite = true; phyinfo->has_res_reg = true; diff --git a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c index e236b94df2..bb6b1c8219 100644 --- a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c +++ b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c @@ -25,6 +25,10 @@ #define RTPCS_SPEED_2500 5 #define RTPCS_SPEED_5000 6 +/* USXGMII-AN opcodes. RTK variant unused but kept for documentation */ +#define RTPCS_USXGMII_AN_OPC_STD 0x03 +#define RTPCS_USXGMII_AN_OPC_RTK 0xaa + #define RTPCS_838X_CPU_PORT 28 #define RTPCS_838X_SERDES_CNT 6 #define RTPCS_838X_MAC_LINK_DUP_STS 0xa19c @@ -112,6 +116,56 @@ #define RTPCS_931X_SDS_MAIN_AMP_MASK GENMASK(9, 5) #define RTPCS_931X_SDS_POST_AMP_MASK GENMASK(14, 10) +/* + * A SerDes has a register space separated into several pages. Each page + * serves a different purpose and is the home of common settings. E.g., + * there are dedicated pages for each operating speed of a SerDes. + */ +enum rtpcs_page { + PAGE_SDS = 0x00, + PAGE_SDS_EXT = 0x01, + PAGE_FIB = 0x02, + PAGE_FIB_EXT = 0x03, + PAGE_TGR_STD_0 = 0x04, + PAGE_TGR_STD_1 = 0x05, + PAGE_TGR_PRO_0 = 0x06, + PAGE_TGR_PRO_1 = 0x07, + PAGE_TGX_STD_0 = 0x08, + PAGE_TGX_STD_1 = 0x09, + PAGE_TGX_PRO_0 = 0x0a, + PAGE_TGX_PRO_1 = 0x0b, + PAGE_WDIG = 0x1f, + PAGE_ANA_MISC = 0x20, + PAGE_ANA_COM = 0x21, + PAGE_ANA_SPD = 0x22, + PAGE_ANA_SPD_EXT = 0x23, + PAGE_ANA_1G2 = 0x24, + PAGE_ANA_1G2_EXT = 0x25, + PAGE_ANA_2G5 = 0x26, + PAGE_ANA_2G5_EXT = 0x27, + PAGE_ANA_3G1 = 0x28, + PAGE_ANA_3G1_EXT = 0x29, + PAGE_ANA_5G0 = 0x2a, + PAGE_ANA_5G0_EXT = 0x2b, + PAGE_ANA_6G2 = 0x2c, + PAGE_ANA_6G2_EXT = 0x2d, + PAGE_ANA_10G = 0x2e, + PAGE_ANA_10G_EXT = 0x2f, + PAGE_GPON_SP = 0x30, + PAGE_GPON_SP_EXT = 0x31, + PAGE_EPON_SP = 0x32, + PAGE_EPON_SP_EXT = 0x33, + PAGE_ANA_6G0 = 0x34, + PAGE_ANA_6G0_EXT = 0x35, +}; + +/* + * RTL931X only: the digital SDS 1/2 register pages mirror an analog page at a + * fixed +0x40 / +0x80 region offset. See rtpcs_931x_sds_op_xsg_write(). + */ +#define DIGI_1(page) ((page) + 0x40) +#define DIGI_2(page) ((page) + 0x80) + enum rtpcs_sds_type { RTPCS_SDS_TYPE_UNKNOWN, RTPCS_SDS_TYPE_5G, @@ -172,13 +226,14 @@ struct rtpcs_ctrl; struct rtpcs_serdes; struct rtpcs_sds_ops { - int (*read)(struct rtpcs_serdes *sds, int page, int regnum, int bithigh, int bitlow); - int (*write)(struct rtpcs_serdes *sds, int page, int regnum, int bithigh, int bitlow, - u16 value); + int (*read)(struct rtpcs_serdes *sds, enum rtpcs_page page, int regnum, + int bithigh, int bitlow); + int (*write)(struct rtpcs_serdes *sds, enum rtpcs_page page, int regnum, + int bithigh, int bitlow, u16 value); /* optional */ - int (*xsg_write)(struct rtpcs_serdes *sds, int page, int regnum, int bithigh, int bitlow, - u16 value); + int (*xsg_write)(struct rtpcs_serdes *sds, enum rtpcs_page page, int regnum, + int bithigh, int bitlow, u16 value); int (*set_autoneg)(struct rtpcs_serdes *sds, unsigned int neg_mode, const unsigned long *advertising); @@ -199,12 +254,19 @@ struct rtpcs_sds_ops { int (*deactivate)(struct rtpcs_serdes *sds); /* required: power back up */ int (*activate)(struct rtpcs_serdes *sds); + /* required: configure SerDes for hardware mode */ + int (*config_hw_mode)(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode); + /* required: set hardware mode */ + int (*set_hw_mode)(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode); + /* optional: configure media-specific parameters */ + int (*config_media)(struct rtpcs_serdes *sds, enum rtpcs_sds_media media, + enum rtpcs_sds_mode hw_mode); /* optional: finalization that must follow power-up, e.g. RX calibration */ int (*post_config)(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode); }; struct rtpcs_sds_reg_field { - u8 page; + enum rtpcs_page page; u8 reg; u8 msb; u8 lsb; @@ -232,6 +294,7 @@ struct rtpcs_serdes { s16 link_port[RTPCS_MAX_LINKS_PER_SDS]; enum rtpcs_sds_mode hw_mode; + enum rtpcs_sds_media media; u8 id; u8 num_of_links; bool first_start; @@ -273,11 +336,10 @@ struct rtpcs_config { int (*init)(struct rtpcs_ctrl *ctrl); int (*sds_probe)(struct rtpcs_serdes *sds); - int (*setup_serdes)(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode); }; struct rtpcs_sds_config { - u8 page; + enum rtpcs_page page; u8 reg; u16 data; }; @@ -288,7 +350,7 @@ struct rtpcs_sds_tx_config { u8 post_amp; }; -static int rtpcs_sds_to_mmd(int sds_page, int sds_regnum) +static int rtpcs_sds_to_mmd(enum rtpcs_page sds_page, int sds_regnum) { return (sds_page << 8) + sds_regnum; } @@ -300,8 +362,8 @@ static int rtpcs_sds_to_mmd(int sds_page, int sds_regnum) * implementing the SerDes read/write ops. */ -static int __rtpcs_sds_read_raw(struct rtpcs_ctrl *ctrl, int sds_id, int page, int regnum, - int bithigh, int bitlow) +static int __rtpcs_sds_read_raw(struct rtpcs_ctrl *ctrl, int sds_id, enum rtpcs_page page, + int regnum, int bithigh, int bitlow) { int mmd_regnum = rtpcs_sds_to_mmd(page, regnum); u16 mask; @@ -318,8 +380,8 @@ static int __rtpcs_sds_read_raw(struct rtpcs_ctrl *ctrl, int sds_id, int page, i return (val & mask) >> bitlow; } -static int __rtpcs_sds_write_raw(struct rtpcs_ctrl *ctrl, int sds_id, int page, int regnum, - int bithigh, int bitlow, u16 value) +static int __rtpcs_sds_write_raw(struct rtpcs_ctrl *ctrl, int sds_id, enum rtpcs_page page, + int regnum, int bithigh, int bitlow, u16 value) { int mmd_regnum = rtpcs_sds_to_mmd(page, regnum); u16 mask, set; @@ -337,38 +399,38 @@ static int __rtpcs_sds_write_raw(struct rtpcs_ctrl *ctrl, int sds_id, int page, /* Generic implementations, if no special behavior is needed */ -static int rtpcs_generic_sds_op_read(struct rtpcs_serdes *sds, int page, int regnum, int bithigh, - int bitlow) +static int rtpcs_generic_sds_op_read(struct rtpcs_serdes *sds, enum rtpcs_page page, int regnum, + int bithigh, int bitlow) { return __rtpcs_sds_read_raw(sds->ctrl, sds->id, page, regnum, bithigh, bitlow); } -static int rtpcs_generic_sds_op_write(struct rtpcs_serdes *sds, int page, int regnum, int bithigh, - int bitlow, u16 value) +static int rtpcs_generic_sds_op_write(struct rtpcs_serdes *sds, enum rtpcs_page page, int regnum, + int bithigh, int bitlow, u16 value) { return __rtpcs_sds_write_raw(sds->ctrl, sds->id, page, regnum, bithigh, bitlow, value); } /* Convenience helpers */ -static int rtpcs_sds_read_bits(struct rtpcs_serdes *sds, int page, int regnum, int bithigh, - int bitlow) +static int rtpcs_sds_read_bits(struct rtpcs_serdes *sds, enum rtpcs_page page, int regnum, + int bithigh, int bitlow) { return sds->ops->read(sds, page, regnum, bithigh, bitlow); } -static int rtpcs_sds_write_bits(struct rtpcs_serdes *sds, int page, int regnum, int bithigh, - int bitlow, u16 value) +static int rtpcs_sds_write_bits(struct rtpcs_serdes *sds, enum rtpcs_page page, int regnum, + int bithigh, int bitlow, u16 value) { return sds->ops->write(sds, page, regnum, bithigh, bitlow, value); } -static int rtpcs_sds_read(struct rtpcs_serdes *sds, int page, int regnum) +static int rtpcs_sds_read(struct rtpcs_serdes *sds, enum rtpcs_page page, int regnum) { return sds->ops->read(sds, page, regnum, 15, 0); } -static int rtpcs_sds_write(struct rtpcs_serdes *sds, int page, int regnum, u16 value) +static int rtpcs_sds_write(struct rtpcs_serdes *sds, enum rtpcs_page page, int regnum, u16 value) { return sds->ops->write(sds, page, regnum, 15, 0, value); } @@ -385,9 +447,8 @@ static int rtpcs_sds_write_field(struct rtpcs_serdes *sds, const struct rtpcs_sd return sds->ops->write(sds, field->page, field->reg, field->msb, field->lsb, value); } -__maybe_unused -static int rtpcs_sds_xsg_write_bits(struct rtpcs_serdes *sds, int page, int regnum, int bithigh, - int bitlow, u16 value) +static int rtpcs_sds_xsg_write_bits(struct rtpcs_serdes *sds, enum rtpcs_page page, int regnum, + int bithigh, int bitlow, u16 value) { if (!sds->ops->xsg_write) return -ENOTSUPP; @@ -395,8 +456,8 @@ static int rtpcs_sds_xsg_write_bits(struct rtpcs_serdes *sds, int page, int regn return sds->ops->xsg_write(sds, page, regnum, bithigh, bitlow, value); } -__maybe_unused -static int rtpcs_sds_xsg_write(struct rtpcs_serdes *sds, int page, int regnum, u16 value) +static int rtpcs_sds_xsg_write(struct rtpcs_serdes *sds, enum rtpcs_page page, int regnum, + u16 value) { if (!sds->ops->xsg_write) return -ENOTSUPP; @@ -406,16 +467,6 @@ static int rtpcs_sds_xsg_write(struct rtpcs_serdes *sds, int page, int regnum, u /* Other helpers */ -__maybe_unused -static int rtpcs_sds_modify(struct rtpcs_serdes *sds, int page, int regnum, - u16 mask, u16 set) -{ - int mmd_regnum = rtpcs_sds_to_mmd(page, regnum); - - return mdiobus_c45_modify(sds->ctrl->bus, sds->id, MDIO_MMD_VEND1, - mmd_regnum, mask, set); -} - static struct rtpcs_serdes *rtpcs_sds_get_even(struct rtpcs_serdes *sds) { u32 even_sds = sds->id & ~1; @@ -452,9 +503,8 @@ static struct rtpcs_link *rtpcs_phylink_pcs_to_link(struct phylink_pcs *pcs) return container_of(pcs, struct rtpcs_link, pcs); } -static int rtpcs_sds_determine_hw_mode(struct rtpcs_serdes *sds, - phy_interface_t if_mode, - enum rtpcs_sds_mode *hw_mode) +static int rtpcs_sds_select_hw_mode(struct rtpcs_serdes *sds, phy_interface_t if_mode, + enum rtpcs_sds_mode *hw_mode) { u8 n_links = sds->num_of_links; @@ -510,6 +560,26 @@ static int rtpcs_sds_determine_hw_mode(struct rtpcs_serdes *sds, return 0; } +static int rtpcs_sds_select_media(enum rtpcs_sds_mode hw_mode, enum rtpcs_sds_media *media) +{ + switch (hw_mode) { + case RTPCS_SDS_MODE_OFF: + *media = RTPCS_SDS_MEDIA_NONE; + break; + case RTPCS_SDS_MODE_SGMII: + case RTPCS_SDS_MODE_1000BASEX: + case RTPCS_SDS_MODE_2500BASEX: + case RTPCS_SDS_MODE_10GBASER: + *media = RTPCS_SDS_MEDIA_FIBER; + break; + default: + *media = RTPCS_SDS_MEDIA_PCB; + break; + } + + return 0; +} + static bool rtpcs_sds_mode_is_usxgmii(enum rtpcs_sds_mode hw_mode) { return (hw_mode == RTPCS_SDS_MODE_USXGMII_10GSXGMII || @@ -672,47 +742,47 @@ static void rtpcs_838x_sds_patch_qsgmii(struct rtpcs_serdes *sds) { bool is_even = (rtpcs_sds_get_even(sds) == sds); - rtpcs_sds_write(sds, 0x1, 0x3, 0xf46d); - rtpcs_sds_write(sds, 0x1, 0x2, 0x85fa); - rtpcs_sds_write(sds, 0x1, 0x6, 0x20d8); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 0x3, 0xf46d); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 0x2, 0x85fa); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 0x6, 0x20d8); - rtpcs_sds_write(sds, 0x1, 10, is_even ? 0x58c7 : 0x80c7); - rtpcs_sds_write(sds, 0x1, 17, is_even ? 0xb7c9 : 0x4208); - rtpcs_sds_write(sds, 0x1, 18, is_even ? 0xab8e : 0xc208); - rtpcs_sds_write(sds, 0x1, 11, 0x482); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 10, is_even ? 0x58c7 : 0x80c7); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 17, is_even ? 0xb7c9 : 0x4208); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 18, is_even ? 0xab8e : 0xc208); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 11, 0x482); if (is_even) - rtpcs_sds_write(sds, 0x1, 19, 0x24ab); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 19, 0x24ab); - rtpcs_sds_write(sds, 0x2, 25, 0x303); - rtpcs_sds_write(sds, 0x1, 14, 0xfcc2); + rtpcs_sds_write(sds, PAGE_FIB, 25, 0x303); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 14, 0xfcc2); } static void rtpcs_838x_sds_patch_fiber(struct rtpcs_serdes *sds) { bool is_even = rtpcs_sds_get_even(sds) == sds; - rtpcs_sds_write(sds, 1, 2, 0x85fa); - rtpcs_sds_write(sds, 1, 3, 0x00); - rtpcs_sds_write(sds, 1, 4, 0xdccc); - rtpcs_sds_write(sds, 1, 5, 0x00); - rtpcs_sds_write(sds, 1, 6, is_even ? 0x20d8 : 0x3600); - rtpcs_sds_write(sds, 1, 7, 0x03); - rtpcs_sds_write(sds, 1, 8, 0x79aa); - rtpcs_sds_write(sds, 1, 9, 0x8c64); - rtpcs_sds_write(sds, 1, 10, 0xc3); - rtpcs_sds_write(sds, 1, 11, 0x1482); - rtpcs_sds_write(sds, 1, 17, 0xb7c9); - rtpcs_sds_write(sds, 1, 18, 0xab8e); - rtpcs_sds_write(sds, 2, 24, 0x14aa); - rtpcs_sds_write(sds, 2, 25, 0x303); - rtpcs_sds_write(sds, 1, 14, 0xf002); - rtpcs_sds_write(sds, 2, 27, 0x4bf); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 2, 0x85fa); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 3, 0x00); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 4, 0xdccc); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 5, 0x00); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 6, is_even ? 0x20d8 : 0x3600); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 7, 0x03); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 8, 0x79aa); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 9, 0x8c64); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 10, 0xc3); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 11, 0x1482); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 17, 0xb7c9); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 18, 0xab8e); + rtpcs_sds_write(sds, PAGE_FIB, 24, 0x14aa); + rtpcs_sds_write(sds, PAGE_FIB, 25, 0x303); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 14, 0xf002); + rtpcs_sds_write(sds, PAGE_FIB, 27, 0x4bf); } static void rtpcs_838x_sds_reset(struct rtpcs_serdes *sds) { - rtpcs_sds_write_bits(sds, 0, 3, 6, 6, 0x1); /* REG3 SOFT_RST */ - rtpcs_sds_write_bits(sds, 0, 3, 6, 6, 0x0); /* REG3 SOFT_RST */ + rtpcs_sds_write_bits(sds, PAGE_SDS, 3, 6, 6, 0x1); /* REG3 SOFT_RST */ + rtpcs_sds_write_bits(sds, PAGE_SDS, 3, 6, 6, 0x0); /* REG3 SOFT_RST */ } static void rtpcs_838x_sds_fill_caps(struct rtpcs_serdes *sds) @@ -756,25 +826,27 @@ static int rtpcs_838x_sds_deactivate(struct rtpcs_serdes *sds) return ret; /* EN_RX | EN_TX */ - ret = rtpcs_sds_write_bits(sds, 0, 0, 1, 0, 0x0); + ret = rtpcs_sds_write_bits(sds, PAGE_SDS, 0, 1, 0, 0x0); if (ret) return ret; /* CFG_FIB_PDOWN / BMCR_PDOWN */ - return rtpcs_sds_write_bits(sds, 2, MII_BMCR, 11, 11, 0x1); + return rtpcs_sds_write_bits(sds, PAGE_FIB, MII_BMCR, 11, 11, 0x1); } static int rtpcs_838x_sds_activate(struct rtpcs_serdes *sds) { int ret; + rtpcs_838x_sds_reset(sds); + /* CFG_FIB_PDOWN / BMCR_PDOWN */ - ret = rtpcs_sds_write_bits(sds, 2, MII_BMCR, 11, 11, 0x0); + ret = rtpcs_sds_write_bits(sds, PAGE_FIB, MII_BMCR, 11, 11, 0x0); if (ret) return ret; /* EN_RX | EN_TX */ - ret = rtpcs_sds_write_bits(sds, 0, 0, 1, 0, 0x3); + ret = rtpcs_sds_write_bits(sds, PAGE_SDS, 0, 1, 0, 0x3); if (ret) return ret; @@ -816,21 +888,20 @@ static int rtpcs_838x_sds_set_mode(struct rtpcs_serdes *sds, enum rtpcs_sds_mode 0x7 << int_mode_shift, int_mode_val << int_mode_shift); } -static int rtpcs_838x_sds_patch(struct rtpcs_serdes *sds, - enum rtpcs_sds_mode hw_mode) +static int rtpcs_838x_sds_config_hw_mode(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode) { struct rtpcs_ctrl *ctrl = sds->ctrl; u8 sds_id = sds->id; - rtpcs_sds_write(sds, 0, 1, 0xf00); + rtpcs_sds_write(sds, PAGE_SDS, 1, 0xf00); usleep_range(1000, 2000); - rtpcs_sds_write(sds, 0, 2, 0x7060); + rtpcs_sds_write(sds, PAGE_SDS, 2, 0x7060); usleep_range(1000, 2000); if (sds_id >= 4) { - rtpcs_sds_write(sds, 2, 30, 0x71e); + rtpcs_sds_write(sds, PAGE_FIB, 30, 0x71e); usleep_range(1000, 2000); - rtpcs_sds_write(sds, 0, 4, 0x74d); + rtpcs_sds_write(sds, PAGE_SDS, 4, 0x74d); usleep_range(1000, 2000); } @@ -855,11 +926,11 @@ static int rtpcs_838x_sds_patch(struct rtpcs_serdes *sds, /* CKREFBUF_S0S1 */ regmap_write_bits(ctrl->map, RTPCS_838X_PLL_CML_CTRL, 0xf, 0xf); - rtpcs_sds_write_bits(sds, 0x1, 0x3, 1, 1, 0x1); /* REG_CML_SEL */ + rtpcs_sds_write_bits(sds, PAGE_SDS_EXT, 0x3, 1, 1, 0x1); /* REG_CML_SEL */ } - rtpcs_sds_write(sds, 0x1, 0x9, 0x8e64); - rtpcs_sds_write(sds, 0x1, 0x9, 0x8c64); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 0x9, 0x8e64); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 0x9, 0x8c64); return 0; } @@ -890,23 +961,6 @@ static int rtpcs_838x_init(struct rtpcs_ctrl *ctrl) return 0; } -static int rtpcs_838x_setup_serdes(struct rtpcs_serdes *sds, - enum rtpcs_sds_mode hw_mode) -{ - int ret; - - rtpcs_838x_sds_patch(sds, hw_mode); - - ret = rtpcs_838x_sds_set_mode(sds, hw_mode); - if (ret) - return ret; - - sds->hw_mode = hw_mode; - - rtpcs_838x_sds_reset(sds); - return 0; -} - static int rtpcs_838x_sds_post_config(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode) { /* @@ -954,33 +1008,33 @@ static void rtpcs_839x_sds_reset(struct rtpcs_serdes *sds) return; if (sds->type == RTPCS_SDS_TYPE_10G) { - rtpcs_sds_write_bits(odd_sds, 0x2f, 0x1d, 3, 0, 0x5); + rtpcs_sds_write_bits(odd_sds, PAGE_ANA_10G_EXT, 0x1d, 3, 0, 0x5); msleep(500); - rtpcs_sds_write_bits(odd_sds, 0x2f, 0x1d, 3, 0, 0xf); - rtpcs_sds_write_bits(odd_sds, 0x2f, 0x1d, 3, 0, 0x0); + rtpcs_sds_write_bits(odd_sds, PAGE_ANA_10G_EXT, 0x1d, 3, 0, 0xf); + rtpcs_sds_write_bits(odd_sds, PAGE_ANA_10G_EXT, 0x1d, 3, 0, 0x0); - rtpcs_sds_write_bits(even_sds, 0x2e, 0x10, 3, 3, 0x0); - rtpcs_sds_write_bits(even_sds, 0x2f, 0x0, 15, 15, 0x1); + rtpcs_sds_write_bits(even_sds, PAGE_ANA_10G, 0x10, 3, 3, 0x0); + rtpcs_sds_write_bits(even_sds, PAGE_ANA_10G_EXT, 0x0, 15, 15, 0x1); msleep(100); - rtpcs_sds_write_bits(even_sds, 0x2f, 0x0, 15, 15, 0x0); + rtpcs_sds_write_bits(even_sds, PAGE_ANA_10G_EXT, 0x0, 15, 15, 0x0); } else { - rtpcs_sds_write(odd_sds, 0x25, 0x1, 0x0050); - rtpcs_sds_write(odd_sds, 0x25, 0x1, 0x00f0); - rtpcs_sds_write(odd_sds, 0x25, 0x1, 0x0000); + rtpcs_sds_write(odd_sds, PAGE_ANA_1G2_EXT, 0x1, 0x0050); + rtpcs_sds_write(odd_sds, PAGE_ANA_1G2_EXT, 0x1, 0x00f0); + rtpcs_sds_write(odd_sds, PAGE_ANA_1G2_EXT, 0x1, 0x0000); - rtpcs_sds_write_bits(sds, 0x24, 0x14, 0, 0, 0x0); - rtpcs_sds_write_bits(sds, 0x24, 0x14, 9, 9, 0x1); + rtpcs_sds_write_bits(sds, PAGE_ANA_1G2, 0x14, 0, 0, 0x0); + rtpcs_sds_write_bits(sds, PAGE_ANA_1G2, 0x14, 9, 9, 0x1); msleep(100); - rtpcs_sds_write_bits(sds, 0x24, 0x14, 9, 9, 0x0); + rtpcs_sds_write_bits(sds, PAGE_ANA_1G2, 0x14, 9, 9, 0x0); } - rtpcs_sds_write(even_sds, 0x0, 0x3, 0x7146); + rtpcs_sds_write(even_sds, PAGE_SDS, 0x3, 0x7146); msleep(100); - rtpcs_sds_write(even_sds, 0x0, 0x3, 0x7106); + rtpcs_sds_write(even_sds, PAGE_SDS, 0x3, 0x7106); - rtpcs_sds_write(odd_sds, 0x0, 0x3, 0x7146); + rtpcs_sds_write(odd_sds, PAGE_SDS, 0x3, 0x7146); msleep(100); - rtpcs_sds_write(odd_sds, 0x0, 0x3, 0x7106); + rtpcs_sds_write(odd_sds, PAGE_SDS, 0x3, 0x7106); } static void rtpcs_839x_sds_fill_caps(struct rtpcs_serdes *sds) @@ -1029,105 +1083,105 @@ static int rtpcs_839x_sds_probe(struct rtpcs_serdes *sds) return 0; /* Part 1: register setup */ - rtpcs_sds_write(sds, 0x2e, 0x0, 0x5800); - rtpcs_sds_write(sds, 0x2e, 0x1, 0x4000); - rtpcs_sds_write(sds, 0x2e, 0x2, is_even ? 0x5400 : 0x5000); - rtpcs_sds_write(sds, 0x2e, 0x3, 0x0000); - rtpcs_sds_write(sds, 0x2e, 0x4, 0x0000); - rtpcs_sds_write(sds, 0x2e, 0x5, 0x4000); - rtpcs_sds_write(sds, 0x2e, 0x6, 0x4000); - rtpcs_sds_write(sds, 0x2e, 0x7, 0xffff); - rtpcs_sds_write(sds, 0x2e, 0x8, 0xffff); - rtpcs_sds_write(sds, 0x2e, 0x9, 0x806f); - rtpcs_sds_write(sds, 0x2e, 0xa, 0x0004); - rtpcs_sds_write(sds, 0x2e, 0xb, 0x0000); - rtpcs_sds_write(sds, 0x2e, 0xc, 0x0000); - rtpcs_sds_write(sds, 0x2e, 0xd, 0x0000); - rtpcs_sds_write(sds, 0x2e, 0xe, 0x0a00); - rtpcs_sds_write(sds, 0x2e, 0xf, 0x2000); - rtpcs_sds_write(sds, 0x2e, 0x10, 0xf00e); - rtpcs_sds_write(sds, 0x2e, 0x11, is_even ? 0xf04a : 0xfdab); - rtpcs_sds_write(sds, 0x2e, 0x12, is_even ? 0x97b3 : 0x96ea); - rtpcs_sds_write(sds, 0x2e, 0x13, 0x5318); - rtpcs_sds_write(sds, 0x2e, 0x14, 0x0f03); - rtpcs_sds_write(sds, 0x2e, 0x15, 0x0000); - rtpcs_sds_write(sds, 0x2e, 0x16, 0x0000); - rtpcs_sds_write(sds, 0x2e, 0x17, 0x0000); - rtpcs_sds_write(sds, 0x2e, 0x18, 0x0000); - rtpcs_sds_write(sds, 0x2e, 0x19, 0x0000); - rtpcs_sds_write(sds, 0x2e, 0x1a, 0xffff); - rtpcs_sds_write(sds, 0x2e, 0x1b, 0x0000); - rtpcs_sds_write(sds, 0x2e, 0x1c, 0x1203); - rtpcs_sds_write(sds, 0x2e, 0x1d, 0x0000); - rtpcs_sds_write(sds, 0x2e, 0x1e, 0xa052); - rtpcs_sds_write(sds, 0x2e, 0x1f, 0x9a00); - rtpcs_sds_write(sds, 0x2f, 0x0, 0x00f5); - rtpcs_sds_write(sds, 0x2f, 0x1, 0xf000); - rtpcs_sds_write(sds, 0x2f, 0x2, is_even ? 0x41ff : 0x4079); - rtpcs_sds_write(sds, 0x2f, 0x3, 0x0000); - rtpcs_sds_write(sds, 0x2f, 0x4, is_even ? 0x39ff : 0x93fa); - rtpcs_sds_write(sds, 0x2f, 0x5, 0x3340); - rtpcs_sds_write(sds, 0x2f, 0x6, is_even ? 0x40aa : 0x4280); - rtpcs_sds_write(sds, 0x2f, 0x7, 0x0000); - rtpcs_sds_write(sds, 0x2f, 0x8, 0x801f); - rtpcs_sds_write(sds, 0x2f, 0x9, 0x0000); - rtpcs_sds_write(sds, 0x2f, 0xa, 0x619c); - rtpcs_sds_write(sds, 0x2f, 0xb, 0xffed); - rtpcs_sds_write(sds, 0x2f, 0xc, 0x29ff); - rtpcs_sds_write(sds, 0x2f, 0xd, 0x29ff); - rtpcs_sds_write(sds, 0x2f, 0xe, is_even ? 0x4e10 : 0x4c50); - rtpcs_sds_write(sds, 0x2f, 0xf, is_even ? 0x4e10 : 0x4c50); - rtpcs_sds_write(sds, 0x2f, 0x10, 0x0000); - rtpcs_sds_write(sds, 0x2f, 0x11, 0x0000); - rtpcs_sds_write(sds, 0x0, 0xc, 0x08ec); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x0, 0x5800); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x1, 0x4000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x2, is_even ? 0x5400 : 0x5000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x3, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x4, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x5, 0x4000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x6, 0x4000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x7, 0xffff); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x8, 0xffff); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x9, 0x806f); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0xa, 0x0004); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0xb, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0xc, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0xd, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0xe, 0x0a00); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0xf, 0x2000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x10, 0xf00e); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x11, is_even ? 0xf04a : 0xfdab); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x12, is_even ? 0x97b3 : 0x96ea); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x13, 0x5318); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x14, 0x0f03); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x15, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x16, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x17, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x18, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x19, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x1a, 0xffff); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x1b, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x1c, 0x1203); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x1d, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x1e, 0xa052); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x1f, 0x9a00); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x0, 0x00f5); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x1, 0xf000); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x2, is_even ? 0x41ff : 0x4079); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x3, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x4, is_even ? 0x39ff : 0x93fa); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x5, 0x3340); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x6, is_even ? 0x40aa : 0x4280); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x7, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x8, 0x801f); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x9, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0xa, 0x619c); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0xb, 0xffed); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0xc, 0x29ff); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0xd, 0x29ff); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0xe, is_even ? 0x4e10 : 0x4c50); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0xf, is_even ? 0x4e10 : 0x4c50); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x10, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x11, 0x0000); + rtpcs_sds_write(sds, PAGE_SDS, 0xc, 0x08ec); if (!is_even) - rtpcs_sds_write(sds, 0x2f, 0x1f, 0x003f); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x1f, 0x003f); /* Part 2: register bit patching (contains some "reset flips") */ - rtpcs_sds_write_bits(sds, 0x0, 0x7, 14, 14, 0x0001); - rtpcs_sds_write_bits(sds, 0x2f, 0x9, 15, 0, 0x417f); - rtpcs_sds_write_bits(sds, 0x2e, 0x1c, 9, 9, 0x0000); - rtpcs_sds_write_bits(sds, 0x2e, 0x1c, 12, 10, 0x0000); - rtpcs_sds_write_bits(sds, 0x2e, 0x1c, 5, 3, 0x0005); - rtpcs_sds_write_bits(sds, 0x2e, 0x1c, 8, 6, 0x0000); - rtpcs_sds_write_bits(sds, 0x2e, 0x1c, 2, 0, 0x0002); - rtpcs_sds_write_bits(sds, 0x2f, 0x1, 15, 0, 0xc440); + rtpcs_sds_write_bits(sds, PAGE_SDS, 0x7, 14, 14, 0x0001); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x9, 15, 0, 0x417f); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1c, 9, 9, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1c, 12, 10, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1c, 5, 3, 0x0005); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1c, 8, 6, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1c, 2, 0, 0x0002); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x1, 15, 0, 0xc440); if (is_even) - rtpcs_sds_write_bits(sds, 0x2f, 0x6, 3, 3, 0x0000); - rtpcs_sds_write_bits(sds, 0x2e, 0x5, 15, 0, 0x8000); - rtpcs_sds_write_bits(sds, 0x2e, 0x6, 15, 0, 0x8000); - rtpcs_sds_write_bits(sds, 0x2e, 0xa, 15, 0, 0x0000); - rtpcs_sds_write_bits(sds, 0x2e, 0x1e, 15, 0, 0x0002); - rtpcs_sds_write_bits(sds, 0x2e, 0x1f, 15, 0, 0xbe00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x6, 3, 3, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x5, 15, 0, 0x8000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x6, 15, 0, 0x8000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0xa, 15, 0, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1e, 15, 0, 0x0002); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1f, 15, 0, 0xbe00); if (is_even) { - rtpcs_sds_write_bits(sds, 0x2f, 0xe, 10, 10, 0x0000); - rtpcs_sds_write_bits(sds, 0x2f, 0xf, 10, 10, 0x0000); - rtpcs_sds_write_bits(sds, 0x2f, 0xe, 14, 14, 0x0000); - rtpcs_sds_write_bits(sds, 0x2f, 0xf, 14, 14, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0xe, 10, 10, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0xf, 10, 10, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0xe, 14, 14, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0xf, 14, 14, 0x0000); } - rtpcs_sds_write_bits(sds, 0x2e, 0x10, 5, 5, 0x0000); - rtpcs_sds_write_bits(sds, 0x2f, 0x9, 8, 8, 0x0000); - rtpcs_sds_write_bits(sds, 0x2e, 0x3, 15, 12, 0x000f); - rtpcs_sds_write_bits(sds, 0x2e, 0x1f, 13, 12, 0x0003); - rtpcs_sds_write_bits(sds, 0x2e, 0x1f, 11, 9, 0x0007); - rtpcs_sds_write_bits(sds, 0x2f, 0x1, 15, 15, 0x0001); - rtpcs_sds_write_bits(sds, 0x2f, 0x1, 14, 14, 0x0001); - rtpcs_sds_write_bits(sds, 0x2f, 0x1, 13, 13, 0x0000); - rtpcs_sds_write_bits(sds, 0x2f, 0x1, 12, 12, 0x0000); - rtpcs_sds_write_bits(sds, 0x2f, 0x1, 11, 9, 0x0002); - rtpcs_sds_write_bits(sds, 0x2f, 0x1, 8, 6, 0x0002); - rtpcs_sds_write_bits(sds, 0x2f, 0x1, 5, 3, 0x0000); - rtpcs_sds_write_bits(sds, 0x2f, 0x1, 2, 0, 0x0000); - rtpcs_sds_write_bits(sds, 0x2f, 0xc, 9, 9, 0x0001); - rtpcs_sds_write_bits(sds, 0x2f, 0xd, 9, 9, 0x0001); - rtpcs_sds_write_bits(sds, 0x2f, 0x8, 5, 5, 0x0001); - rtpcs_sds_write_bits(sds, 0x2f, 0x8, 6, 6, 0x0000); - rtpcs_sds_write_bits(sds, 0x2e, 0x1c, 15, 15, 0x0000); - rtpcs_sds_write_bits(sds, 0x2e, 0x10, 15, 12, 0x0000); - rtpcs_sds_write_bits(sds, 0x2e, 0x13, 4, 4, 0x0000); - rtpcs_sds_write_bits(sds, 0x2e, 0x13, 9, 9, 0x0000); - rtpcs_sds_write_bits(sds, 0x2e, 0x13, 3, 0, 0x0008); - rtpcs_sds_write_bits(sds, 0x2e, 0x13, 8, 5, 0x0008); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x10, 5, 5, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x9, 8, 8, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x3, 15, 12, 0x000f); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1f, 13, 12, 0x0003); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1f, 11, 9, 0x0007); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x1, 15, 15, 0x0001); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x1, 14, 14, 0x0001); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x1, 13, 13, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x1, 12, 12, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x1, 11, 9, 0x0002); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x1, 8, 6, 0x0002); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x1, 5, 3, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x1, 2, 0, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0xc, 9, 9, 0x0001); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0xd, 9, 9, 0x0001); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x8, 5, 5, 0x0001); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x8, 6, 6, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1c, 15, 15, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x10, 15, 12, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x13, 4, 4, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x13, 9, 9, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x13, 3, 0, 0x0008); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x13, 8, 5, 0x0008); return 0; } @@ -1152,28 +1206,16 @@ static int rtpcs_839x_sds_deactivate(struct rtpcs_serdes *sds) static int rtpcs_839x_sds_activate(struct rtpcs_serdes *sds) { + rtpcs_839x_sds_reset(sds); return 0; } -static int rtpcs_839x_setup_serdes(struct rtpcs_serdes *sds, - enum rtpcs_sds_mode hw_mode) +/* + * Keep this as a no-op stub until RTL839x is extended to do proper configuration + * here. E.g., the still missing SGMII, 100BASEX and 1000BASEX setup should go here. + */ +static int rtpcs_839x_sds_config_hw_mode(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode) { - int ret; - - /* Don't touch 5G SerDes, they are already properly configured - * at startup for QSGMII. Thus, connected PHYs should work out - * of the box. - */ - if (sds->type == RTPCS_SDS_TYPE_5G) - return 0; - - ret = rtpcs_sds_set_mac_mode(sds, hw_mode); - if (ret < 0) - return ret; - - sds->hw_mode = hw_mode; - - rtpcs_839x_sds_reset(sds); return 0; } @@ -1206,7 +1248,7 @@ static int rtpcs_93xx_sds_set_autoneg(struct rtpcs_serdes *sds, unsigned int neg case RTPCS_SDS_MODE_XSGMII: /* XSG N-way state */ en_val = neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED ? 0x0 : 0x1; - return rtpcs_sds_xsg_write_bits(sds, 0x0, 0x2, 9, 8, en_val); + return rtpcs_sds_xsg_write_bits(sds, PAGE_SDS, 0x2, 9, 8, en_val); case RTPCS_SDS_MODE_USXGMII_10GSXGMII ... RTPCS_SDS_MODE_USXGMII_2_5GSXGMII: /* @@ -1215,7 +1257,7 @@ static int rtpcs_93xx_sds_set_autoneg(struct rtpcs_serdes *sds, unsigned int neg * We do not support forced USXGMII link yet, always activate USXGMII-AN * for now. */ - return rtpcs_sds_write_bits(sds, 0x7, 0x11, 3, 0, 0xf); + return rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_1, 0x11, 3, 0, 0xf); default: return rtpcs_generic_sds_set_autoneg(sds, neg_mode, advertising); @@ -1226,39 +1268,39 @@ static void rtpcs_93xx_sds_usxgmii_config(struct rtpcs_serdes *sds, u32 opcode, u32 all_am_markers, u32 an_table, u32 sync_bit) { /* this comes from USXGMII patch sequences of the SDK */ - rtpcs_sds_write(sds, 0x06, 0x00, 0x0000); - rtpcs_sds_write(sds, 0x06, 0x0D, 0x0F00); - rtpcs_sds_write(sds, 0x06, 0x1D, 0x0600); + rtpcs_sds_write(sds, PAGE_TGR_PRO_0, 0x00, 0x0000); + rtpcs_sds_write(sds, PAGE_TGR_PRO_0, 0x0D, 0x0F00); + rtpcs_sds_write(sds, PAGE_TGR_PRO_0, 0x1D, 0x0600); - rtpcs_sds_write(sds, 0x07, 0x06, 0x1401); /* CFG_QHSG_TXCFG_MAC_CH0 */ - rtpcs_sds_write(sds, 0x07, 0x08, 0x1401); /* CFG_QHSG_TXCFG_MAC_CH1 */ - rtpcs_sds_write(sds, 0x07, 0x0a, 0x1401); /* CFG_QHSG_TXCFG_MAC_CH2 */ - rtpcs_sds_write(sds, 0x07, 0x0c, 0x1401); /* CFG_QHSG_TXCFG_MAC_CH3 */ + rtpcs_sds_write(sds, PAGE_TGR_PRO_1, 0x06, 0x1401); /* CFG_QHSG_TXCFG_MAC_CH0 */ + rtpcs_sds_write(sds, PAGE_TGR_PRO_1, 0x08, 0x1401); /* CFG_QHSG_TXCFG_MAC_CH1 */ + rtpcs_sds_write(sds, PAGE_TGR_PRO_1, 0x0a, 0x1401); /* CFG_QHSG_TXCFG_MAC_CH2 */ + rtpcs_sds_write(sds, PAGE_TGR_PRO_1, 0x0c, 0x1401); /* CFG_QHSG_TXCFG_MAC_CH3 */ /* * Controls the USXGMII AN mode. Two states are currently known: * - 0x03: generic/standard-compliant mode * - 0xaa: Realtek-proprietary mode (e.g. RTL8224) */ - rtpcs_sds_write_bits(sds, 0x7, 0x10, 7, 0, opcode); /* CFG_QHSG_AN_OPC */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_1, 0x10, 7, 0, opcode); /* CFG_QHSG_AN_OPC */ - rtpcs_sds_write_bits(sds, 0x6, 0x12, 15, 0, am_period); - rtpcs_sds_write_bits(sds, 0x6, 0x13, 7, 0, all_am_markers); /* CFG_AM0_M0 */ - rtpcs_sds_write_bits(sds, 0x6, 0x13, 15, 8, all_am_markers); /* CFG_AM0_M1 */ - rtpcs_sds_write_bits(sds, 0x6, 0x14, 7, 0, all_am_markers); /* CFG_AM0_M2 */ - rtpcs_sds_write_bits(sds, 0x6, 0x14, 15, 8, all_am_markers); /* CFG_AM1_M0 */ - rtpcs_sds_write_bits(sds, 0x6, 0x15, 7, 0, all_am_markers); /* CFG_AM1_M1 */ - rtpcs_sds_write_bits(sds, 0x6, 0x15, 15, 8, all_am_markers); /* CFG_AM1_M2 */ - rtpcs_sds_write_bits(sds, 0x6, 0x16, 7, 0, all_am_markers); /* CFG_AM2_M0 */ - rtpcs_sds_write_bits(sds, 0x6, 0x16, 15, 8, all_am_markers); /* CFG_AM2_M1 */ - rtpcs_sds_write_bits(sds, 0x6, 0x17, 7, 0, all_am_markers); /* CFG_AM2_M2 */ - rtpcs_sds_write_bits(sds, 0x6, 0x17, 15, 8, all_am_markers); /* CFG_AM3_M0 */ - rtpcs_sds_write_bits(sds, 0x6, 0x18, 7, 0, all_am_markers); /* CFG_AM3_M1 */ - rtpcs_sds_write_bits(sds, 0x6, 0x18, 15, 8, all_am_markers); /* CFG_AM3_M2 */ - rtpcs_sds_write_bits(sds, 0x6, 0xe, 10, 10, an_table); - rtpcs_sds_write_bits(sds, 0x6, 0x1d, 11, 10, sync_bit); + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x12, 15, 0, am_period); + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x13, 7, 0, all_am_markers); /* CFG_AM0_M0 */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x13, 15, 8, all_am_markers); /* CFG_AM0_M1 */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x14, 7, 0, all_am_markers); /* CFG_AM0_M2 */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x14, 15, 8, all_am_markers); /* CFG_AM1_M0 */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x15, 7, 0, all_am_markers); /* CFG_AM1_M1 */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x15, 15, 8, all_am_markers); /* CFG_AM1_M2 */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x16, 7, 0, all_am_markers); /* CFG_AM2_M0 */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x16, 15, 8, all_am_markers); /* CFG_AM2_M1 */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x17, 7, 0, all_am_markers); /* CFG_AM2_M2 */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x17, 15, 8, all_am_markers); /* CFG_AM3_M0 */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x18, 7, 0, all_am_markers); /* CFG_AM3_M1 */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x18, 15, 8, all_am_markers); /* CFG_AM3_M2 */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0xe, 10, 10, an_table); + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x1d, 11, 10, sync_bit); - rtpcs_sds_write_bits(sds, 0x06, 0x03, 15, 15, 0x1); /* FP_TGR3_CFG_EEE_EN */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x03, 15, 15, 0x1); /* FP_TGR3_CFG_EEE_EN */ } static int rtpcs_93xx_init(struct rtpcs_ctrl *ctrl) @@ -1297,7 +1339,7 @@ static int rtpcs_93xx_sds_get_pll_config(struct rtpcs_serdes *sds, enum rtpcs_sd */ sbit = pll == RTPCS_SDS_PLL_TYPE_LC ? 8 : 12; - speed_val = rtpcs_sds_read_bits(even_sds, 0x20, 0x12, sbit + 3, sbit); + speed_val = rtpcs_sds_read_bits(even_sds, PAGE_ANA_MISC, 0x12, sbit + 3, sbit); if (speed_val < 0) return speed_val; @@ -1327,12 +1369,13 @@ static int rtpcs_93xx_sds_set_pll_config(struct rtpcs_serdes *sds, enum rtpcs_sd * LC PLL. As it is unclear if disabling PLLs has any positive or negative effect, * always activate both. */ - ret = rtpcs_sds_write_bits(even_sds, 0x20, 0x12, 3, 0, 0xf); + ret = rtpcs_sds_write_bits(even_sds, PAGE_ANA_MISC, 0x12, 3, 0, 0xf); if (ret < 0) return ret; /* bit 0 is force-bit, bits [3:1] are speed selector */ - ret = rtpcs_sds_write_bits(even_sds, 0x20, 0x12, sbit + 3, sbit, (speed << 1) | BIT(0)); + ret = rtpcs_sds_write_bits(even_sds, PAGE_ANA_MISC, 0x12, sbit + 3, sbit, + (speed << 1) | BIT(0)); if (ret < 0) return ret; @@ -1485,7 +1528,7 @@ static int rtpcs_93xx_sds_set_mac_driven_mode(struct rtpcs_serdes *sds, { int ret; - ret = rtpcs_sds_write_bits(sds, 0x1f, 0x09, 6, 6, 0); + ret = rtpcs_sds_write_bits(sds, PAGE_WDIG, 0x09, 6, 6, 0); if (ret) return ret; @@ -1506,7 +1549,7 @@ static int rtpcs_93xx_sds_get_ip_mode(struct rtpcs_serdes *sds) const s16 *vals = sds->ctrl->cfg->sds_hw_mode_vals; int raw; - raw = rtpcs_sds_read_bits(sds, 0x1f, 0x09, 11, 7); + raw = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x09, 11, 7); if (raw < 0) return raw; @@ -1529,7 +1572,7 @@ static int rtpcs_93xx_sds_set_ip_mode(struct rtpcs_serdes *sds, enum rtpcs_sds_m return -EOPNOTSUPP; /* BIT(0) is force mode enable bit */ - return rtpcs_sds_write_bits(sds, 0x1f, 0x09, 11, 6, raw << 1 | BIT(0)); + return rtpcs_sds_write_bits(sds, PAGE_WDIG, 0x09, 11, 6, raw << 1 | BIT(0)); } static void rtpcs_93xx_sds_fill_caps(struct rtpcs_serdes *sds) @@ -1601,16 +1644,16 @@ static int rtpcs_930x_sds_get_phys_sds_id(int sds_id, int page) return sds_id; } -static int rtpcs_930x_sds_op_read(struct rtpcs_serdes *sds, int page, int regnum, int bithigh, - int bitlow) +static int rtpcs_930x_sds_op_read(struct rtpcs_serdes *sds, enum rtpcs_page page, int regnum, + int bithigh, int bitlow) { int sds_id = rtpcs_930x_sds_get_phys_sds_id(sds->id, page); return __rtpcs_sds_read_raw(sds->ctrl, sds_id, page, regnum, bithigh, bitlow); } -static int rtpcs_930x_sds_op_write(struct rtpcs_serdes *sds, int page, int regnum, int bithigh, - int bitlow, u16 value) +static int rtpcs_930x_sds_op_write(struct rtpcs_serdes *sds, enum rtpcs_page page, int regnum, + int bithigh, int bitlow, u16 value) { int sds_id = rtpcs_930x_sds_get_phys_sds_id(sds->id, page); @@ -1623,7 +1666,7 @@ static int rtpcs_930x_sds_op_write(struct rtpcs_serdes *sds, int page, int regnu * This implements 'dal_longan_sds_xsg_field_write' and a combination of * '_rtl9300_serdes_index_to_physical' and '_rtl9300_serdes_reg_write' from the SDK. */ -static int rtpcs_930x_sds_op_xsg_write(struct rtpcs_serdes *sds, int page, int regnum, +static int rtpcs_930x_sds_op_xsg_write(struct rtpcs_serdes *sds, enum rtpcs_page page, int regnum, int bithigh, int bitlow, u16 value) { int phys_sds_id, ret; @@ -1653,10 +1696,10 @@ static int rtpcs_930x_sds_op_xsg_write(struct rtpcs_serdes *sds, int page, int r static void rtpcs_930x_sds_rx_reset(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode) { - int page = 0x2e; /* 10GR and USXGMII */ + enum rtpcs_page page = PAGE_ANA_10G; /* 10GR and USXGMII */ if (hw_mode == RTPCS_SDS_MODE_1000BASEX) - page = 0x24; + page = PAGE_ANA_1G2; rtpcs_sds_write_bits(sds, page, 0x15, 4, 4, 0x1); mdelay(5); @@ -1669,7 +1712,7 @@ static int rtpcs_930x_sds_get_pll_select(struct rtpcs_serdes *sds, enum rtpcs_sd int pbit = (sds == even_sds) ? 4 : 6; int pll_sel; - pll_sel = rtpcs_sds_read_bits(even_sds, 0x20, 0x12, pbit + 1, pbit); + pll_sel = rtpcs_sds_read_bits(even_sds, PAGE_ANA_MISC, 0x12, pbit + 1, pbit); if (pll_sel < 0) return pll_sel; @@ -1684,10 +1727,11 @@ static int rtpcs_930x_sds_set_pll_select(struct rtpcs_serdes *sds, enum rtpcs_sd struct rtpcs_serdes *even_sds = rtpcs_sds_get_even(sds); int pbit = (sds == even_sds) ? 4 : 6; - /* Selecting the PLL a SerDes is done in the even lane register */ + /* Selecting the PLL a SerDes uses is done in the even lane register */ /* bit 0 is force-bit, bit 1 is PLL selector */ - return rtpcs_sds_write_bits(even_sds, 0x20, 0x12, pbit + 1, pbit, (pll << 1) | BIT(0)); + return rtpcs_sds_write_bits(even_sds, PAGE_ANA_MISC, 0x12, pbit + 1, pbit, + (pll << 1) | BIT(0)); } static int rtpcs_930x_sds_reset_cmu(struct rtpcs_serdes *sds, enum rtpcs_sds_pll_type pll) @@ -1705,7 +1749,7 @@ static int rtpcs_930x_sds_reset_cmu(struct rtpcs_serdes *sds, enum rtpcs_sds_pll bit = pll == RTPCS_SDS_PLL_TYPE_LC ? 2 : 0; for (i = 0; i < ARRAY_SIZE(reset_sequence); i++) { - ret = rtpcs_sds_write_bits(even_sds, 0x21, 0x0b, bit + 1, bit, + ret = rtpcs_sds_write_bits(even_sds, PAGE_ANA_COM, 0x0b, bit + 1, bit, reset_sequence[i]); if (ret < 0) return ret; @@ -1727,8 +1771,8 @@ static int rtpcs_930x_sds_wait_clock_ready(struct rtpcs_serdes *sds) for (i = 0; i < 20; i++) { usleep_range(10000, 15000); - rtpcs_sds_write(even_sds, 0x1f, 0x02, 53); - ready = rtpcs_sds_read_bits(even_sds, 0x1f, 0x14, bit, bit); + rtpcs_sds_write(even_sds, PAGE_WDIG, 0x02, 53); + ready = rtpcs_sds_read_bits(even_sds, PAGE_WDIG, 0x14, bit, bit); ready_cnt = ready ? ready_cnt + 1 : 0; if (ready_cnt >= 3) @@ -1743,8 +1787,8 @@ static void rtpcs_930x_sds_set_power(struct rtpcs_serdes *sds, bool on) int power_down = on ? 0x0 : 0x3; int rx_enable = on ? 0x3 : 0x1; - rtpcs_sds_write_bits(sds, 0x20, 0x00, 7, 6, power_down); - rtpcs_sds_write_bits(sds, 0x20, 0x00, 5, 4, rx_enable); + rtpcs_sds_write_bits(sds, PAGE_ANA_MISC, 0x00, 7, 6, power_down); + rtpcs_sds_write_bits(sds, PAGE_ANA_MISC, 0x00, 5, 4, rx_enable); } static int rtpcs_930x_sds_reconfigure_to_pll(struct rtpcs_serdes *sds, enum rtpcs_sds_pll_type pll) @@ -1786,9 +1830,9 @@ static int rtpcs_930x_sds_reconfigure_to_pll(struct rtpcs_serdes *sds, enum rtpc static void rtpcs_930x_sds_reset_state_machine(struct rtpcs_serdes *sds) { - rtpcs_sds_write_bits(sds, 0x06, 0x02, 12, 12, 0x01); /* SM_RESET bit */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x02, 12, 12, 0x01); /* SM_RESET bit */ usleep_range(10000, 20000); - rtpcs_sds_write_bits(sds, 0x06, 0x02, 12, 12, 0x00); + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x02, 12, 12, 0x00); usleep_range(10000, 20000); } @@ -1804,18 +1848,20 @@ static int rtpcs_930x_sds_init_state_machine(struct rtpcs_serdes *sds, * works properly for 10G. To verify operation readyness run a connection check via * loopback. */ - loopback = rtpcs_sds_read_bits(sds, 0x06, 0x01, 2, 2); /* CFG_AFE_LPK bit */ - rtpcs_sds_write_bits(sds, 0x06, 0x01, 2, 2, 0x01); + loopback = rtpcs_sds_read_bits(sds, PAGE_TGR_PRO_0, 0x01, 2, 2); /* CFG_AFE_LPK bit */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x01, 2, 2, 0x01); while (cnt-- && ret) { rtpcs_930x_sds_reset_state_machine(sds); - link = rtpcs_sds_read_bits(sds, 0x05, 0x00, 12, 12); /* 10G link state (latched) */ - link = rtpcs_sds_read_bits(sds, 0x05, 0x00, 12, 12); + + /* 10G link state (latched) */ + link = rtpcs_sds_read_bits(sds, PAGE_TGR_STD_1, 0x00, 12, 12); + link = rtpcs_sds_read_bits(sds, PAGE_TGR_STD_1, 0x00, 12, 12); if (link) ret = 0; } - rtpcs_sds_write_bits(sds, 0x06, 0x01, 2, 2, loopback); + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x01, 2, 2, loopback); rtpcs_930x_sds_reset_state_machine(sds); return ret; @@ -1899,17 +1945,17 @@ static int rtpcs_930x_sds_deactivate(struct rtpcs_serdes *sds) return ret; /* Disable fiber RX. */ - ret = rtpcs_sds_write_bits(sds, 0x20, 2, 12, 12, 1); + ret = rtpcs_sds_write_bits(sds, PAGE_ANA_MISC, 2, 12, 12, 1); if (ret) return ret; /* Power down the 1G PHY block. */ - ret = rtpcs_sds_write_bits(sds, 0x02, MII_BMCR, 11, 11, 1); /* BMCR_PDOWN */ + ret = rtpcs_sds_write_bits(sds, PAGE_FIB, MII_BMCR, 11, 11, 1); /* BMCR_PDOWN */ if (ret) return ret; /* Power down the 10G PHY block. */ - return rtpcs_sds_write_bits(sds, 0x04, MII_BMCR, 11, 11, 1); /* BMCR_PDOWN */ + return rtpcs_sds_write_bits(sds, PAGE_TGR_STD_0, MII_BMCR, 11, 11, 1); /* BMCR_PDOWN */ } static int rtpcs_930x_sds_activate(struct rtpcs_serdes *sds) @@ -1921,30 +1967,30 @@ static int rtpcs_930x_sds_activate(struct rtpcs_serdes *sds) rtpcs_930x_sds_rx_reset(sds, sds->hw_mode); /* Enable fiber RX. */ - ret = rtpcs_sds_write_bits(sds, 0x20, 2, 12, 12, 0); + ret = rtpcs_sds_write_bits(sds, PAGE_ANA_MISC, 2, 12, 12, 0); if (ret) return ret; /* Power up the 1G PHY block. */ - ret = rtpcs_sds_write_bits(sds, 0x02, MII_BMCR, 11, 11, 0); /* BMCR_PDOWN */ + ret = rtpcs_sds_write_bits(sds, PAGE_FIB, MII_BMCR, 11, 11, 0); /* BMCR_PDOWN */ if (ret) return ret; /* Power up the 10G PHY block. */ - return rtpcs_sds_write_bits(sds, 0x04, MII_BMCR, 11, 11, 0); /* BMCR_PDOWN */ + return rtpcs_sds_write_bits(sds, PAGE_TGR_STD_0, MII_BMCR, 11, 11, 0); /* BMCR_PDOWN */ } static void rtpcs_930x_sds_tx_config(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode) { /* parameters: rtl9303_80G_txParam_s2 */ + enum rtpcs_page page; int impedance = 0x8; int pre_amp = 0x2; int main_amp = 0x9; int post_amp = 0x2; int pre_en = 0x1; int post_en = 0x1; - int page; switch (hw_mode) { case RTPCS_SDS_MODE_1000BASEX: @@ -1952,13 +1998,13 @@ static void rtpcs_930x_sds_tx_config(struct rtpcs_serdes *sds, pre_amp = 0x1; main_amp = 0x9; post_amp = 0x1; - page = 0x25; + page = PAGE_ANA_1G2_EXT; break; case RTPCS_SDS_MODE_2500BASEX: pre_amp = 0; post_amp = 0x8; pre_en = 0; - page = 0x29; + page = PAGE_ANA_3G1_EXT; break; case RTPCS_SDS_MODE_10GBASER: case RTPCS_SDS_MODE_USXGMII_10GSXGMII: @@ -1969,7 +2015,7 @@ static void rtpcs_930x_sds_tx_config(struct rtpcs_serdes *sds, main_amp = 0x10; post_amp = 0; post_en = 0; - page = 0x2f; + page = PAGE_ANA_10G_EXT; break; case RTPCS_SDS_MODE_QSGMII: return; @@ -1988,67 +2034,51 @@ static void rtpcs_930x_sds_tx_config(struct rtpcs_serdes *sds, __always_unused static void rtpcs_930x_sds_rxcal_dcvs_manual(struct rtpcs_serdes *sds, - u32 dcvs_id, bool manual, u32 dvcs_list[]) + u32 dcvs_id, bool manual, u32 dcvs_list[]) { - if (manual) { - switch (dcvs_id) { - case 0: - rtpcs_sds_write_bits(sds, 0x2e, 0x1e, 14, 14, 0x1); - rtpcs_sds_write_bits(sds, 0x2f, 0x03, 5, 5, dvcs_list[0]); - rtpcs_sds_write_bits(sds, 0x2f, 0x03, 4, 0, dvcs_list[1]); - break; - case 1: - rtpcs_sds_write_bits(sds, 0x2e, 0x1e, 13, 13, 0x1); - rtpcs_sds_write_bits(sds, 0x2e, 0x1d, 15, 15, dvcs_list[0]); - rtpcs_sds_write_bits(sds, 0x2e, 0x1d, 14, 11, dvcs_list[1]); - break; - case 2: - rtpcs_sds_write_bits(sds, 0x2e, 0x1e, 12, 12, 0x1); - rtpcs_sds_write_bits(sds, 0x2e, 0x1d, 10, 10, dvcs_list[0]); - rtpcs_sds_write_bits(sds, 0x2e, 0x1d, 9, 6, dvcs_list[1]); - break; - case 3: - rtpcs_sds_write_bits(sds, 0x2e, 0x1e, 11, 11, 0x1); - rtpcs_sds_write_bits(sds, 0x2e, 0x1d, 5, 5, dvcs_list[0]); - rtpcs_sds_write_bits(sds, 0x2e, 0x1d, 4, 1, dvcs_list[1]); - break; - case 4: - rtpcs_sds_write_bits(sds, 0x2e, 0x01, 15, 15, 0x1); - rtpcs_sds_write_bits(sds, 0x2e, 0x11, 10, 10, dvcs_list[0]); - rtpcs_sds_write_bits(sds, 0x2e, 0x11, 9, 6, dvcs_list[1]); - break; - case 5: - rtpcs_sds_write_bits(sds, 0x2e, 0x02, 11, 11, 0x1); - rtpcs_sds_write_bits(sds, 0x2e, 0x11, 4, 4, dvcs_list[0]); - rtpcs_sds_write_bits(sds, 0x2e, 0x11, 3, 0, dvcs_list[1]); - break; - default: - break; - } - } else { - switch (dcvs_id) { - case 0: - rtpcs_sds_write_bits(sds, 0x2e, 0x1e, 14, 14, 0x0); - break; - case 1: - rtpcs_sds_write_bits(sds, 0x2e, 0x1e, 13, 13, 0x0); - break; - case 2: - rtpcs_sds_write_bits(sds, 0x2e, 0x1e, 12, 12, 0x0); - break; - case 3: - rtpcs_sds_write_bits(sds, 0x2e, 0x1e, 11, 11, 0x0); - break; - case 4: - rtpcs_sds_write_bits(sds, 0x2e, 0x01, 15, 15, 0x0); - break; - case 5: - rtpcs_sds_write_bits(sds, 0x2e, 0x02, 11, 11, 0x0); - break; - default: - break; - } + u8 reg[6] = { 0x1e, 0x1e, 0x1e, 0x1e, 0x01, 0x02 }; + u8 bit[6] = { 14, 13, 12, 11, 15, 11 }; + + if (dcvs_id > 5) + return; + + /* set DCVS auto/manual */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, reg[dcvs_id], bit[dcvs_id], bit[dcvs_id], + manual ? 0x1 : 0x0); + + if (!manual) { + /* give auto mode some time */ mdelay(1); + return; + } + + switch (dcvs_id) { + case 0: + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x03, 5, 5, dcvs_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x03, 4, 0, dcvs_list[1]); + break; + case 1: + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 15, 15, dcvs_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 14, 11, dcvs_list[1]); + break; + case 2: + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 10, 10, dcvs_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 9, 6, dcvs_list[1]); + break; + case 3: + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 5, 5, dcvs_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 4, 1, dcvs_list[1]); + break; + case 4: + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x11, 10, 10, dcvs_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x11, 9, 6, dcvs_list[1]); + break; + case 5: + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x11, 4, 4, dcvs_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x11, 3, 0, dcvs_list[1]); + break; + default: + break; } } @@ -2056,81 +2086,33 @@ __always_unused static void rtpcs_930x_sds_rxcal_dcvs_get(struct rtpcs_serdes *sds, u32 dcvs_id, u32 dcvs_list[]) { - struct rtpcs_serdes *even_sds = rtpcs_sds_get_even(sds); + u8 manual_reg[6] = { 0x1e, 0x1e, 0x1e, 0x1e, 0x01, 0x02 }; + u8 coeff_sel[6] = { 0x22, 0x23, 0x24, 0x25, 0x2c, 0x2d }; + u8 manual_bit[6] = { 14, 13, 12, 11, 15, 11 }; u32 dcvs_sign_out = 0, dcvs_coef_bin = 0; + struct rtpcs_serdes *even_sds; bool dcvs_manual; + if (dcvs_id > 5) + return; + + even_sds = rtpcs_sds_get_even(sds); if (sds == even_sds) - rtpcs_sds_write(sds, 0x1f, 0x2, 0x2f); + rtpcs_sds_write(sds, PAGE_WDIG, 0x2, 0x2f); else - rtpcs_sds_write(even_sds, 0x1f, 0x2, 0x31); + rtpcs_sds_write(even_sds, PAGE_WDIG, 0x2, 0x31); - rtpcs_sds_write_bits(sds, 0x2e, 0x15, 9, 9, 0x1); /* REG0_RX_EN_TEST */ - rtpcs_sds_write_bits(sds, 0x21, 0x06, 11, 6, 0x20); /* REG0_RX_DEBUG_SEL */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x15, 9, 9, 0x1); /* REG0_RX_EN_TEST */ + rtpcs_sds_write_bits(sds, PAGE_ANA_COM, 0x06, 11, 6, 0x20); /* REG0_RX_DEBUG_SEL */ - switch (dcvs_id) { - case 0: - rtpcs_sds_write_bits(sds, 0x2f, 0x0c, 5, 0, 0x22); - mdelay(1); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0c, 5, 0, coeff_sel[dcvs_id]); + mdelay(1); - /* ##DCVS0 Read Out */ - dcvs_sign_out = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 4, 4); - dcvs_coef_bin = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 3, 0); - dcvs_manual = !!rtpcs_sds_read_bits(sds, 0x2e, 0x1e, 14, 14); - break; - - case 1: - rtpcs_sds_write_bits(sds, 0x2f, 0x0c, 5, 0, 0x23); - mdelay(1); - - /* ##DCVS0 Read Out */ - dcvs_coef_bin = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 4, 4); - dcvs_coef_bin = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 3, 0); - dcvs_manual = !!rtpcs_sds_read_bits(sds, 0x2e, 0x1e, 13, 13); - break; - - case 2: - rtpcs_sds_write_bits(sds, 0x2f, 0x0c, 5, 0, 0x24); - mdelay(1); - - /* ##DCVS0 Read Out */ - dcvs_sign_out = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 4, 4); - dcvs_coef_bin = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 3, 0); - dcvs_manual = !!rtpcs_sds_read_bits(sds, 0x2e, 0x1e, 12, 12); - break; - case 3: - rtpcs_sds_write_bits(sds, 0x2f, 0x0c, 5, 0, 0x25); - mdelay(1); - - /* ##DCVS0 Read Out */ - dcvs_sign_out = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 4, 4); - dcvs_coef_bin = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 3, 0); - dcvs_manual = rtpcs_sds_read_bits(sds, 0x2e, 0x1e, 11, 11); - break; - - case 4: - rtpcs_sds_write_bits(sds, 0x2f, 0x0c, 5, 0, 0x2c); - mdelay(1); - - /* ##DCVS0 Read Out */ - dcvs_sign_out = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 4, 4); - dcvs_coef_bin = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 3, 0); - dcvs_manual = !!rtpcs_sds_read_bits(sds, 0x2e, 0x01, 15, 15); - break; - - case 5: - rtpcs_sds_write_bits(sds, 0x2f, 0x0c, 5, 0, 0x2d); - mdelay(1); - - /* ##DCVS0 Read Out */ - dcvs_sign_out = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 4, 4); - dcvs_coef_bin = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 3, 0); - dcvs_manual = rtpcs_sds_read_bits(sds, 0x2e, 0x02, 11, 11); - break; - - default: - break; - } + /* ## DCVSX Read Out */ + dcvs_sign_out = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 4, 4); + dcvs_coef_bin = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 3, 0); + dcvs_manual = !!rtpcs_sds_read_bits(sds, PAGE_ANA_10G, manual_reg[dcvs_id], + manual_bit[dcvs_id], manual_bit[dcvs_id]); pr_info("%s: DCVS %u sign = %s, manual = %u, even coefficient = %u\n", __func__, dcvs_id, dcvs_sign_out ? "-" : "+", dcvs_manual, dcvs_coef_bin); @@ -2143,10 +2125,10 @@ static void rtpcs_930x_sds_rxcal_leq_manual(struct rtpcs_serdes *sds, bool manual, u32 leq_gray) { if (manual) { - rtpcs_sds_write_bits(sds, 0x2e, 0x18, 15, 15, 0x1); - rtpcs_sds_write_bits(sds, 0x2e, 0x16, 14, 10, leq_gray); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x18, 15, 15, 0x1); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x16, 14, 10, leq_gray); } else { - rtpcs_sds_write_bits(sds, 0x2e, 0x18, 15, 15, 0x0); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x18, 15, 15, 0x0); mdelay(100); } } @@ -2155,38 +2137,22 @@ static void rtpcs_930x_sds_rxcal_leq_offset_manual(struct rtpcs_serdes *sds, bool manual, u32 offset) { if (manual) { - rtpcs_sds_write_bits(sds, 0x2e, 0x17, 6, 2, offset); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x17, 6, 2, offset); } else { - rtpcs_sds_write_bits(sds, 0x2e, 0x17, 6, 2, offset); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x17, 6, 2, offset); mdelay(1); } } -#define GRAY_BITS 5 static u32 rtpcs_930x_sds_rxcal_gray_to_binary(u32 gray_code) { - int i, j, m; - u32 g[GRAY_BITS]; - u32 c[GRAY_BITS]; - u32 leq_binary = 0; + u32 binary = gray_code; - for (i = 0; i < GRAY_BITS; i++) - g[i] = (gray_code & BIT(i)) >> i; + gray_code &= 0x1f; /* only lower 5 bits */ + while (gray_code >>= 1) + binary ^= gray_code; - m = GRAY_BITS - 1; - - c[m] = g[m]; - - for (i = 0; i < m; i++) { - c[i] = g[i]; - for (j = i + 1; j < GRAY_BITS; j++) - c[i] = c[i] ^ g[j]; - } - - for (i = 0; i < GRAY_BITS; i++) - leq_binary += c[i] << i; - - return leq_binary; + return binary; } static u32 rtpcs_930x_sds_rxcal_leq_read(struct rtpcs_serdes *sds) @@ -2195,14 +2161,14 @@ static u32 rtpcs_930x_sds_rxcal_leq_read(struct rtpcs_serdes *sds) u32 leq_gray, leq_bin; bool leq_manual; - rtpcs_sds_write(even_sds, 0x1f, 0x2, (sds == even_sds) ? 0x2f : 0x31); /* REG_DBGO_SEL */ - rtpcs_sds_write_bits(sds, 0x2e, 0x15, 9, 9, 0x1); /* REG0_RX_EN_TEST */ - rtpcs_sds_write_bits(sds, 0x21, 0x06, 11, 6, 0x10); /* REG0_RX_DEBUG_SEL */ + rtpcs_sds_write(even_sds, PAGE_WDIG, 0x2, (sds == even_sds) ? 0x2f : 0x31); /* REG_DBGO_SEL */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x15, 9, 9, 0x1); /* REG0_RX_EN_TEST */ + rtpcs_sds_write_bits(sds, PAGE_ANA_COM, 0x06, 11, 6, 0x10); /* REG0_RX_DEBUG_SEL */ mdelay(1); /* ##LEQ Read Out */ - leq_gray = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 7, 3); - leq_manual = !!rtpcs_sds_read_bits(sds, 0x2e, 0x18, 15, 15); + leq_gray = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 7, 3); + leq_manual = !!rtpcs_sds_read_bits(sds, PAGE_ANA_10G, 0x18, 15, 15); leq_bin = rtpcs_930x_sds_rxcal_gray_to_binary(leq_gray); pr_info("LEQ gray: %u, LEQ bin: %u, LEQ manual: %u\n", leq_gray, leq_bin, leq_manual); @@ -2212,14 +2178,14 @@ static u32 rtpcs_930x_sds_rxcal_leq_read(struct rtpcs_serdes *sds) static void rtpcs_930x_sds_rxcal_vth_manual(struct rtpcs_serdes *sds, bool manual, u32 vth_list[]) { + /* REG0_LOAD_IN_INIT, [13:13] = VTH */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0f, 13, 13, manual ? 0x1 : 0x0); + if (manual) { - rtpcs_sds_write_bits(sds, 0x2e, 0x0f, 13, 13, 0x1); - rtpcs_sds_write_bits(sds, 0x2e, 0x13, 5, 3, vth_list[0]); - rtpcs_sds_write_bits(sds, 0x2e, 0x13, 2, 0, vth_list[1]); - } else { - rtpcs_sds_write_bits(sds, 0x2e, 0x0f, 13, 13, 0x0); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x13, 5, 3, vth_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x13, 2, 0, vth_list[1]); + } else mdelay(10); - } } static void rtpcs_930x_sds_rxcal_vth_get(struct rtpcs_serdes *sds, @@ -2228,17 +2194,17 @@ static void rtpcs_930x_sds_rxcal_vth_get(struct rtpcs_serdes *sds, struct rtpcs_serdes *even_sds = rtpcs_sds_get_even(sds); int vth_manual; - rtpcs_sds_write(even_sds, 0x1f, 0x2, (sds == even_sds) ? 0x2f : 0x31); /* REG_DBGO_SEL */ - rtpcs_sds_write_bits(sds, 0x2e, 0x15, 9, 9, 0x1); /* REG0_RX_EN_TEST */ - rtpcs_sds_write_bits(sds, 0x21, 0x06, 11, 6, 0x20); /* REG0_RX_DEBUG_SEL */ - rtpcs_sds_write_bits(sds, 0x2f, 0x0c, 5, 0, 0xc); /* REG0_COEF_SEL */ + rtpcs_sds_write(even_sds, PAGE_WDIG, 0x2, (sds == even_sds) ? 0x2f : 0x31); /* REG_DBGO_SEL */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x15, 9, 9, 0x1); /* REG0_RX_EN_TEST */ + rtpcs_sds_write_bits(sds, PAGE_ANA_COM, 0x06, 11, 6, 0x20); /* REG0_RX_DEBUG_SEL */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0c, 5, 0, 0xc); /* REG0_COEF_SEL */ mdelay(1); /* ##VthP & VthN Read Out */ - vth_list[0] = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 2, 0); /* v_thp set bin */ - vth_list[1] = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 5, 3); /* v_thn set bin */ - vth_manual = rtpcs_sds_read_bits(sds, 0x2e, 0x0f, 13, 13); + vth_list[0] = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 2, 0); /* v_thp set bin */ + vth_list[1] = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 5, 3); /* v_thn set bin */ + vth_manual = rtpcs_sds_read_bits(sds, PAGE_ANA_10G, 0x0f, 13, 13); pr_info("vthp_set_bin = %d, vthn_set_bin = %d, manual = %d\n", vth_list[0], vth_list[1], vth_manual); @@ -2247,48 +2213,50 @@ static void rtpcs_930x_sds_rxcal_vth_get(struct rtpcs_serdes *sds, static void rtpcs_930x_sds_rxcal_tap_manual(struct rtpcs_serdes *sds, int tap_id, bool manual, u32 tap_list[]) { - if (manual) { - switch (tap_id) { - case 0: - /* ##REG0_LOAD_IN_INIT[0]=1; REG0_TAP0_INIT[5:0]=Tap0_Value */ - rtpcs_sds_write_bits(sds, 0x2e, 0x0f, tap_id + 7, tap_id + 7, 0x1); - rtpcs_sds_write_bits(sds, 0x2f, 0x03, 5, 5, tap_list[0]); - rtpcs_sds_write_bits(sds, 0x2f, 0x03, 4, 0, tap_list[1]); - break; - case 1: - rtpcs_sds_write_bits(sds, 0x2e, 0x0f, tap_id + 7, tap_id + 7, 0x1); - rtpcs_sds_write_bits(sds, 0x21, 0x07, 6, 6, tap_list[0]); - rtpcs_sds_write_bits(sds, 0x2e, 0x09, 11, 6, tap_list[1]); - rtpcs_sds_write_bits(sds, 0x21, 0x07, 5, 5, tap_list[2]); - rtpcs_sds_write_bits(sds, 0x2f, 0x12, 5, 0, tap_list[3]); - break; - case 2: - rtpcs_sds_write_bits(sds, 0x2e, 0x0f, tap_id + 7, tap_id + 7, 0x1); - rtpcs_sds_write_bits(sds, 0x2e, 0x09, 5, 5, tap_list[0]); - rtpcs_sds_write_bits(sds, 0x2e, 0x09, 4, 0, tap_list[1]); - rtpcs_sds_write_bits(sds, 0x2e, 0x0a, 11, 11, tap_list[2]); - rtpcs_sds_write_bits(sds, 0x2e, 0x0a, 10, 6, tap_list[3]); - break; - case 3: - rtpcs_sds_write_bits(sds, 0x2e, 0x0f, tap_id + 7, tap_id + 7, 0x1); - rtpcs_sds_write_bits(sds, 0x2e, 0x0a, 5, 5, tap_list[0]); - rtpcs_sds_write_bits(sds, 0x2e, 0x0a, 4, 0, tap_list[1]); - rtpcs_sds_write_bits(sds, 0x2e, 0x06, 5, 5, tap_list[2]); - rtpcs_sds_write_bits(sds, 0x2e, 0x06, 4, 0, tap_list[3]); - break; - case 4: - rtpcs_sds_write_bits(sds, 0x2e, 0x0f, tap_id + 7, tap_id + 7, 0x1); - rtpcs_sds_write_bits(sds, 0x2f, 0x01, 5, 5, tap_list[0]); - rtpcs_sds_write_bits(sds, 0x2f, 0x01, 4, 0, tap_list[1]); - rtpcs_sds_write_bits(sds, 0x2e, 0x06, 11, 11, tap_list[2]); - rtpcs_sds_write_bits(sds, 0x2e, 0x06, 10, 6, tap_list[3]); - break; - default: - break; - } - } else { - rtpcs_sds_write_bits(sds, 0x2e, 0x0f, tap_id + 7, tap_id + 7, 0x0); + if (tap_id > 4) + return; + + /* ##REG0_LOAD_IN_INIT[0], [11:7] = TAP0-TAP4 */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0xf, tap_id + 7, tap_id + 7, + manual ? 0x1 : 0x0); + + if (!manual) { mdelay(10); + return; + } + + switch (tap_id) { + case 0: + /* ##REG0_TAP0_INIT[5:0]=Tap0_Value */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x03, 5, 5, tap_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x03, 4, 0, tap_list[1]); + break; + case 1: + rtpcs_sds_write_bits(sds, PAGE_ANA_COM, 0x07, 6, 6, tap_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x09, 11, 6, tap_list[1]); + rtpcs_sds_write_bits(sds, PAGE_ANA_COM, 0x07, 5, 5, tap_list[2]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x12, 5, 0, tap_list[3]); + break; + case 2: + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x09, 5, 5, tap_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x09, 4, 0, tap_list[1]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0a, 11, 11, tap_list[2]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0a, 10, 6, tap_list[3]); + break; + case 3: + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0a, 5, 5, tap_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0a, 4, 0, tap_list[1]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x06, 5, 5, tap_list[2]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x06, 4, 0, tap_list[3]); + break; + case 4: + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x01, 5, 5, tap_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x01, 4, 0, tap_list[1]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x06, 11, 11, tap_list[2]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x06, 10, 6, tap_list[3]); + break; + default: + break; } } @@ -2304,16 +2272,16 @@ static void rtpcs_930x_sds_rxcal_tap_get(struct rtpcs_serdes *sds, u32 tap_coef_bin_odd; bool tap_manual; - rtpcs_sds_write(even_sds, 0x1f, 0x2, (sds == even_sds) ? 0x2f : 0x31); /* REG_DBGO_SEL */ - rtpcs_sds_write_bits(sds, 0x2e, 0x15, 9, 9, 0x1); /* REG0_RX_EN_TEST */ - rtpcs_sds_write_bits(sds, 0x21, 0x06, 11, 6, 0x20); /* REG0_RX_DEBUG_SEL */ + rtpcs_sds_write(even_sds, PAGE_WDIG, 0x2, (sds == even_sds) ? 0x2f : 0x31); /* REG_DBGO_SEL */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x15, 9, 9, 0x1); /* REG0_RX_EN_TEST */ + rtpcs_sds_write_bits(sds, PAGE_ANA_COM, 0x06, 11, 6, 0x20); /* REG0_RX_DEBUG_SEL */ if (!tap_id) { - rtpcs_sds_write_bits(sds, 0x2f, 0x0c, 5, 0, 0); /* REG0_COEF_SEL */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0c, 5, 0, 0); /* REG0_COEF_SEL */ /* ##Tap1 Even Read Out */ mdelay(1); - tap0_sign_out = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 5, 5); - tap0_coef_bin = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 4, 0); + tap0_sign_out = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 5, 5); + tap0_coef_bin = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 4, 0); pr_info("tap0: coef_bin = %d, sign = %s\n", tap0_coef_bin, tap0_sign_out ? "-" : "+"); @@ -2321,19 +2289,19 @@ static void rtpcs_930x_sds_rxcal_tap_get(struct rtpcs_serdes *sds, tap_list[0] = tap0_sign_out; tap_list[1] = tap0_coef_bin; - tap_manual = !!rtpcs_sds_read_bits(sds, 0x2e, 0x0f, 7, 7); + tap_manual = !!rtpcs_sds_read_bits(sds, PAGE_ANA_10G, 0x0f, 7, 7); pr_info("tap0: manual = %u\n", tap_manual); } else { - rtpcs_sds_write_bits(sds, 0x2f, 0x0c, 5, 0, tap_id); /* REG0_COEF_SEL */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0c, 5, 0, tap_id); /* REG0_COEF_SEL */ mdelay(1); /* ##Tap1 Even Read Out */ - tap_sign_out_even = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 5, 5); - tap_coef_bin_even = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 4, 0); + tap_sign_out_even = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 5, 5); + tap_coef_bin_even = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 4, 0); - rtpcs_sds_write_bits(sds, 0x2f, 0x0c, 5, 0, (tap_id + 5)); /* REG0_COEF_SEL */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0c, 5, 0, (tap_id + 5)); /* REG0_COEF_SEL */ /* ##Tap1 Odd Read Out */ - tap_sign_out_odd = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 5, 5); - tap_coef_bin_odd = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 4, 0); + tap_sign_out_odd = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 5, 5); + tap_coef_bin_odd = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 4, 0); pr_info("tap%u: even coefficient = %u, sign = %s\n", tap_id, tap_coef_bin_even, tap_sign_out_even ? "-" : "+"); @@ -2346,7 +2314,8 @@ static void rtpcs_930x_sds_rxcal_tap_get(struct rtpcs_serdes *sds, tap_list[2] = tap_sign_out_odd; tap_list[3] = tap_coef_bin_odd; - tap_manual = rtpcs_sds_read_bits(sds, 0x2e, 0x0f, tap_id + 7, tap_id + 7); + tap_manual = rtpcs_sds_read_bits(sds, PAGE_ANA_10G, 0x0f, tap_id + 7, + tap_id + 7); pr_info("tap%u: manual = %d\n", tap_id, tap_manual); } } @@ -2359,128 +2328,121 @@ static void rtpcs_930x_sds_do_rx_calibration_1(struct rtpcs_serdes *sds, int vth_min = 0x1; /* 1.1.1 --- */ - rtpcs_sds_write(sds, 6, 0, 0); /* initial value */ + rtpcs_sds_write(sds, PAGE_TGR_PRO_0, 0, 0); /* initial value */ /* FGCAL */ - rtpcs_sds_write_bits(sds, 0x2e, 0x01, 14, 14, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x1c, 10, 5, 0x20); - rtpcs_sds_write_bits(sds, 0x2f, 0x02, 0, 0, 0x01); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x01, 14, 14, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1c, 10, 5, 0x20); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x02, 0, 0, 0x01); /* DCVS */ - rtpcs_sds_write_bits(sds, 0x2e, 0x1e, 14, 11, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x01, 15, 15, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x02, 11, 11, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x1c, 4, 0, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x1d, 15, 11, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x1d, 10, 6, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x1d, 5, 1, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x02, 10, 6, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x11, 4, 0, 0x00); - rtpcs_sds_write_bits(sds, 0x2f, 0x00, 3, 0, 0x0f); - rtpcs_sds_write_bits(sds, 0x2e, 0x04, 6, 6, 0x01); - rtpcs_sds_write_bits(sds, 0x2e, 0x04, 7, 7, 0x01); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1e, 14, 11, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x01, 15, 15, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x02, 11, 11, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1c, 4, 0, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 15, 11, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 10, 6, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 5, 1, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x02, 10, 6, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x11, 4, 0, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x00, 3, 0, 0x0f); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x04, 6, 6, 0x01); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x04, 7, 7, 0x01); /* LEQ (Long Term Equivalent signal level) */ - rtpcs_sds_write_bits(sds, 0x2e, 0x16, 14, 8, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x16, 14, 8, 0x00); /* DFE (Decision Fed Equalizer) */ - rtpcs_sds_write_bits(sds, 0x2f, 0x03, 5, 0, tap0_init_val); - rtpcs_sds_write_bits(sds, 0x2e, 0x09, 11, 6, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x09, 5, 0, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x0a, 5, 0, 0x00); - rtpcs_sds_write_bits(sds, 0x2f, 0x01, 5, 0, 0x00); - rtpcs_sds_write_bits(sds, 0x2f, 0x12, 5, 0, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x0a, 11, 6, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x06, 5, 0, 0x00); - rtpcs_sds_write_bits(sds, 0x2f, 0x01, 5, 0, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x03, 5, 0, tap0_init_val); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x09, 11, 6, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x09, 5, 0, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0a, 5, 0, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x01, 5, 0, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x12, 5, 0, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0a, 11, 6, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x06, 5, 0, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x01, 5, 0, 0x00); /* Vth */ - rtpcs_sds_write_bits(sds, 0x2e, 0x13, 5, 3, 0x07); - rtpcs_sds_write_bits(sds, 0x2e, 0x13, 2, 0, 0x07); - rtpcs_sds_write_bits(sds, 0x2f, 0x0b, 5, 3, vth_min); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x13, 5, 3, 0x07); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x13, 2, 0, 0x07); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0b, 5, 3, vth_min); /* --- 1.1.1 */ /* 1.1.2 Load DFE initial value --- */ - rtpcs_sds_write_bits(sds, 0x2e, 0x0f, 13, 7, 0x7f); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0f, 13, 7, 0x7f); /* --- 1.1.2 */ /* 1.1.3 disable LEQ training, enable DFE clock --- */ - rtpcs_sds_write_bits(sds, 0x2e, 0x17, 7, 7, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x17, 6, 2, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x0c, 8, 8, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x0b, 4, 4, 0x01); - rtpcs_sds_write_bits(sds, 0x2e, 0x12, 14, 14, 0x00); - rtpcs_sds_write_bits(sds, 0x2f, 0x02, 15, 15, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x17, 7, 7, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x17, 6, 2, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0c, 8, 8, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0b, 4, 4, 0x01); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x12, 14, 14, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x02, 15, 15, 0x00); /* --- 1.1.3 */ /* 1.1.4 offset cali setting --- */ - rtpcs_sds_write_bits(sds, 0x2e, 0x0f, 15, 14, 0x03); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0f, 15, 14, 0x03); /* --- 1.1.4 */ /* 1.1.5 LEQ and DFE setting --- */ /* assume this is equivalent with (PHY_TYPE == SERDES && MEDIA == FIBER_10G) for now */ if (hw_mode == RTPCS_SDS_MODE_10GBASER) { - rtpcs_sds_write_bits(sds, 0x2e, 0x03, 13, 8, 0x1f); - rtpcs_sds_write_bits(sds, 0x2e, 0x00, 13, 13, 0x01); - rtpcs_sds_write_bits(sds, 0x2e, 0x16, 14, 8, 0x00); /* REG0_FILTER_OUT */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x03, 13, 8, 0x1f); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x00, 13, 13, 0x01); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x16, 14, 8, 0x00); /* REG0_FILTER_OUT */ } - /* REG0_LEQ_DC_GAIN */ - rtpcs_sds_write_bits(sds, 0x2e, 0x16, 3, 2, 0x02); /* REG0_LEQ_DC_GAIN, 0x01 for short DACs */ - rtpcs_sds_write_bits(sds, 0x2e, 0x0f, 6, 0, 0x5f); - rtpcs_sds_write_bits(sds, 0x2f, 0x05, 7, 2, 0x1f); - rtpcs_sds_write_bits(sds, 0x2e, 0x19, 9, 5, 0x1f); - rtpcs_sds_write_bits(sds, 0x2f, 0x0b, 15, 9, 0x3c); - rtpcs_sds_write_bits(sds, 0x2e, 0x0b, 1, 0, 0x03); + /* REG0_LEQ_DC_GAIN, 0x01 for short DACs */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x16, 3, 2, 0x02); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0f, 6, 0, 0x5f); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x05, 7, 2, 0x1f); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x19, 9, 5, 0x1f); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0b, 15, 9, 0x3c); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0b, 1, 0, 0x03); /* --- 1.1.5 */ } -static void rtpcs_930x_sds_do_rx_calibration_2_1(struct rtpcs_serdes *sds) -{ - /* 1.2.1 ForegroundOffsetCal_Manual --- */ - - /* Gray config endis to 1 */ - rtpcs_sds_write_bits(sds, 0x2f, 0x02, 2, 2, 0x01); - - /* ForegroundOffsetCal_Manual(auto mode) */ - rtpcs_sds_write_bits(sds, 0x2e, 0x01, 14, 14, 0x00); - - /* --- 1.2.1 */ -} - -static void rtpcs_930x_sds_do_rx_calibration_2_2(struct rtpcs_serdes *sds) -{ - /* Force Rx-Run = 0 */ - rtpcs_sds_write_bits(sds, 0x2e, 0x15, 8, 8, 0x0); - - rtpcs_930x_sds_rx_reset(sds, RTPCS_SDS_MODE_10GBASER); -} - -static void rtpcs_930x_sds_do_rx_calibration_2_3(struct rtpcs_serdes *sds) +static void rtpcs_930x_sds_rxcal_fgcal(struct rtpcs_serdes *sds) { struct rtpcs_serdes *even_sds = rtpcs_sds_get_even(sds); u32 fgcal_binary, fgcal_gray; u32 offset_range; - /* 1.2.3 Foreground Calibration --- */ + rtpcs_930x_sds_rx_reset(sds, RTPCS_SDS_MODE_10GBASER); + + /* ForegroundOffsetCal_Manual */ + + /* Gray config endis to 1 */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x02, 2, 2, 0x01); + + /* ForegroundOffsetCal_Manual(auto mode) */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x01, 14, 14, 0x00); + + /* Force Rx-Run = 0 */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x15, 8, 8, 0x0); + rtpcs_930x_sds_rx_reset(sds, RTPCS_SDS_MODE_10GBASER); + + /* Foreground Calibration --- */ for (int run = 0; run < 10; run++) { /* REG_DBGO_SEL */ - rtpcs_sds_write(even_sds, 0x1f, 0x2, (sds == even_sds) ? 0x2f : 0x31); - rtpcs_sds_write_bits(sds, 0x2e, 0x15, 9, 9, 0x1); /* REG0_RX_EN_TEST */ - rtpcs_sds_write_bits(sds, 0x21, 0x06, 11, 6, 0x20); /* REG0_RX_DEBUG_SEL */ + rtpcs_sds_write(even_sds, PAGE_WDIG, 0x2, (sds == even_sds) ? 0x2f : 0x31); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x15, 9, 9, 0x1); /* REG0_RX_EN_TEST */ + rtpcs_sds_write_bits(sds, PAGE_ANA_COM, 0x06, 11, 6, 0x20); /* REG0_RX_DEBUG_SEL */ - rtpcs_sds_write_bits(sds, 0x2f, 0x0c, 5, 0, 0xf); /* REG0_COEF_SEL */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0c, 5, 0, 0xf); /* REG0_COEF_SEL */ /* ##FGCAL read gray */ - fgcal_gray = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 5, 0); - rtpcs_sds_write_bits(sds, 0x2f, 0x0c, 5, 0, 0xe); /* REG0_COEF_SEL */ + fgcal_gray = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 5, 0); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0c, 5, 0, 0xe); /* REG0_COEF_SEL */ /* ##FGCAL read binary */ - fgcal_binary = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 5, 0); + fgcal_binary = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 5, 0); if (fgcal_binary <= 60 && fgcal_binary >= 3) break; @@ -2488,184 +2450,121 @@ static void rtpcs_930x_sds_do_rx_calibration_2_3(struct rtpcs_serdes *sds) pr_info("%s: fgcal_gray = %d, fgcal_binary = %d\n", __func__, fgcal_gray, fgcal_binary); - offset_range = rtpcs_sds_read_bits(sds, 0x2e, 0x15, 15, 14); + offset_range = rtpcs_sds_read_bits(sds, PAGE_ANA_10G, 0x15, 15, 14); if (offset_range == 3) { pr_info("%s: Foreground Calibration result marginal!", __func__); break; } offset_range++; - rtpcs_sds_write_bits(sds, 0x2e, 0x15, 15, 14, offset_range); - rtpcs_930x_sds_do_rx_calibration_2_2(sds); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x15, 15, 14, offset_range); + + /* Force Rx-Run = 0 */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x15, 8, 8, 0x0); + rtpcs_930x_sds_rx_reset(sds, RTPCS_SDS_MODE_10GBASER); } - /* --- 1.2.3 */ } -static void rtpcs_930x_sds_do_rx_calibration_2(struct rtpcs_serdes *sds) +__always_unused +static void rtpcs_930x_sds_rxcal_leq_adapt_lock(struct rtpcs_serdes *sds) { - rtpcs_930x_sds_rx_reset(sds, RTPCS_SDS_MODE_10GBASER); - rtpcs_930x_sds_do_rx_calibration_2_1(sds); - rtpcs_930x_sds_do_rx_calibration_2_2(sds); - rtpcs_930x_sds_do_rx_calibration_2_3(sds); -} - -static void rtpcs_930x_sds_rxcal_3_1(struct rtpcs_serdes *sds, - enum rtpcs_sds_mode hw_mode) -{ - /* 1.3.1 --- */ - if (hw_mode != RTPCS_SDS_MODE_10GBASER && - hw_mode != RTPCS_SDS_MODE_1000BASEX && - hw_mode != RTPCS_SDS_MODE_SGMII) - rtpcs_sds_write_bits(sds, 0x2e, 0xc, 8, 8, 0); - - rtpcs_sds_write_bits(sds, 0x2e, 0x17, 7, 7, 0x0); - rtpcs_930x_sds_rxcal_leq_manual(sds, false, 0); - - /* --- 1.3.1 */ -} - -static void rtpcs_930x_sds_rxcal_3_2(struct rtpcs_serdes *sds, - enum rtpcs_sds_mode hw_mode) -{ - u32 sum10 = 0, avg10, int10; - int dac_long_cable_offset; - bool eq_hold_enabled; + /* + * SDK dacLongCableOffset / eqHoldEnable from rtl9300_rxCaliConf_serdes/phy_myParam. + * These distinguish direct SerDes connections (DAC, fiber SFP — no external PHY in + * the signal path) from PHY-attached ports (PCB traces to an external PHY). On + * PHY-attached ports the PHY handles its own equalization, so the SerDes LEQ is left + * in auto-adapt and no correction offset is needed. + */ + bool direct_serdes = sds->media == RTPCS_SDS_MEDIA_FIBER || + sds->media == RTPCS_SDS_MEDIA_DAC_SHORT || + sds->media == RTPCS_SDS_MEDIA_DAC_LONG; + u32 sum10 = 0, avg10; int i; - if (hw_mode == RTPCS_SDS_MODE_10GBASER || - hw_mode == RTPCS_SDS_MODE_1000BASEX || - hw_mode == RTPCS_SDS_MODE_SGMII) { - /* rtl9300_rxCaliConf_serdes_myParam */ - dac_long_cable_offset = 3; - eq_hold_enabled = true; - } else { - /* rtl9300_rxCaliConf_phy_myParam */ - dac_long_cable_offset = 0; - eq_hold_enabled = false; - } - - if (hw_mode != RTPCS_SDS_MODE_10GBASER) - pr_warn("%s: LEQ only valid for 10GR!\n", __func__); - - /* 1.3.2 --- */ + /* 1.3.1: release LEQ auto-adapt, let it settle from zero */ + if (!direct_serdes) + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0xc, 8, 8, 0x0); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x17, 7, 7, 0x0); + rtpcs_930x_sds_rxcal_leq_manual(sds, false, 0); + /* 1.3.2: sample the auto-adapted LEQ value 10 times over ~100ms */ for (i = 0; i < 10; i++) { sum10 += rtpcs_930x_sds_rxcal_leq_read(sds); mdelay(10); } + /* rounded average of where auto-adapt settled */ avg10 = (sum10 / 10) + (((sum10 % 10) >= 5) ? 1 : 0); - int10 = sum10 / 10; - pr_info("sum10:%u, avg10:%u, int10:%u", sum10, avg10, int10); + /* + * Empirical correction based on media type. + * Direct SerDes connections get a base offset of +3; DAC cables add further + * correction for their attenuation. PHY-attached (PCB) needs none. + */ + switch (sds->media) { + case RTPCS_SDS_MEDIA_FIBER: + avg10 += 3; + break; + case RTPCS_SDS_MEDIA_DAC_SHORT: + avg10 += 4; /* base 3 + 1 for short DAC */ + break; + case RTPCS_SDS_MEDIA_DAC_LONG: + avg10 += 6; /* base 3 + 3 for long DAC */ + break; + default: + break; + } - if (hw_mode == RTPCS_SDS_MODE_10GBASER || - hw_mode == RTPCS_SDS_MODE_1000BASEX || - hw_mode == RTPCS_SDS_MODE_SGMII) { - if (dac_long_cable_offset) { - rtpcs_930x_sds_rxcal_leq_offset_manual(sds, 1, - dac_long_cable_offset); - rtpcs_sds_write_bits(sds, 0x2e, 0x17, 7, 7, - eq_hold_enabled); - if (hw_mode == RTPCS_SDS_MODE_10GBASER) - rtpcs_930x_sds_rxcal_leq_manual(sds, - true, avg10); - } else { - if (sum10 >= 5) { - rtpcs_930x_sds_rxcal_leq_offset_manual(sds, 1, 3); - rtpcs_sds_write_bits(sds, 0x2e, 0x17, 7, 7, 0x1); - if (hw_mode == RTPCS_SDS_MODE_10GBASER) - rtpcs_930x_sds_rxcal_leq_manual(sds, true, avg10); - } else { - rtpcs_930x_sds_rxcal_leq_offset_manual(sds, 1, 0); - rtpcs_sds_write_bits(sds, 0x2e, 0x17, 7, 7, 0x1); - if (hw_mode == RTPCS_SDS_MODE_10GBASER) - rtpcs_930x_sds_rxcal_leq_manual(sds, true, avg10); - } - } + pr_info("sum10:%u, avg10:%u", sum10, avg10); + + /* lock LEQ at corrected value for direct SerDes; PHY-attached stays in auto-adapt */ + if (direct_serdes) { + rtpcs_930x_sds_rxcal_leq_offset_manual(sds, 1, 0); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x17, 7, 7, 0x1); + rtpcs_930x_sds_rxcal_leq_manual(sds, true, avg10); } pr_info("SDS %u LEQ = %u", sds->id, rtpcs_930x_sds_rxcal_leq_read(sds)); - - /* --- 1.3.2 */ } -__always_unused -static void rtpcs_930x_sds_do_rx_calibration_3(struct rtpcs_serdes *sds, - enum rtpcs_sds_mode hw_mode) +static void rtpcs_930x_sds_rxcal_vth_tap0_adapt_lock(struct rtpcs_serdes *sds) { - rtpcs_930x_sds_rxcal_3_1(sds, hw_mode); + u32 tap0_list[4] = {0}; + u32 vth_list[2] = {0}; - if (hw_mode == RTPCS_SDS_MODE_10GBASER || - hw_mode == RTPCS_SDS_MODE_1000BASEX || - hw_mode == RTPCS_SDS_MODE_SGMII) - rtpcs_930x_sds_rxcal_3_2(sds, hw_mode); -} - -static void rtpcs_930x_sds_do_rx_calibration_4_1(struct rtpcs_serdes *sds) -{ - u32 vth_list[2] = {0, 0}; - u32 tap0_list[4] = {0, 0, 0, 0}; - - /* 1.4.1 --- */ + /* run VTH/TAP auto-adapt */ rtpcs_930x_sds_rxcal_vth_manual(sds, false, vth_list); rtpcs_930x_sds_rxcal_tap_manual(sds, 0, false, tap0_list); mdelay(200); - /* --- 1.4.2 */ -} - -static void rtpcs_930x_sds_do_rx_calibration_4_2(struct rtpcs_serdes *sds) -{ - u32 vth_list[2]; - u32 tap_list[4]; - - /* 1.4.2 --- */ - + /* manually set learned VTH */ rtpcs_930x_sds_rxcal_vth_get(sds, vth_list); rtpcs_930x_sds_rxcal_vth_manual(sds, true, vth_list); mdelay(100); - rtpcs_930x_sds_rxcal_tap_get(sds, 0, tap_list); - rtpcs_930x_sds_rxcal_tap_manual(sds, 0, true, tap_list); - - /* --- 1.4.2 */ + /* manually set learned TAP0 */ + rtpcs_930x_sds_rxcal_tap_get(sds, 0, tap0_list); + rtpcs_930x_sds_rxcal_tap_manual(sds, 0, true, tap0_list); } -static void rtpcs_930x_sds_do_rx_calibration_4(struct rtpcs_serdes *sds) -{ - rtpcs_930x_sds_do_rx_calibration_4_1(sds); - rtpcs_930x_sds_do_rx_calibration_4_2(sds); -} - -static void rtpcs_930x_sds_do_rx_calibration_5_2(struct rtpcs_serdes *sds) +static void rtpcs_930x_sds_rxcal_dfe_taps_adapt(struct rtpcs_serdes *sds) { u32 tap1_list[4] = {0}; u32 tap2_list[4] = {0}; u32 tap3_list[4] = {0}; u32 tap4_list[4] = {0}; - /* 1.5.2 --- */ - + /* dfeTap1_4Enable true */ rtpcs_930x_sds_rxcal_tap_manual(sds, 1, false, tap1_list); rtpcs_930x_sds_rxcal_tap_manual(sds, 2, false, tap2_list); rtpcs_930x_sds_rxcal_tap_manual(sds, 3, false, tap3_list); rtpcs_930x_sds_rxcal_tap_manual(sds, 4, false, tap4_list); mdelay(30); - - /* --- 1.5.2 */ } -static void rtpcs_930x_sds_do_rx_calibration_5(struct rtpcs_serdes *sds, - enum rtpcs_sds_mode hw_mode) -{ - if (hw_mode == RTPCS_SDS_MODE_10GBASER) /* dfeTap1_4Enable true */ - rtpcs_930x_sds_do_rx_calibration_5_2(sds); -} - -static void rtpcs_930x_sds_do_rx_calibration_dfe_disable(struct rtpcs_serdes *sds) +static void rtpcs_930x_sds_rxcal_dfe_disable(struct rtpcs_serdes *sds) { u32 tap1_list[4] = {0}; u32 tap2_list[4] = {0}; @@ -2686,20 +2585,21 @@ static void rtpcs_930x_sds_do_rx_calibration(struct rtpcs_serdes *sds, u32 latch_sts; rtpcs_930x_sds_do_rx_calibration_1(sds, hw_mode); - rtpcs_930x_sds_do_rx_calibration_2(sds); - rtpcs_930x_sds_do_rx_calibration_4(sds); - rtpcs_930x_sds_do_rx_calibration_5(sds, hw_mode); - mdelay(20); + rtpcs_930x_sds_rxcal_fgcal(sds); + rtpcs_930x_sds_rxcal_vth_tap0_adapt_lock(sds); /* Do this only for 10GR mode */ if (hw_mode == RTPCS_SDS_MODE_10GBASER) { - latch_sts = rtpcs_sds_read_bits(sds, 0x4, 1, 2, 2); + rtpcs_930x_sds_rxcal_dfe_taps_adapt(sds); + mdelay(20); + + latch_sts = rtpcs_sds_read_bits(sds, PAGE_TGR_STD_0, 1, 2, 2); mdelay(1); - latch_sts = rtpcs_sds_read_bits(sds, 0x4, 1, 2, 2); + latch_sts = rtpcs_sds_read_bits(sds, PAGE_TGR_STD_0, 1, 2, 2); if (latch_sts) { - rtpcs_930x_sds_do_rx_calibration_dfe_disable(sds); - rtpcs_930x_sds_do_rx_calibration_4(sds); - rtpcs_930x_sds_do_rx_calibration_5(sds, hw_mode); + rtpcs_930x_sds_rxcal_dfe_disable(sds); + rtpcs_930x_sds_rxcal_vth_tap0_adapt_lock(sds); + rtpcs_930x_sds_rxcal_dfe_taps_adapt(sds); } } } @@ -2713,8 +2613,8 @@ static int rtpcs_930x_sds_sym_err_reset(struct rtpcs_serdes *sds, case RTPCS_SDS_MODE_10GBASER: case RTPCS_SDS_MODE_USXGMII_10GSXGMII: /* Read twice to clear */ - rtpcs_sds_read(sds, 0x5, 0x1); - rtpcs_sds_read(sds, 0x5, 0x1); + rtpcs_sds_read(sds, PAGE_TGR_STD_1, 0x1); + rtpcs_sds_read(sds, PAGE_TGR_STD_1, 0x1); return 0; case RTPCS_SDS_MODE_XSGMII: @@ -2728,23 +2628,23 @@ static int rtpcs_930x_sds_sym_err_reset(struct rtpcs_serdes *sds, for (channel = 0; channel < channels; channel++) { if (hw_mode == RTPCS_SDS_MODE_XSGMII) { - rtpcs_sds_xsg_write_bits(sds, 0x1, 0x18, 2, 0, channel); - rtpcs_sds_xsg_write_bits(sds, 0x1, 0x3, 15, 8, 0x0); - rtpcs_sds_xsg_write_bits(sds, 0x1, 0x2, 15, 0, 0x0); + rtpcs_sds_xsg_write_bits(sds, PAGE_SDS_EXT, 0x18, 2, 0, channel); + rtpcs_sds_xsg_write_bits(sds, PAGE_SDS_EXT, 0x3, 15, 8, 0x0); + rtpcs_sds_xsg_write_bits(sds, PAGE_SDS_EXT, 0x2, 15, 0, 0x0); } else { - rtpcs_sds_write_bits(sds, 0x1, 0x18, 2, 0, channel); - rtpcs_sds_write_bits(sds, 0x1, 0x3, 15, 8, 0x0); - rtpcs_sds_write_bits(sds, 0x1, 0x2, 15, 0, 0x0); + rtpcs_sds_write_bits(sds, PAGE_SDS_EXT, 0x18, 2, 0, channel); + rtpcs_sds_write_bits(sds, PAGE_SDS_EXT, 0x3, 15, 8, 0x0); + rtpcs_sds_write_bits(sds, PAGE_SDS_EXT, 0x2, 15, 0, 0x0); } } if (channels > 1) { if (hw_mode == RTPCS_SDS_MODE_XSGMII) { - rtpcs_sds_xsg_write_bits(sds, 0x1, 0x0, 15, 0, 0x0); - rtpcs_sds_xsg_write_bits(sds, 0x1, 0x1, 15, 8, 0x0); + rtpcs_sds_xsg_write_bits(sds, PAGE_SDS_EXT, 0x0, 15, 0, 0x0); + rtpcs_sds_xsg_write_bits(sds, PAGE_SDS_EXT, 0x1, 15, 8, 0x0); } else { - rtpcs_sds_write_bits(sds, 0x1, 0x0, 15, 0, 0x0); - rtpcs_sds_write_bits(sds, 0x1, 0x1, 15, 8, 0x0); + rtpcs_sds_write_bits(sds, PAGE_SDS_EXT, 0x0, 15, 0, 0x0); + rtpcs_sds_write_bits(sds, PAGE_SDS_EXT, 0x1, 15, 8, 0x0); } } @@ -2759,8 +2659,8 @@ static u32 rtpcs_930x_sds_sym_err_get(struct rtpcs_serdes *sds, switch (hw_mode) { case RTPCS_SDS_MODE_QSGMII: case RTPCS_SDS_MODE_XSGMII: - v = rtpcs_sds_read_bits(sds, 0x1, 0x1, 15, 8) << 16; /* ALL_SYMBOLERR_CNT_NEW_23_16 */ - v |= rtpcs_sds_read_bits(sds, 0x1, 0x0, 15, 0); /* ALL_SYMBOLERR_CNT_NEW_15_0 */ + v = rtpcs_sds_read_bits(sds, PAGE_SDS_EXT, 0x1, 15, 8) << 16; /* ALL_SYMBOLERR_CNT_NEW_23_16 */ + v |= rtpcs_sds_read_bits(sds, PAGE_SDS_EXT, 0x0, 15, 0); /* ALL_SYMBOLERR_CNT_NEW_15_0 */ break; case RTPCS_SDS_MODE_USXGMII_10GQXGMII: @@ -2770,15 +2670,15 @@ static u32 rtpcs_930x_sds_sym_err_get(struct rtpcs_serdes *sds, case RTPCS_SDS_MODE_SGMII: case RTPCS_SDS_MODE_10GBASER: case RTPCS_SDS_MODE_USXGMII_10GSXGMII: - v = rtpcs_sds_read(sds, 0x5, 0x1); + v = rtpcs_sds_read(sds, PAGE_TGR_STD_1, 0x1); v &= 0xff; break; default: - rtpcs_sds_write_bits(sds, 0x1, 24, 2, 0, 0); + rtpcs_sds_write_bits(sds, PAGE_SDS_EXT, 24, 2, 0, 0); - v = rtpcs_sds_read_bits(sds, 0x1, 0x3, 15, 8) << 16; /* MUX_SYMBOLERR_CNT_NEW_23_16 */ - v |= rtpcs_sds_read_bits(sds, 0x1, 0x2, 15, 0); /* MUX_SYMBOLERR_CNT_NEW_15_0 */ + v = rtpcs_sds_read_bits(sds, PAGE_SDS_EXT, 0x3, 15, 8) << 16; /* MUX_SYMBOLERR_CNT_NEW_23_16 */ + v |= rtpcs_sds_read_bits(sds, PAGE_SDS_EXT, 0x2, 15, 0); /* MUX_SYMBOLERR_CNT_NEW_15_0 */ } return v; @@ -2826,8 +2726,8 @@ static int rtpcs_930x_sds_10g_idle(struct rtpcs_serdes *sds) timeout = ktime_add_us(ktime_get(), 10000); /* timeout after 10 msecs */ do { - rtpcs_sds_write(even_sds, 0x1f, 0x2, 53); - busy = rtpcs_sds_read_bits(even_sds, 0x1f, 0x14, bit, bit); + rtpcs_sds_write(even_sds, PAGE_WDIG, 0x2, 53); + busy = rtpcs_sds_read_bits(even_sds, PAGE_WDIG, 0x14, bit, bit); if (busy < 0) return busy; @@ -2852,73 +2752,101 @@ static int rtpcs_930x_sds_config_polarity(struct rtpcs_serdes *sds, unsigned int /* 10GR */ val = (tx_val << 1) | rx_val; - ret = rtpcs_sds_write_bits(sds, 0x6, 0x2, 14, 13, val); + ret = rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x2, 14, 13, val); if (ret) return ret; /* 1G */ val = (rx_val << 1) | tx_val; - return rtpcs_sds_write_bits(sds, 0x0, 0x0, 9, 8, val); + return rtpcs_sds_write_bits(sds, PAGE_SDS, 0x0, 9, 8, val); } static const struct rtpcs_sds_config rtpcs_930x_sds_cfg_ana_com[] = { - {0x21, 0x03, 0x8206}, {0x21, 0x05, 0x40B0}, {0x21, 0x06, 0x0010}, {0x21, 0x07, 0xF09F}, - {0x21, 0x0A, 0x0003}, {0x21, 0x0B, 0x0005}, {0x21, 0x0C, 0x0007}, {0x21, 0x0D, 0x6009}, - {0x21, 0x0E, 0x0000}, {0x21, 0x0F, 0x0008} + {PAGE_ANA_COM, 0x03, 0x8206}, {PAGE_ANA_COM, 0x05, 0x40B0}, + {PAGE_ANA_COM, 0x06, 0x0010}, {PAGE_ANA_COM, 0x07, 0xF09F}, + {PAGE_ANA_COM, 0x0A, 0x0003}, {PAGE_ANA_COM, 0x0B, 0x0005}, + {PAGE_ANA_COM, 0x0C, 0x0007}, {PAGE_ANA_COM, 0x0D, 0x6009}, + {PAGE_ANA_COM, 0x0E, 0x0000}, {PAGE_ANA_COM, 0x0F, 0x0008} }; static const struct rtpcs_sds_config rtpcs_930x_sds_cfg_ana_1g[] = { - {0x24, 0x00, 0x0668}, {0x24, 0x02, 0xD020}, {0x24, 0x06, 0xC000}, {0x24, 0x0B, 0x1892}, - {0x24, 0x0F, 0xFFDF}, {0x24, 0x12, 0x03C4}, {0x24, 0x13, 0x027F}, {0x24, 0x14, 0x1311}, - {0x24, 0x16, 0x00C9}, {0x24, 0x17, 0xA100}, {0x24, 0x1A, 0x0001}, {0x24, 0x1C, 0x0400}, - {0x25, 0x00, 0x820F}, {0x25, 0x01, 0x0300}, {0x25, 0x02, 0x1017}, {0x25, 0x03, 0xFFDF}, - {0x25, 0x05, 0x7F7C}, {0x25, 0x07, 0x8100}, {0x25, 0x08, 0x0001}, {0x25, 0x09, 0xFFD4}, - {0x25, 0x0A, 0x7C2F}, {0x25, 0x0E, 0x003F}, {0x25, 0x0F, 0x0121}, {0x25, 0x10, 0x0020}, - {0x25, 0x11, 0x8840} + {PAGE_ANA_1G2, 0x00, 0x0668}, {PAGE_ANA_1G2, 0x02, 0xD020}, + {PAGE_ANA_1G2, 0x06, 0xC000}, {PAGE_ANA_1G2, 0x0B, 0x1892}, + {PAGE_ANA_1G2, 0x0F, 0xFFDF}, {PAGE_ANA_1G2, 0x12, 0x03C4}, + {PAGE_ANA_1G2, 0x13, 0x027F}, {PAGE_ANA_1G2, 0x14, 0x1311}, + {PAGE_ANA_1G2, 0x16, 0x00C9}, {PAGE_ANA_1G2, 0x17, 0xA100}, + {PAGE_ANA_1G2, 0x1A, 0x0001}, {PAGE_ANA_1G2, 0x1C, 0x0400}, + {PAGE_ANA_1G2_EXT, 0x00, 0x820F}, {PAGE_ANA_1G2_EXT, 0x01, 0x0300}, + {PAGE_ANA_1G2_EXT, 0x02, 0x1017}, {PAGE_ANA_1G2_EXT, 0x03, 0xFFDF}, + {PAGE_ANA_1G2_EXT, 0x05, 0x7F7C}, {PAGE_ANA_1G2_EXT, 0x07, 0x8100}, + {PAGE_ANA_1G2_EXT, 0x08, 0x0001}, {PAGE_ANA_1G2_EXT, 0x09, 0xFFD4}, + {PAGE_ANA_1G2_EXT, 0x0A, 0x7C2F}, {PAGE_ANA_1G2_EXT, 0x0E, 0x003F}, + {PAGE_ANA_1G2_EXT, 0x0F, 0x0121}, {PAGE_ANA_1G2_EXT, 0x10, 0x0020}, + {PAGE_ANA_1G2_EXT, 0x11, 0x8840} }; static const struct rtpcs_sds_config rtpcs_930x_sds_cfg_ana_3g[] = { - {0x28, 0x00, 0x0668}, {0x28, 0x02, 0xD020}, {0x28, 0x06, 0xC000}, {0x28, 0x0B, 0x1892}, - {0x28, 0x0F, 0xFFDF}, {0x28, 0x12, 0x01C4}, {0x28, 0x13, 0x027F}, {0x28, 0x14, 0x1311}, - {0x28, 0x16, 0x00C9}, {0x28, 0x17, 0xA100}, {0x28, 0x1A, 0x0001}, {0x28, 0x1C, 0x0400}, - {0x29, 0x00, 0x820F}, {0x29, 0x01, 0x0300}, {0x29, 0x02, 0x1017}, {0x29, 0x03, 0xFFDF}, - {0x29, 0x05, 0x7F7C}, {0x29, 0x07, 0x8100}, {0x29, 0x08, 0x0001}, {0x29, 0x09, 0xFFD4}, - {0x29, 0x0A, 0x7C2F}, {0x29, 0x0E, 0x003F}, {0x29, 0x0F, 0x0121}, {0x29, 0x10, 0x0020}, - {0x29, 0x11, 0x8840}, + {PAGE_ANA_3G1, 0x00, 0x0668}, {PAGE_ANA_3G1, 0x02, 0xD020}, + {PAGE_ANA_3G1, 0x06, 0xC000}, {PAGE_ANA_3G1, 0x0B, 0x1892}, + {PAGE_ANA_3G1, 0x0F, 0xFFDF}, {PAGE_ANA_3G1, 0x12, 0x01C4}, + {PAGE_ANA_3G1, 0x13, 0x027F}, {PAGE_ANA_3G1, 0x14, 0x1311}, + {PAGE_ANA_3G1, 0x16, 0x00C9}, {PAGE_ANA_3G1, 0x17, 0xA100}, + {PAGE_ANA_3G1, 0x1A, 0x0001}, {PAGE_ANA_3G1, 0x1C, 0x0400}, + {PAGE_ANA_3G1_EXT, 0x00, 0x820F}, {PAGE_ANA_3G1_EXT, 0x01, 0x0300}, + {PAGE_ANA_3G1_EXT, 0x02, 0x1017}, {PAGE_ANA_3G1_EXT, 0x03, 0xFFDF}, + {PAGE_ANA_3G1_EXT, 0x05, 0x7F7C}, {PAGE_ANA_3G1_EXT, 0x07, 0x8100}, + {PAGE_ANA_3G1_EXT, 0x08, 0x0001}, {PAGE_ANA_3G1_EXT, 0x09, 0xFFD4}, + {PAGE_ANA_3G1_EXT, 0x0A, 0x7C2F}, {PAGE_ANA_3G1_EXT, 0x0E, 0x003F}, + {PAGE_ANA_3G1_EXT, 0x0F, 0x0121}, {PAGE_ANA_3G1_EXT, 0x10, 0x0020}, + {PAGE_ANA_3G1_EXT, 0x11, 0x8840}, }; static const struct rtpcs_sds_config rtpcs_930x_sds_cfg_ana_10g[] = { - {0x2E, 0x00, 0xA668}, {0x2E, 0x01, 0x2088}, {0x2E, 0x02, 0xD020}, {0x2E, 0x06, 0xC000}, - {0x2E, 0x0B, 0x1892}, {0x2E, 0x0F, 0xFFDF}, {0x2E, 0x11, 0x8280}, {0x2E, 0x12, 0x0044}, - {0x2E, 0x13, 0x027F}, {0x2E, 0x14, 0x1311}, {0x2E, 0x17, 0xA100}, {0x2E, 0x1A, 0x0001}, - {0x2E, 0x1C, 0x0400}, {0x2F, 0x00, 0x820F}, {0x2F, 0x01, 0x0300}, {0x2F, 0x02, 0x1217}, - {0x2F, 0x03, 0xFFDF}, {0x2F, 0x05, 0x7F7C}, {0x2F, 0x07, 0x80C4}, {0x2F, 0x08, 0x0001}, - {0x2F, 0x09, 0xFFD4}, {0x2F, 0x0A, 0x7C2F}, {0x2F, 0x0E, 0x003F}, {0x2F, 0x0F, 0x0121}, - {0x2F, 0x10, 0x0020}, {0x2F, 0x11, 0x8840}, + {PAGE_ANA_10G, 0x00, 0xA668}, {PAGE_ANA_10G, 0x01, 0x2088}, + {PAGE_ANA_10G, 0x02, 0xD020}, {PAGE_ANA_10G, 0x06, 0xC000}, + {PAGE_ANA_10G, 0x0B, 0x1892}, {PAGE_ANA_10G, 0x0F, 0xFFDF}, + {PAGE_ANA_10G, 0x11, 0x8280}, {PAGE_ANA_10G, 0x12, 0x0044}, + {PAGE_ANA_10G, 0x13, 0x027F}, {PAGE_ANA_10G, 0x14, 0x1311}, + {PAGE_ANA_10G, 0x17, 0xA100}, {PAGE_ANA_10G, 0x1A, 0x0001}, + {PAGE_ANA_10G, 0x1C, 0x0400}, + {PAGE_ANA_10G_EXT, 0x00, 0x820F}, {PAGE_ANA_10G_EXT, 0x01, 0x0300}, + {PAGE_ANA_10G_EXT, 0x02, 0x1217}, {PAGE_ANA_10G_EXT, 0x03, 0xFFDF}, + {PAGE_ANA_10G_EXT, 0x05, 0x7F7C}, {PAGE_ANA_10G_EXT, 0x07, 0x80C4}, + {PAGE_ANA_10G_EXT, 0x08, 0x0001}, {PAGE_ANA_10G_EXT, 0x09, 0xFFD4}, + {PAGE_ANA_10G_EXT, 0x0A, 0x7C2F}, {PAGE_ANA_10G_EXT, 0x0E, 0x003F}, + {PAGE_ANA_10G_EXT, 0x0F, 0x0121}, {PAGE_ANA_10G_EXT, 0x10, 0x0020}, + {PAGE_ANA_10G_EXT, 0x11, 0x8840}, }; static const struct rtpcs_sds_config rtpcs_930x_sds_cfg_usxgmii_xsgmii[] = { - {0x2E, 0x12, 0x0484}, {0x2F, 0x02, 0x1017}, {0x2F, 0x07, 0x8104} + {PAGE_ANA_10G, 0x12, 0x0484}, + {PAGE_ANA_10G_EXT, 0x02, 0x1017}, {PAGE_ANA_10G_EXT, 0x07, 0x8104} }; static const struct rtpcs_sds_config rtpcs_930x_sds_cfg_5g_qsgmii[] = { - {0x21, 0x00, 0x3C91},{0x21, 0x02, 0xB602},{0x21, 0x07, 0xFA66},{0x21, 0x0A, 0xDF40}, - {0x2A, 0x02, 0x35A1},{0x2A, 0x03, 0x6960}, + {PAGE_ANA_COM, 0x00, 0x3C91}, {PAGE_ANA_COM, 0x02, 0xB602}, + {PAGE_ANA_COM, 0x07, 0xFA66}, {PAGE_ANA_COM, 0x0A, 0xDF40}, + {PAGE_ANA_5G0, 0x02, 0x35A1}, {PAGE_ANA_5G0, 0x03, 0x6960}, }; static const struct rtpcs_sds_config rtpcs_930x_sds_cfg_final_even[] = { - {0x2B, 0x13, 0x0050}, {0x2B, 0x18, 0x8E88}, {0x2B, 0x19, 0x4902}, {0x2B, 0x1D, 0x2501}, - {0x2D, 0x13, 0x0050}, {0x2D, 0x17, 0x4109}, {0x2D, 0x18, 0x8E88}, {0x2D, 0x19, 0x4902}, - {0x2D, 0x1C, 0x1109}, {0x2D, 0x1D, 0x2641}, {0x2F, 0x13, 0x0050}, {0x2F, 0x18, 0x8E88}, - {0x2F, 0x19, 0x4902}, {0x2F, 0x1D, 0x66E1}, + {PAGE_ANA_5G0_EXT, 0x13, 0x0050}, {PAGE_ANA_5G0_EXT, 0x18, 0x8E88}, + {PAGE_ANA_5G0_EXT, 0x19, 0x4902}, {PAGE_ANA_5G0_EXT, 0x1D, 0x2501}, + + {PAGE_ANA_6G2_EXT, 0x13, 0x0050}, {PAGE_ANA_6G2_EXT, 0x17, 0x4109}, + {PAGE_ANA_6G2_EXT, 0x18, 0x8E88}, {PAGE_ANA_6G2_EXT, 0x19, 0x4902}, + {PAGE_ANA_6G2_EXT, 0x1C, 0x1109}, {PAGE_ANA_6G2_EXT, 0x1D, 0x2641}, + + {PAGE_ANA_10G_EXT, 0x13, 0x0050}, {PAGE_ANA_10G_EXT, 0x18, 0x8E88}, + {PAGE_ANA_10G_EXT, 0x19, 0x4902}, {PAGE_ANA_10G_EXT, 0x1D, 0x66E1}, }; static const struct rtpcs_sds_config rtpcs_930x_sds_cfg_final_odd[] = { - {0x2B, 0x13, 0x3D87}, {0x2B, 0x14, 0x3108}, - {0x2D, 0x13, 0x3C87}, {0x2D, 0x14, 0x1808} + {PAGE_ANA_5G0_EXT, 0x13, 0x3D87}, {PAGE_ANA_5G0_EXT, 0x14, 0x3108}, + {PAGE_ANA_6G2_EXT, 0x13, 0x3C87}, {PAGE_ANA_6G2_EXT, 0x14, 0x1808} }; static int rtpcs_930x_sds_config_hw_mode(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode) @@ -2941,10 +2869,10 @@ static int rtpcs_930x_sds_config_hw_mode(struct rtpcs_serdes *sds, enum rtpcs_sd if (hw_mode != RTPCS_SDS_MODE_USXGMII_10GSXGMII && hw_mode != RTPCS_SDS_MODE_USXGMII_10GQXGMII) { if (is_xsgmii) - rtpcs_sds_xsg_write(sds, 0x00, 0x0E, 0x3053); + rtpcs_sds_xsg_write(sds, PAGE_SDS, 0x0E, 0x3053); else { - rtpcs_sds_write(sds, 0x00, 0x0E, 0x3053); - rtpcs_sds_write(sds, 0x01, 0x14, 0x0100); + rtpcs_sds_write(sds, PAGE_SDS, 0x0E, 0x3053); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 0x14, 0x0100); } } @@ -2963,9 +2891,9 @@ static int rtpcs_930x_sds_config_hw_mode(struct rtpcs_serdes *sds, enum rtpcs_sd break; case RTPCS_SDS_MODE_10GBASER: - rtpcs_sds_write(sds, 0x06, 0x0D, 0x0F00); - rtpcs_sds_write(sds, 0x06, 0x00, 0x0000); - rtpcs_sds_write(sds, 0x06, 0x01, 0xC800); + rtpcs_sds_write(sds, PAGE_TGR_PRO_0, 0x0D, 0x0F00); + rtpcs_sds_write(sds, PAGE_TGR_PRO_0, 0x00, 0x0000); + rtpcs_sds_write(sds, PAGE_TGR_PRO_0, 0x01, 0xC800); /* * TODO: Do the 1G and 3G sequences need to be applied? The SDK usually * uses a 10GR-1000BX automatic mode covering all speeds. But in Linux, @@ -2987,7 +2915,7 @@ static int rtpcs_930x_sds_config_hw_mode(struct rtpcs_serdes *sds, enum rtpcs_sd if (ret < 0) return ret; - rtpcs_sds_write(sds, 0x2F, 0x14, 0xE008); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x14, 0xE008); break; case RTPCS_SDS_MODE_2500BASEX: @@ -3017,8 +2945,8 @@ static int rtpcs_930x_sds_config_hw_mode(struct rtpcs_serdes *sds, enum rtpcs_sd return ret; if (!is_xsgmii) - /* opcode 0x03: standard/generic USXGMII mode */ - rtpcs_93xx_sds_usxgmii_config(sds, 0x03, 0xa4, 0, 1, 0x1); + rtpcs_93xx_sds_usxgmii_config(sds, RTPCS_USXGMII_AN_OPC_STD, + 0xa4, 0, 1, 0x1); break; default: @@ -3036,66 +2964,22 @@ static int rtpcs_930x_sds_config_hw_mode(struct rtpcs_serdes *sds, enum rtpcs_sd return ret; if (hw_mode == RTPCS_SDS_MODE_10GBASER && is_even_sds) - rtpcs_sds_write(sds, 0x2F, 0x1D, 0x76E1); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x1D, 0x76E1); return 0; } -__always_unused -static int rtpcs_930x_sds_cmu_band_get(struct rtpcs_serdes *sds) +static int rtpcs_930x_sds_config_media(struct rtpcs_serdes *sds, enum rtpcs_sds_media media, + enum rtpcs_sds_mode hw_mode) { - struct rtpcs_serdes *even_sds = rtpcs_sds_get_even(sds); - struct rtpcs_serdes *odd_sds = rtpcs_sds_get_odd(sds); - u32 page; - u32 en; - u32 cmu_band; - -/* page = rtl9300_sds_cmu_page_get(sds); */ - page = 0x25; /* 10GR and 1000BX */ - - rtpcs_sds_write_bits(even_sds, page, 0x1c, 15, 15, 1); - rtpcs_sds_write_bits(odd_sds, page, 0x1c, 15, 15, 1); - - en = rtpcs_sds_read_bits(even_sds, page, 27, 1, 1); - if (!en) { /* Auto mode */ - rtpcs_sds_write(even_sds, 0x1f, 0x02, 31); - - cmu_band = rtpcs_sds_read_bits(even_sds, 0x1f, 0x15, 5, 1); - } else { - cmu_band = rtpcs_sds_read_bits(even_sds, page, 30, 4, 0); - } - - return cmu_band; -} - -static int rtpcs_930x_setup_serdes(struct rtpcs_serdes *sds, - enum rtpcs_sds_mode hw_mode) -{ - int ret; - - /* Apply configuration for a hardware mode to SerDes */ - ret = rtpcs_930x_sds_config_hw_mode(sds, hw_mode); - if (ret < 0) - return ret; - - /* Maybe use dal_longan_sds_init */ - /* * dal_longan_construct_mac_default_10gmedia_fiber: set medium to fiber. * TODO: this is unconditional regardless of hw_mode; needs mode-aware * handling. */ - rtpcs_sds_write_bits(sds, 0x1f, 11, 1, 1, 1); + rtpcs_sds_write_bits(sds, PAGE_WDIG, 11, 1, 1, 1); rtpcs_930x_sds_tx_config(sds, hw_mode); - - /* Enable SDS in desired mode */ - ret = rtpcs_930x_sds_set_mode(sds, hw_mode); - if (ret < 0) - return ret; - - sds->hw_mode = hw_mode; - return 0; } @@ -3161,17 +3045,17 @@ static int rtpcs_930x_sds_probe(struct rtpcs_serdes *sds) * An XSG write operates on digital SDS 1 and digital SDS 2. Map that to the * page ranges accordingly. */ -static int rtpcs_931x_sds_op_xsg_write(struct rtpcs_serdes *sds, int page, int regnum, +static int rtpcs_931x_sds_op_xsg_write(struct rtpcs_serdes *sds, enum rtpcs_page page, int regnum, int bithigh, int bitlow, u16 value) { int ret; - ret = __rtpcs_sds_write_raw(sds->ctrl, sds->id, page + 0x40, regnum, bithigh, bitlow, + ret = __rtpcs_sds_write_raw(sds->ctrl, sds->id, DIGI_1(page), regnum, bithigh, bitlow, value); if (ret) return ret; - return __rtpcs_sds_write_raw(sds->ctrl, sds->id, page + 0x80, regnum, bithigh, bitlow, + return __rtpcs_sds_write_raw(sds->ctrl, sds->id, DIGI_2(page), regnum, bithigh, bitlow, value); } @@ -3183,13 +3067,13 @@ static int rtpcs_931x_sds_fiber_get_symerr(struct rtpcs_serdes *sds, switch (hw_mode) { case RTPCS_SDS_MODE_10GBASER: - symerr = rtpcs_sds_read_bits(sds, 0x5, 0x1, 7, 0); + symerr = rtpcs_sds_read_bits(sds, PAGE_TGR_STD_1, 0x1, 7, 0); break; case RTPCS_SDS_MODE_1000BASEX: - rtpcs_sds_write_bits(sds, 0x41, 0x18, 2, 0, 0x0); + rtpcs_sds_write_bits(sds, DIGI_1(PAGE_SDS_EXT), 0x18, 2, 0, 0x0); - val = rtpcs_sds_read_bits(sds, 0x41, 0x3, 15, 8); - val2 = rtpcs_sds_read_bits(sds, 0x41, 0x2, 15, 0); + val = rtpcs_sds_read_bits(sds, DIGI_1(PAGE_SDS_EXT), 0x3, 15, 8); + val2 = rtpcs_sds_read_bits(sds, DIGI_1(PAGE_SDS_EXT), 0x2, 15, 0); symerr = (val << 16) | val2; break; default: @@ -3206,30 +3090,22 @@ static void rtpcs_931x_sds_clear_symerr(struct rtpcs_serdes *sds, case RTPCS_SDS_MODE_SGMII: case RTPCS_SDS_MODE_XSGMII: for (int i = 0; i < 4; ++i) { - rtpcs_sds_write_bits(sds, 0x41, 0x18, 2, 0, i); - rtpcs_sds_write_bits(sds, 0x41, 0x3, 15, 8, 0x0); - rtpcs_sds_write_bits(sds, 0x41, 0x2, 15, 0, 0x0); + rtpcs_sds_xsg_write_bits(sds, PAGE_SDS_EXT, 0x18, 2, 0, i); + rtpcs_sds_xsg_write_bits(sds, PAGE_SDS_EXT, 0x3, 15, 8, 0x0); + rtpcs_sds_xsg_write(sds, PAGE_SDS_EXT, 0x2, 0x0); } - for (int i = 0; i < 4; ++i) { - rtpcs_sds_write_bits(sds, 0x81, 0x18, 2, 0, i); - rtpcs_sds_write_bits(sds, 0x81, 0x3, 15, 8, 0x0); - rtpcs_sds_write_bits(sds, 0x81, 0x2, 15, 0, 0x0); - } - - rtpcs_sds_write_bits(sds, 0x41, 0x0, 15, 0, 0x0); - rtpcs_sds_write_bits(sds, 0x41, 0x1, 15, 8, 0x0); - rtpcs_sds_write_bits(sds, 0x81, 0x0, 15, 0, 0x0); - rtpcs_sds_write_bits(sds, 0x81, 0x1, 15, 8, 0x0); + rtpcs_sds_xsg_write(sds, PAGE_SDS_EXT, 0x0, 0x0); + rtpcs_sds_xsg_write_bits(sds, PAGE_SDS_EXT, 0x1, 15, 8, 0x0); break; case RTPCS_SDS_MODE_1000BASEX: - rtpcs_sds_write_bits(sds, 0x41, 0x18, 2, 0, 0x0); - rtpcs_sds_write_bits(sds, 0x41, 0x3, 15, 8, 0x0); - rtpcs_sds_write_bits(sds, 0x41, 0x2, 15, 0, 0x0); + rtpcs_sds_write_bits(sds, DIGI_1(PAGE_SDS_EXT), 0x18, 2, 0, 0x0); + rtpcs_sds_write_bits(sds, DIGI_1(PAGE_SDS_EXT), 0x3, 15, 8, 0x0); + rtpcs_sds_write_bits(sds, DIGI_1(PAGE_SDS_EXT), 0x2, 15, 0, 0x0); break; case RTPCS_SDS_MODE_10GBASER: /* to be verified: clear on read? */ - rtpcs_sds_read_bits(sds, 0x5, 0x1, 7, 0); + rtpcs_sds_read_bits(sds, PAGE_TGR_STD_1, 0x1, 7, 0); break; case RTPCS_SDS_MODE_OFF: default: @@ -3253,17 +3129,17 @@ static void rtpcs_931x_sds_clear_symerr(struct rtpcs_serdes *sds, */ static int rtpcs_931x_sds_reset_leq_dfe(struct rtpcs_serdes *sds) { - rtpcs_sds_write_bits(sds, 0x2e, 0xd, 6, 0, 0x0); /* [6:2] LEQ gain */ - rtpcs_sds_write_bits(sds, 0x2e, 0xd, 7, 7, 0x1); /* LEQ manual 1=true,0=false */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0xd, 6, 0, 0x0); /* [6:2] LEQ gain */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0xd, 7, 7, 0x1); /* LEQ manual 1=true,0=false */ - rtpcs_sds_write_bits(sds, 0x2e, 0x1c, 5, 0, 0x1e); /* TAP0 */ - rtpcs_sds_write_bits(sds, 0x2e, 0x1d, 11, 0, 0x0); /* TAP1 [11:6] ODD | [5:0] EVEN */ - rtpcs_sds_write_bits(sds, 0x2e, 0x1f, 11, 0, 0x0); /* TAP2 [11:6] ODD | [5:0] EVEN */ - rtpcs_sds_write_bits(sds, 0x2f, 0x0, 11, 0, 0x0); /* TAP3 [11:6] ODD | [5:0] EVEN */ - rtpcs_sds_write_bits(sds, 0x2f, 0x1, 11, 0, 0x0); /* TAP4 [11:6] ODD | [5:0] EVEN */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1c, 5, 0, 0x1e); /* TAP0 */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 11, 0, 0x0); /* TAP1 [11:6] ODD | [5:0] EVEN */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1f, 11, 0, 0x0); /* TAP2 [11:6] ODD | [5:0] EVEN */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0, 11, 0, 0x0); /* TAP3 [11:6] ODD | [5:0] EVEN */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x1, 11, 0, 0x0); /* TAP4 [11:6] ODD | [5:0] EVEN */ - rtpcs_sds_write_bits(sds, 0x2e, 0xf, 12, 6, 0x7f); /* set manual mode */ - rtpcs_sds_write(sds, 0x2f, 0x12, 0xaaa); /* [11:8] VTHN | [7:4] VTHP */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0xf, 12, 6, 0x7f); /* set manual mode */ + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x12, 0xaaa); /* [11:8] VTHN | [7:4] VTHP */ return 0; } @@ -3326,6 +3202,7 @@ static int rtpcs_931x_sds_activate(struct rtpcs_serdes *sds) return rtpcs_931x_sds_power(sds, true); } +__maybe_unused static void rtpcs_931x_sds_reset(struct rtpcs_serdes *sds) { u32 o_mode, f_bit; @@ -3354,15 +3231,15 @@ static void rtpcs_931x_sds_rx_reset(struct rtpcs_serdes *sds) if (sds->type != RTPCS_SDS_TYPE_10G) return; - rtpcs_sds_write(sds, 0x2e, 0x12, 0x2740); - rtpcs_sds_write(sds, 0x2f, 0x0, 0x0); /* [11:6] DFE_TAP3_ODD | [5:0] DFE_TAP3_EVEN */ - rtpcs_sds_write(sds, 0x2f, 0x2, 0x2010); - rtpcs_sds_write(sds, 0x20, 0x0, 0xc10); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x12, 0x2740); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x0, 0x0); /* [11:6] DFE_TAP3_ODD | [5:0] DFE_TAP3_EVEN */ + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x2, 0x2010); + rtpcs_sds_write(sds, PAGE_ANA_MISC, 0x0, 0xc10); - rtpcs_sds_write(sds, 0x2e, 0x12, 0x27c0); - rtpcs_sds_write(sds, 0x2f, 0x0, 0xc000); /* [11:6] DFE_TAP3_ODD | [5:0] DFE_TAP3_EVEN */ - rtpcs_sds_write(sds, 0x2f, 0x2, 0x6010); - rtpcs_sds_write(sds, 0x20, 0x0, 0xc30); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x12, 0x27c0); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x0, 0xc000); /* [11:6] DFE_TAP3_ODD | [5:0] DFE_TAP3_EVEN */ + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x2, 0x6010); + rtpcs_sds_write(sds, PAGE_ANA_MISC, 0x0, 0xc30); mdelay(50); } @@ -3372,12 +3249,12 @@ static int rtpcs_931x_sds_cmu_page_get(enum rtpcs_sds_mode hw_mode) switch (hw_mode) { case RTPCS_SDS_MODE_SGMII: case RTPCS_SDS_MODE_1000BASEX: - return 0x24; /* ANA_1G */ + return PAGE_ANA_1G2; case RTPCS_SDS_MODE_2500BASEX: - return 0x28; /* ANA_3G */ + return PAGE_ANA_3G1; case RTPCS_SDS_MODE_QSGMII: - return 0x2a; /* ANA_5G/6G */ - // return 0x34; + return PAGE_ANA_5G0; + // return PAGE_ANA_6G0; case RTPCS_SDS_MODE_XSGMII: case RTPCS_SDS_MODE_USXGMII_10GSXGMII: case RTPCS_SDS_MODE_USXGMII_10GDXGMII: @@ -3386,7 +3263,7 @@ static int rtpcs_931x_sds_cmu_page_get(enum rtpcs_sds_mode hw_mode) case RTPCS_SDS_MODE_USXGMII_5GDXGMII: case RTPCS_SDS_MODE_USXGMII_2_5GSXGMII: case RTPCS_SDS_MODE_10GBASER: - return 0x2e; /* ANA_10G */ + return PAGE_ANA_10G; default: return -ENOTSUPP; } @@ -3430,7 +3307,7 @@ static int rtpcs_931x_sds_set_pll_select(struct rtpcs_serdes *sds, enum rtpcs_sd */ val = (pll == RTPCS_SDS_PLL_TYPE_LC) ? 0x3 : 0x1; frc_lc_mode_bit = (sds == even_sds) ? 4 : 6; - ret = rtpcs_sds_write_bits(even_sds, 0x20, 0x12, frc_lc_mode_bit + 1, + ret = rtpcs_sds_write_bits(even_sds, PAGE_ANA_MISC, 0x12, frc_lc_mode_bit + 1, frc_lc_mode_bit, val); if (ret < 0) return ret; @@ -3480,46 +3357,6 @@ static int rtpcs_931x_sds_reconfigure_to_pll(struct rtpcs_serdes *sds, enum rtpc return rtpcs_931x_sds_power(sds, true); } -static int rtpcs_931x_sds_cmu_band_set(struct rtpcs_serdes *sds, - bool enable, u32 band, - enum rtpcs_sds_mode hw_mode) -{ - struct rtpcs_serdes *even_sds = rtpcs_sds_get_even(sds); - int page = rtpcs_931x_sds_cmu_page_get(hw_mode); - int en_val; - - if (page < 0) - return -EINVAL; - - page += 1; - en_val = enable ? 0 : 1; - - rtpcs_sds_write_bits(even_sds, page, 0x7, 13, 13, en_val); - rtpcs_sds_write_bits(even_sds, page, 0x7, 11, 11, en_val); - rtpcs_sds_write_bits(even_sds, page, 0x7, 4, 0, band); - - rtpcs_931x_sds_reset(even_sds); - - return 0; -} - -__maybe_unused -static int rtpcs_931x_sds_cmu_band_get(struct rtpcs_serdes *sds, - enum rtpcs_sds_mode hw_mode) -{ - struct rtpcs_serdes *even_sds = rtpcs_sds_get_even(sds); - int page = rtpcs_931x_sds_cmu_page_get(hw_mode); - - if (page < 0) - return -EINVAL; - - page += 1; - rtpcs_sds_write(even_sds, 0x1f, 0x02, 73); - rtpcs_sds_write_bits(even_sds, page, 0x5, 15, 15, 0x1); - - return rtpcs_sds_read_bits(even_sds, 0x1f, 0x15, 8, 3); -} - __always_unused static int rtpcs_931x_sds_link_sts_get(struct rtpcs_serdes *sds) { @@ -3527,23 +3364,23 @@ static int rtpcs_931x_sds_link_sts_get(struct rtpcs_serdes *sds) switch (sds->hw_mode) { case RTPCS_SDS_MODE_XSGMII: - sts = rtpcs_sds_read_bits(sds, 0x41, 29, 8, 0); - sts1 = rtpcs_sds_read_bits(sds, 0x81, 29, 8, 0); - latch_sts = rtpcs_sds_read_bits(sds, 0x41, 30, 8, 0); - latch_sts1 = rtpcs_sds_read_bits(sds, 0x81, 30, 8, 0); + sts = rtpcs_sds_read_bits(sds, DIGI_1(PAGE_SDS_EXT), 29, 8, 0); + sts1 = rtpcs_sds_read_bits(sds, DIGI_2(PAGE_SDS_EXT), 29, 8, 0); + latch_sts = rtpcs_sds_read_bits(sds, DIGI_1(PAGE_SDS_EXT), 30, 8, 0); + latch_sts1 = rtpcs_sds_read_bits(sds, DIGI_2(PAGE_SDS_EXT), 30, 8, 0); break; case RTPCS_SDS_MODE_SGMII: case RTPCS_SDS_MODE_2500BASEX: - sts = rtpcs_sds_read_bits(sds, 0x41, 29, 8, 0); - latch_sts = rtpcs_sds_read_bits(sds, 0x41, 30, 8, 0); + sts = rtpcs_sds_read_bits(sds, DIGI_1(PAGE_SDS_EXT), 29, 8, 0); + latch_sts = rtpcs_sds_read_bits(sds, DIGI_1(PAGE_SDS_EXT), 30, 8, 0); break; default: - sts = rtpcs_sds_read_bits(sds, 0x5, 0, 12, 12); - latch_sts = rtpcs_sds_read_bits(sds, 0x4, 1, 2, 2); - latch_sts1 = rtpcs_sds_read_bits(sds, 0x42, 1, 2, 2); - sts1 = rtpcs_sds_read_bits(sds, 0x42, 1, 2, 2); + sts = rtpcs_sds_read_bits(sds, PAGE_TGR_STD_1, 0, 12, 12); + latch_sts = rtpcs_sds_read_bits(sds, PAGE_TGR_STD_0, 1, 2, 2); + latch_sts1 = rtpcs_sds_read_bits(sds, DIGI_1(PAGE_FIB), 1, 2, 2); + sts1 = rtpcs_sds_read_bits(sds, DIGI_1(PAGE_FIB), 1, 2, 2); } pr_info("%s: serdes %d sts %d, sts1 %d, latch_sts %d, latch_sts1 %d\n", __func__, @@ -3562,17 +3399,13 @@ static int rtpcs_931x_sds_config_polarity(struct rtpcs_serdes *sds, unsigned int /* 10gr_*_inv */ val = (tx_val << 1) | rx_val; - ret = rtpcs_sds_write_bits(sds, 0x6, 0x2, 14, 13, val); + ret = rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x2, 14, 13, val); if (ret) return ret; /* xsg_*_inv */ val = (rx_val << 1) | tx_val; - ret = rtpcs_sds_write_bits(sds, 0x40, 0x0, 9, 8, val); - if (ret) - return ret; - - return rtpcs_sds_write_bits(sds, 0x80, 0x0, 9, 8, val); + return rtpcs_sds_xsg_write_bits(sds, PAGE_SDS, 0x0, 9, 8, val); } static const struct rtpcs_sds_tx_config rtpcs_931x_sds_tx_cfg_v1[] = { @@ -3627,7 +3460,7 @@ static int rtpcs_931x_sds_config_tx_amps(struct rtpcs_serdes *sds, u8 pre_amp, u cfg_val = FIELD_PREP(RTPCS_931X_SDS_PRE_AMP_MASK, pre_amp) | FIELD_PREP(RTPCS_931X_SDS_MAIN_AMP_MASK, main_amp) | FIELD_PREP(RTPCS_931X_SDS_POST_AMP_MASK, post_amp); - ret = rtpcs_sds_write(sds, 0x2e, 0x1, cfg_val); + ret = rtpcs_sds_write(sds, PAGE_ANA_10G, 0x1, cfg_val); if (ret < 0) return ret; @@ -3637,7 +3470,7 @@ static int rtpcs_931x_sds_config_tx_amps(struct rtpcs_serdes *sds, u8 pre_amp, u if (pre_amp) en_val |= BIT(1); - return rtpcs_sds_write_bits(sds, 0x2e, 0x0, 1, 0, en_val); + return rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0, 1, 0, en_val); } /** @@ -3684,8 +3517,8 @@ static int rtpcs_931x_sds_config_rx(struct rtpcs_serdes *sds, return 0; } -static int rtpcs_931x_sds_set_media(struct rtpcs_serdes *sds, enum rtpcs_sds_media sds_media, - enum rtpcs_sds_mode hw_mode) +static int rtpcs_931x_sds_config_media(struct rtpcs_serdes *sds, enum rtpcs_sds_media sds_media, + enum rtpcs_sds_mode hw_mode) { struct rtpcs_serdes *even_sds = rtpcs_sds_get_even(sds); bool is_dac, is_10g; @@ -3696,10 +3529,10 @@ static int rtpcs_931x_sds_set_media(struct rtpcs_serdes *sds, enum rtpcs_sds_med * here and later deactivated for non-10G and XSGMII. * (from DMS1250 SDK) */ - rtpcs_sds_write_bits(sds, 0x5f, 0x1, 0, 0, 0x1); + rtpcs_sds_write_bits(sds, DIGI_1(PAGE_WDIG), 0x1, 0, 0, 0x1); /* from _phy_rtl9310_sds_init */ - rtpcs_sds_write_bits(sds, 0x2e, 0xe, 13, 11, 0x0); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0xe, 13, 11, 0x0); if (hw_mode != RTPCS_SDS_MODE_XSGMII) rtpcs_931x_sds_reset_leq_dfe(sds); @@ -3710,13 +3543,13 @@ static int rtpcs_931x_sds_set_media(struct rtpcs_serdes *sds, enum rtpcs_sds_med * - the last one slightly differs in the value. Something is taken into power down * while rx_reset doesn't do this. */ - rtpcs_sds_write(sds, 0x2e, 0x12, 0x2740); - rtpcs_sds_write(sds, 0x2f, 0x0, 0x0); /* [11:6] DFE_TAP3_ODD | [5:0] DFE_TAP3_EVEN */ - rtpcs_sds_write(sds, 0x2f, 0x2, 0x2010); - rtpcs_sds_write(sds, 0x20, 0x0, 0xcd1); /* from 930x: [7:6] POWER_DOWN OF ?? */ + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x12, 0x2740); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x0, 0x0); /* [11:6] DFE_TAP3_ODD | [5:0] DFE_TAP3_EVEN */ + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x2, 0x2010); + rtpcs_sds_write(sds, PAGE_ANA_MISC, 0x0, 0xcd1); /* from 930x: [7:6] POWER_DOWN OF ?? */ - rtpcs_sds_write_bits(sds, 0x2e, 0xf, 5, 0, 0x4); - rtpcs_sds_write_bits(sds, 0x2a, 0x12, 7, 6, 0x1); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0xf, 5, 0, 0x4); + rtpcs_sds_write_bits(sds, PAGE_ANA_5G0, 0x12, 7, 6, 0x1); if (sds_media == RTPCS_SDS_MEDIA_NONE) return 0; @@ -3737,44 +3570,44 @@ static int rtpcs_931x_sds_set_media(struct rtpcs_serdes *sds, enum rtpcs_sds_med hw_mode == RTPCS_SDS_MODE_XSGMII || rtpcs_sds_mode_is_usxgmii(hw_mode)); - rtpcs_sds_write_bits(sds, 0x20, 0x0, 11, 10, 0x0); - rtpcs_sds_write_bits(sds, 0x2a, 0x7, 15, 15, is_dac ? 0x1 : 0x0); - rtpcs_sds_write_bits(sds, 0x20, 0x0, 11, 10, 0x3); + rtpcs_sds_write_bits(sds, PAGE_ANA_MISC, 0x0, 11, 10, 0x0); + rtpcs_sds_write_bits(sds, PAGE_ANA_5G0, 0x7, 15, 15, is_dac ? 0x1 : 0x0); + rtpcs_sds_write_bits(sds, PAGE_ANA_MISC, 0x0, 11, 10, 0x3); switch (sds_media) { case RTPCS_SDS_MEDIA_DAC_SHORT: case RTPCS_SDS_MEDIA_DAC_LONG: - rtpcs_sds_write(sds, 0x21, 0x19, 0xf0a5); /* from XS1930-10 SDK */ - rtpcs_sds_write(even_sds, 0x2e, 0x8, 0x02a0); /* [10:7] impedance */ + rtpcs_sds_write(sds, PAGE_ANA_COM, 0x19, 0xf0a5); /* from XS1930-10 SDK */ + rtpcs_sds_write(even_sds, PAGE_ANA_10G, 0x8, 0x02a0); /* [10:7] impedance */ break; case RTPCS_SDS_MEDIA_FIBER: if (is_10g) - rtpcs_sds_write_bits(sds, 0x2e, 0xf, 5, 0, 0x2); /* from DMS1250 SDK */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0xf, 5, 0, 0x2); /* from DMS1250 SDK */ fallthrough; default: - rtpcs_sds_write(sds, 0x21, 0x19, 0xf0f0); /* from XS1930 SDK */ - rtpcs_sds_write(even_sds, 0x2e, 0x8, 0x0294); /* [10:7] TX impedance */ + rtpcs_sds_write(sds, PAGE_ANA_COM, 0x19, 0xf0f0); /* from XS1930 SDK */ + rtpcs_sds_write(even_sds, PAGE_ANA_10G, 0x8, 0x0294); /* [10:7] TX impedance */ break; } /* CFG_LINKDW_SEL? (same semantics as 930x) */ - rtpcs_sds_write_bits(sds, 0x6, 0xd, 6, 6, is_dac ? 0x0 : 0x1); + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0xd, 6, 6, is_dac ? 0x0 : 0x1); if (is_10g) { - rtpcs_sds_write(sds, 0x2e, 0x12, 0x27c0); - rtpcs_sds_write(sds, 0x2f, 0x0, 0xc000); /* [11:6] DFE_TAP3_ODD | [5:0] DFE_TAP3_EVEN */ - rtpcs_sds_write(sds, 0x2f, 0x2, 0x6010); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x12, 0x27c0); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x0, 0xc000); /* [11:6] DFE_TAP3_ODD | [5:0] DFE_TAP3_EVEN */ + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x2, 0x6010); } /* FIXME: is this redundant with the writes below? */ - rtpcs_sds_write(sds, 0x20, 0x0, 0xc30); /* from 930x: [7:6] POWER_DOWN OF ?? */ - rtpcs_sds_write_bits(sds, 0x20, 0x0, 9, 0, 0x30); - rtpcs_sds_write_bits(sds, 0x2a, 0x12, 7, 6, 0x3); + rtpcs_sds_write(sds, PAGE_ANA_MISC, 0x0, 0xc30); /* from 930x: [7:6] POWER_DOWN OF ?? */ + rtpcs_sds_write_bits(sds, PAGE_ANA_MISC, 0x0, 9, 0, 0x30); + rtpcs_sds_write_bits(sds, PAGE_ANA_5G0, 0x12, 7, 6, 0x3); - rtpcs_sds_write_bits(sds, 0x20, 0x0, 11, 10, 0x1); - rtpcs_sds_write_bits(sds, 0x20, 0x0, 11, 10, 0x3); + rtpcs_sds_write_bits(sds, PAGE_ANA_MISC, 0x0, 11, 10, 0x1); + rtpcs_sds_write_bits(sds, PAGE_ANA_MISC, 0x0, 11, 10, 0x3); /* clear pending SerDes RX idle interrupt flag */ regmap_write_bits(sds->ctrl->map, RTPCS_931X_ISR_SERDES_RXIDLE, @@ -3782,17 +3615,17 @@ static int rtpcs_931x_sds_set_media(struct rtpcs_serdes *sds, enum rtpcs_sds_med /* Gating as mentioned above, deactivated here for non-10G and XSGMII */ if (!is_10g || hw_mode == RTPCS_SDS_MODE_XSGMII) - rtpcs_sds_write_bits(sds, 0x5f, 0x1, 0, 0, 0x0); + rtpcs_sds_write_bits(sds, DIGI_1(PAGE_WDIG), 0x1, 0, 0, 0x0); return 0; } static int rtpcs_931x_sds_config_fiber_1g(struct rtpcs_serdes *sds) { - rtpcs_sds_write_bits(sds, 0x43, 0x12, 15, 14, 0x0); + rtpcs_sds_write_bits(sds, DIGI_1(PAGE_FIB_EXT), 0x12, 15, 14, 0x0); - rtpcs_sds_write_bits(sds, 0x42, 0x0, 6, 6, 0x1); - rtpcs_sds_write_bits(sds, 0x42, 0x0, 13, 13, 0x0); + rtpcs_sds_write_bits(sds, DIGI_1(PAGE_FIB), 0x0, 6, 6, 0x1); + rtpcs_sds_write_bits(sds, DIGI_1(PAGE_FIB), 0x0, 13, 13, 0x0); return 0; } @@ -3809,31 +3642,27 @@ static int rtpcs_931x_sds_config_hw_mode(struct rtpcs_serdes *sds, break; case RTPCS_SDS_MODE_2500BASEX: - rtpcs_sds_write_bits(sds, 0x41, 0x14, 8, 8, 1); + rtpcs_sds_write_bits(sds, DIGI_1(PAGE_SDS_EXT), 0x14, 8, 8, 1); break; case RTPCS_SDS_MODE_10GBASER: /* 10GR1000BX_AUTO */ /* configure 10GR fiber mode=1 */ - rtpcs_sds_write_bits(sds, 0x1f, 0xb, 1, 1, 1); + rtpcs_sds_write_bits(sds, PAGE_WDIG, 0xb, 1, 1, 1); rtpcs_931x_sds_config_fiber_1g(sds); /* init auto */ - rtpcs_sds_write_bits(sds, 0x1f, 13, 15, 0, 0x109e); - rtpcs_sds_write_bits(sds, 0x1f, 0x6, 14, 10, 0x8); - rtpcs_sds_write_bits(sds, 0x1f, 0x7, 10, 4, 0x7f); + rtpcs_sds_write_bits(sds, PAGE_WDIG, 13, 15, 0, 0x109e); + rtpcs_sds_write_bits(sds, PAGE_WDIG, 0x6, 14, 10, 0x8); + rtpcs_sds_write_bits(sds, PAGE_WDIG, 0x7, 10, 4, 0x7f); break; case RTPCS_SDS_MODE_SGMII: - rtpcs_sds_write_bits(sds, 0x24, 0x9, 15, 15, 0); - - /* TODO: where does this come from? SDK doesn't have this. */ - rtpcs_931x_sds_cmu_band_set(sds, true, 62, RTPCS_SDS_MODE_SGMII); + rtpcs_sds_write_bits(sds, PAGE_ANA_1G2, 0x9, 15, 15, 0); break; case RTPCS_SDS_MODE_XSGMII: - rtpcs_sds_write_bits(sds, 0x40, 0xE, 12, 12, 1); - rtpcs_sds_write_bits(sds, 0x80, 0xE, 12, 12, 1); + rtpcs_sds_xsg_write_bits(sds, PAGE_SDS, 0xe, 12, 12, 0x1); break; case RTPCS_SDS_MODE_USXGMII_10GSXGMII: @@ -3845,7 +3674,7 @@ static int rtpcs_931x_sds_config_hw_mode(struct rtpcs_serdes *sds, rtpcs_931x_sds_reset_leq_dfe(sds); rtpcs_931x_sds_rx_reset(sds); - rtpcs_93xx_sds_usxgmii_config(sds, 0x03, 0xa4, 0, 1, 0x1); + rtpcs_93xx_sds_usxgmii_config(sds, RTPCS_USXGMII_AN_OPC_STD, 0xa4, 0, 1, 0x1); break; case RTPCS_SDS_MODE_QSGMII: @@ -3853,51 +3682,7 @@ static int rtpcs_931x_sds_config_hw_mode(struct rtpcs_serdes *sds, return -ENOTSUPP; } - return 0; -} - -static int rtpcs_931x_setup_serdes(struct rtpcs_serdes *sds, - enum rtpcs_sds_mode hw_mode) -{ - struct rtpcs_ctrl *ctrl = sds->ctrl; - enum rtpcs_sds_media sds_media; - int ret; - - ret = rtpcs_931x_sds_config_hw_mode(sds, hw_mode); - if (ret < 0) - return ret; - - ret = rtpcs_93xx_sds_config_cmu(sds, hw_mode); - if (ret < 0) - return ret; - - switch (hw_mode) { - case RTPCS_SDS_MODE_OFF: - sds_media = RTPCS_SDS_MEDIA_NONE; - break; - case RTPCS_SDS_MODE_SGMII: - case RTPCS_SDS_MODE_1000BASEX: - case RTPCS_SDS_MODE_2500BASEX: - case RTPCS_SDS_MODE_10GBASER: - sds_media = RTPCS_SDS_MEDIA_FIBER; - break; - default: - sds_media = RTPCS_SDS_MEDIA_PCB; - break; - } - ret = rtpcs_931x_sds_set_media(sds, sds_media, hw_mode); - if (ret < 0) { - dev_err(ctrl->dev, "failed to config SerDes for media: %d\n", ret); - return ret; - } - - ret = rtpcs_931x_sds_set_mode(sds, hw_mode); - if (ret < 0) - return ret; - - sds->hw_mode = hw_mode; - - return 0; + return rtpcs_93xx_sds_config_cmu(sds, hw_mode); } /** @@ -4099,10 +3884,11 @@ static int rtpcs_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, struct rtpcs_link *link = rtpcs_phylink_pcs_to_link(pcs); struct rtpcs_ctrl *ctrl = link->ctrl; struct rtpcs_serdes *sds = link->sds; + enum rtpcs_sds_media sds_media; enum rtpcs_sds_mode hw_mode; int ret; - ret = rtpcs_sds_determine_hw_mode(sds, interface, &hw_mode); + ret = rtpcs_sds_select_hw_mode(sds, interface, &hw_mode); if (ret < 0) { dev_err(ctrl->dev, "SerDes %u doesn't support %s mode\n", sds->id, phy_modes(interface)); @@ -4125,10 +3911,28 @@ static int rtpcs_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, if (ret < 0) return ret; - ret = ctrl->cfg->setup_serdes(sds, hw_mode); + ret = sds->ops->config_hw_mode(sds, hw_mode); if (ret < 0) return ret; + if (sds->ops->config_media) { + ret = rtpcs_sds_select_media(hw_mode, &sds_media); + if (ret < 0) + return ret; + + sds->media = sds_media; + + ret = sds->ops->config_media(sds, sds_media, hw_mode); + if (ret < 0) + return ret; + } + + ret = sds->ops->set_hw_mode(sds, hw_mode); + if (ret < 0) + return ret; + + sds->hw_mode = hw_mode; + ret = sds->ops->activate(sds); if (ret < 0) return ret; @@ -4418,13 +4222,15 @@ static const struct rtpcs_sds_ops rtpcs_838x_sds_ops = { .restart_autoneg = rtpcs_generic_sds_restart_autoneg, .deactivate = rtpcs_838x_sds_deactivate, .activate = rtpcs_838x_sds_activate, + .config_hw_mode = rtpcs_838x_sds_config_hw_mode, + .set_hw_mode = rtpcs_838x_sds_set_mode, .post_config = rtpcs_838x_sds_post_config, }; static const struct rtpcs_sds_regs rtpcs_838x_sds_regs = { - .an_enable = { .page = 0x2, .reg = MII_BMCR, .msb = 12, .lsb = 12 }, - .an_restart = { .page = 0x2, .reg = MII_BMCR, .msb = 9, .lsb = 9 }, - .an_advertise = { .page = 0x2, .reg = MII_ADVERTISE, .msb = 15, .lsb = 0 }, + .an_enable = { .page = PAGE_FIB, .reg = MII_BMCR, .msb = 12, .lsb = 12 }, + .an_restart = { .page = PAGE_FIB, .reg = MII_BMCR, .msb = 9, .lsb = 9 }, + .an_advertise = { .page = PAGE_FIB, .reg = MII_ADVERTISE, .msb = 15, .lsb = 0 }, }; static const struct rtpcs_config rtpcs_838x_cfg = { @@ -4442,7 +4248,6 @@ static const struct rtpcs_config rtpcs_838x_cfg = { .sds_hw_mode_vals = rtpcs_838x_sds_hw_mode_vals, .init = rtpcs_838x_init, .sds_probe = rtpcs_838x_sds_probe, - .setup_serdes = rtpcs_838x_setup_serdes, }; static const struct phylink_pcs_ops rtpcs_839x_pcs_ops = { @@ -4458,12 +4263,14 @@ static const struct rtpcs_sds_ops rtpcs_839x_sds_ops = { .restart_autoneg = rtpcs_generic_sds_restart_autoneg, .deactivate = rtpcs_839x_sds_deactivate, .activate = rtpcs_839x_sds_activate, + .config_hw_mode = rtpcs_839x_sds_config_hw_mode, + .set_hw_mode = rtpcs_sds_set_mac_mode, }; static const struct rtpcs_sds_regs rtpcs_839x_sds_regs = { - .an_enable = { .page = 0x2, .reg = MII_BMCR, .msb = 12, .lsb = 12 }, - .an_restart = { .page = 0x2, .reg = MII_BMCR, .msb = 9, .lsb = 9 }, - .an_advertise = { .page = 0x2, .reg = MII_ADVERTISE, .msb = 15, .lsb = 0 }, + .an_enable = { .page = PAGE_FIB, .reg = MII_BMCR, .msb = 12, .lsb = 12 }, + .an_restart = { .page = PAGE_FIB, .reg = MII_BMCR, .msb = 9, .lsb = 9 }, + .an_advertise = { .page = PAGE_FIB, .reg = MII_ADVERTISE, .msb = 15, .lsb = 0 }, }; static const struct rtpcs_config rtpcs_839x_cfg = { @@ -4481,7 +4288,6 @@ static const struct rtpcs_config rtpcs_839x_cfg = { .sds_hw_mode_vals = rtpcs_839x_sds_hw_mode_vals, .init = rtpcs_839x_init, .sds_probe = rtpcs_839x_sds_probe, - .setup_serdes = rtpcs_839x_setup_serdes, }; static const struct phylink_pcs_ops rtpcs_930x_pcs_ops = { @@ -4503,13 +4309,16 @@ static const struct rtpcs_sds_ops rtpcs_930x_sds_ops = { .config_polarity = rtpcs_930x_sds_config_polarity, .deactivate = rtpcs_930x_sds_deactivate, .activate = rtpcs_930x_sds_activate, + .config_hw_mode = rtpcs_930x_sds_config_hw_mode, + .set_hw_mode = rtpcs_930x_sds_set_mode, + .config_media = rtpcs_930x_sds_config_media, .post_config = rtpcs_930x_sds_post_config, }; static const struct rtpcs_sds_regs rtpcs_930x_sds_regs = { - .an_enable = { .page = 0x2, .reg = MII_BMCR, .msb = 12, .lsb = 12 }, - .an_restart = { .page = 0x2, .reg = MII_BMCR, .msb = 9, .lsb = 9 }, - .an_advertise = { .page = 0x2, .reg = MII_ADVERTISE, .msb = 15, .lsb = 0 }, + .an_enable = { .page = PAGE_FIB, .reg = MII_BMCR, .msb = 12, .lsb = 12 }, + .an_restart = { .page = PAGE_FIB, .reg = MII_BMCR, .msb = 9, .lsb = 9 }, + .an_advertise = { .page = PAGE_FIB, .reg = MII_ADVERTISE, .msb = 15, .lsb = 0 }, }; static const struct rtpcs_config rtpcs_930x_cfg = { @@ -4527,7 +4336,6 @@ static const struct rtpcs_config rtpcs_930x_cfg = { .sds_hw_mode_vals = rtpcs_93xx_sds_hw_mode_vals, .init = rtpcs_93xx_init, .sds_probe = rtpcs_930x_sds_probe, - .setup_serdes = rtpcs_930x_setup_serdes, }; static const struct phylink_pcs_ops rtpcs_931x_pcs_ops = { @@ -4548,12 +4356,15 @@ static const struct rtpcs_sds_ops rtpcs_931x_sds_ops = { .config_polarity = rtpcs_931x_sds_config_polarity, .deactivate = rtpcs_931x_sds_deactivate, .activate = rtpcs_931x_sds_activate, + .config_hw_mode = rtpcs_931x_sds_config_hw_mode, + .set_hw_mode = rtpcs_931x_sds_set_mode, + .config_media = rtpcs_931x_sds_config_media, }; static const struct rtpcs_sds_regs rtpcs_931x_sds_regs = { - .an_enable = { .page = 0x42, .reg = MII_BMCR, .msb = 12, .lsb = 12 }, - .an_restart = { .page = 0x42, .reg = MII_BMCR, .msb = 9, .lsb = 9 }, - .an_advertise = { .page = 0x42, .reg = MII_ADVERTISE, .msb = 15, .lsb = 0 }, + .an_enable = { .page = DIGI_1(PAGE_FIB), .reg = MII_BMCR, .msb = 12, .lsb = 12 }, + .an_restart = { .page = DIGI_1(PAGE_FIB), .reg = MII_BMCR, .msb = 9, .lsb = 9 }, + .an_advertise = { .page = DIGI_1(PAGE_FIB), .reg = MII_ADVERTISE, .msb = 15, .lsb = 0 }, }; static const struct rtpcs_config rtpcs_931x_cfg = { @@ -4571,7 +4382,6 @@ static const struct rtpcs_config rtpcs_931x_cfg = { .sds_hw_mode_vals = rtpcs_93xx_sds_hw_mode_vals, .init = rtpcs_931x_init, .sds_probe = rtpcs_931x_sds_probe, - .setup_serdes = rtpcs_931x_setup_serdes, }; static const struct of_device_id rtpcs_of_match[] = { diff --git a/target/linux/realtek/files-6.18/net/dsa/tag_rtl_otto.c b/target/linux/realtek/files-6.18/net/dsa/tag_rtl_otto.c index 08a9915584..ecbf67b42a 100644 --- a/target/linux/realtek/files-6.18/net/dsa/tag_rtl_otto.c +++ b/target/linux/realtek/files-6.18/net/dsa/tag_rtl_otto.c @@ -1,8 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -/* - * net/dsa/tag_trailer.c - Trailer tag format handling - * Copyright (c) 2008-2009 Marvell Semiconductor - */ #include #include @@ -10,63 +6,38 @@ #include "tag.h" -#define RTL_OTTO_NAME "rtl_otto" - -/* - * TODO: This driver was copied over from trailer tagging. It will be developed - * downstream in OpenWrt in conjunction with the Realtek Otto ethernet driver. - * For now rely on the old trailer handling and keep everything as is. - */ +#define RTL_OTTO_NAME "rtl_otto" +#define RTL_OTTO_TAILROOM 4 static struct sk_buff *rtl_otto_xmit(struct sk_buff *skb, struct net_device *dev) { struct dsa_port *dp = dsa_user_to_port(dev); u8 *trailer; - trailer = skb_put(skb, 4); - trailer[0] = 0x80; - trailer[1] = dp->index; - trailer[2] = 0x10; - trailer[3] = 0x00; + /* Hardware needs space for Layer 2 FCS. Align tag size with that. */ + trailer = skb_put(skb, RTL_OTTO_TAILROOM); + trailer[0] = dp->index; + trailer[1] = 0xab; + trailer[2] = 0xcd; + trailer[3] = 0xef; return skb; } static struct sk_buff *rtl_otto_rcv(struct sk_buff *skb, struct net_device *dev) { - u8 *trailer; - int source_port; - - if (skb_linearize(skb)) - return NULL; - - trailer = skb_tail_pointer(skb) - 4; - - if (trailer[0] != 0x80 || (trailer[1] & 0x80) != 0x00 || - (trailer[2] & 0xef) != 0x00 || trailer[3] != 0x00) - return NULL; - - if (trailer[1] & 0x40) - skb->offload_fwd_mark = 1; - - source_port = trailer[1] & 0x3f; - - skb->dev = dsa_conduit_find_user(dev, 0, source_port); - if (!skb->dev) - return NULL; - - if (pskb_trim_rcsum(skb, skb->len - 4)) - return NULL; + /* RX path uses METADATA_HW_PORT_MUX. This function just makes netdev_uses_dsa() happy. */ + netdev_err(dev, "ethernet driver did not set METADATA\n"); return skb; } static const struct dsa_device_ops rtl_otto_netdev_ops = { - .name = RTL_OTTO_NAME, - .proto = DSA_TAG_PROTO_RTL_OTTO, - .xmit = rtl_otto_xmit, - .rcv = rtl_otto_rcv, - .needed_tailroom = 4, + .name = RTL_OTTO_NAME, + .proto = DSA_TAG_PROTO_RTL_OTTO, + .xmit = rtl_otto_xmit, + .rcv = rtl_otto_rcv, + .needed_tailroom = RTL_OTTO_TAILROOM, }; MODULE_DESCRIPTION("DSA tag driver for Realtek Otto switches (RTL83xx/RTL93xx)"); diff --git a/target/linux/realtek/image/common.mk b/target/linux/realtek/image/common.mk index 3a820fec43..6975654395 100644 --- a/target/linux/realtek/image/common.mk +++ b/target/linux/realtek/image/common.mk @@ -101,6 +101,16 @@ define Device/zyxel_gs1900 check-size 6976k endef +define Device/zyxel_xgs1010-12 + SOC := rtl9302 + UIMAGE_MAGIC := 0x93001010 + DEVICE_VENDOR := Zyxel + DEVICE_MODEL := XGS1010-12 + KERNEL_SIZE := 7168k + IMAGE_SIZE := 13184k + $(Device/kernel-lzma) +endef + define Device/zyxel_xgs1210-12 SOC := rtl9302 UIMAGE_MAGIC := 0x93001210 diff --git a/target/linux/realtek/image/rt-loader/Makefile b/target/linux/realtek/image/rt-loader/Makefile index 198506bce8..90f8349c96 100644 --- a/target/linux/realtek/image/rt-loader/Makefile +++ b/target/linux/realtek/image/rt-loader/Makefile @@ -73,7 +73,7 @@ LD := $(CROSS_COMPILE)ld OBJCOPY := $(CROSS_COMPILE)objcopy OBJDUMP := $(CROSS_COMPILE)objdump -CFLAGS = -fpic -mabicalls -O2 -fno-builtin-printf -Iinclude +CFLAGS = -fpic -mabicalls -O3 -fno-builtin-printf -Iinclude CFLAGS += -DFLASH_ADDR=$(FLASH_ADDR) CFLAGS += -DKERNEL_ADDR=$(KERNEL_ADDR) diff --git a/target/linux/realtek/image/rtl838x.mk b/target/linux/realtek/image/rtl838x.mk index 52a0f1bb46..73e282b6ed 100644 --- a/target/linux/realtek/image/rtl838x.mk +++ b/target/linux/realtek/image/rtl838x.mk @@ -353,6 +353,17 @@ define Device/tplink_sg2008p-v1 endef TARGET_DEVICES += tplink_sg2008p-v1 +define Device/tplink_sg2008p-v3 + SOC := rtl8380 + KERNEL_SIZE := 6m + IMAGE_SIZE := 26m + DEVICE_VENDOR := TP-Link + DEVICE_MODEL := SG2008P + DEVICE_VARIANT := v3 + DEVICE_PACKAGES := i2c-tools +endef +TARGET_DEVICES += tplink_sg2008p-v3 + define Device/tplink_sg2210p-v3 SOC := rtl8380 KERNEL_SIZE := 6m diff --git a/target/linux/realtek/image/rtl930x.mk b/target/linux/realtek/image/rtl930x.mk index 9b01f629ac..e58020551b 100644 --- a/target/linux/realtek/image/rtl930x.mk +++ b/target/linux/realtek/image/rtl930x.mk @@ -97,6 +97,17 @@ define Device/horaco_zx-swtgw2c8f endef TARGET_DEVICES += horaco_zx-swtgw2c8f +define Device/nicgiga_s100-0800s-m + SOC := rtl9303 + UIMAGE_MAGIC := 0x93030000 + DEVICE_VENDOR := NicGiga + DEVICE_MODEL := S100-0800S-M + DEVICE_PACKAGES := kmod-gpio-pca953x + IMAGE_SIZE := 29696k + $(Device/kernel-lzma) +endef +TARGET_DEVICES += nicgiga_s100-0800s-m + define Device/plasmacloud-common SOC := rtl9302 UIMAGE_MAGIC := 0x93000000 @@ -261,17 +272,17 @@ endef TARGET_DEVICES += xikestor_sks8310-8x define Device/zyxel_xgs1010-12-a1 - SOC := rtl9302 - UIMAGE_MAGIC := 0x93001010 - DEVICE_VENDOR := Zyxel - DEVICE_MODEL := XGS1010-12 + $(Device/zyxel_xgs1010-12) DEVICE_VARIANT := A1 - KERNEL_SIZE := 7168k - IMAGE_SIZE := 13184k - $(Device/kernel-lzma) endef TARGET_DEVICES += zyxel_xgs1010-12-a1 +define Device/zyxel_xgs1010-12-b1 + $(Device/zyxel_xgs1010-12) + DEVICE_VARIANT := B1 +endef +TARGET_DEVICES += zyxel_xgs1010-12-b1 + define Device/zyxel_xgs1210-12-a1 $(Device/zyxel_xgs1210-12) SUPPORTED_DEVICES += zyxel,xgs1210-12 diff --git a/target/linux/realtek/image/rtl931x.mk b/target/linux/realtek/image/rtl931x.mk index 865ef551a9..3d6607a1f0 100644 --- a/target/linux/realtek/image/rtl931x.mk +++ b/target/linux/realtek/image/rtl931x.mk @@ -2,6 +2,16 @@ include ./common.mk +define Device/hasivo_f5800w-12s-plus + SOC := rtl9313 + DEVICE_VENDOR := Hasivo + DEVICE_MODEL := F5800W-12S+ + IMAGE_SIZE := 29696k + DEVICE_PACKAGES := kmod-hasivo-mcu-wdt kmod-hasivo-mcu-sensor kmod-rtc-pcf8563 + $(Device/kernel-lzma) +endef +TARGET_DEVICES += hasivo_f5800w-12s-plus + define Device/plasmacloud-common SOC := rtl9312 UIMAGE_MAGIC := 0x93100000 diff --git a/target/linux/realtek/patches-6.18/705-v7.1-net-sfp-initialize-i2c_block_size-at-adapter-configu.patch b/target/linux/realtek/patches-6.18/705-v7.1-net-sfp-initialize-i2c_block_size-at-adapter-configu.patch new file mode 100644 index 0000000000..534d15a6fa --- /dev/null +++ b/target/linux/realtek/patches-6.18/705-v7.1-net-sfp-initialize-i2c_block_size-at-adapter-configu.patch @@ -0,0 +1,41 @@ +From 56d0885514491e5ed8f7593400879ab77c52504c Mon Sep 17 00:00:00 2001 +From: Jonas Jelonek +Date: Thu, 28 May 2026 20:52:40 +0000 +Subject: [PATCH] net: sfp: initialize i2c_block_size at adapter configure time + +sfp->i2c_block_size is only assigned in sfp_sm_mod_probe(), which runs +from the state machine timer after SFP_F_PRESENT has been set. Between +those two points, sfp_module_eeprom() (the ethtool -m callback) gates +only on SFP_F_PRESENT and can be entered with i2c_block_size still at +its kzalloc'd value of 0. + +On a pure-I2C adapter, sfp_i2c_read() then issues an i2c_transfer() +with msgs[1].len = 0 inside a loop that subtracts this_len from len +each iteration; on adapters that succeed a zero-length read the loop +never advances, spinning while holding rtnl_lock. + +This was previously addressed by initializing i2c_block_size in +sfp_alloc() (commit 813c2dd78618), but the initialization was dropped +when i2c_block_size was split from i2c_max_block_size. + +Initialize sfp->i2c_block_size from sfp->i2c_max_block_size in +sfp_i2c_configure(), so the field is valid as soon as the adapter is +known. sfp_sm_mod_probe() still reassigns it on each module insertion +to recover from a per-module clamp to 1 (sfp_id_needs_byte_io). + +Fixes: 7662abf4db94 ("net: phy: sfp: Add support for SMBus module access") +Cc: stable@vger.kernel.org +Signed-off-by: Jonas Jelonek +Link: https://patch.msgid.link/20260528205242.971410-2-jelonek.jonas@gmail.com +Signed-off-by: Jakub Kicinski + +--- a/drivers/net/phy/sfp.c ++++ b/drivers/net/phy/sfp.c +@@ -1815,6 +1815,7 @@ static int sfp_hwmon_insert(struct sfp * + sfp->hwmon_tries = R_PROBE_RETRY_SLOW; + } + ++ sfp->i2c_block_size = sfp->i2c_max_block_size; + return 0; + } + diff --git a/target/linux/realtek/patches-6.18/741-net-sfp-apply-I2C-adapter-quirks-to-limit-blocks.patch b/target/linux/realtek/patches-6.18/706-01-v7.2-net-sfp-apply-I2C-adapter-quirks-to-limit-block-size.patch similarity index 79% rename from target/linux/realtek/patches-6.18/741-net-sfp-apply-I2C-adapter-quirks-to-limit-blocks.patch rename to target/linux/realtek/patches-6.18/706-01-v7.2-net-sfp-apply-I2C-adapter-quirks-to-limit-block-size.patch index 7e575141d2..d2ce503e81 100644 --- a/target/linux/realtek/patches-6.18/741-net-sfp-apply-I2C-adapter-quirks-to-limit-blocks.patch +++ b/target/linux/realtek/patches-6.18/706-01-v7.2-net-sfp-apply-I2C-adapter-quirks-to-limit-block-size.patch @@ -1,8 +1,7 @@ -From 572304faf8c1d30f142060c76a3e731438fc5975 Mon Sep 17 00:00:00 2001 +From f2a138abfb719a3bfd370ca79f00055ec81e4f59 Mon Sep 17 00:00:00 2001 From: Jonas Jelonek -Date: Thu, 22 Jan 2026 10:59:20 +0000 -Subject: [PATCH net-next v6 1/2] net: sfp: apply I2C adapter quirks to limit - block size +Date: Sun, 14 Jun 2026 13:34:17 +0000 +Subject: [PATCH 1/2] net: sfp: apply I2C adapter quirks to limit block size The SFP driver assumes all I2C adapters support reading and writing the pre-defined block size SFP_EEPROM_BLOCK_SIZE of 16 bytes. This constant @@ -19,13 +18,13 @@ max_read_len and max_write_len in struct i2c_adapter_quirks into account to further limit the maximum block size if needed. Signed-off-by: Jonas Jelonek ---- - drivers/net/phy/sfp.c | 12 ++++++++++-- - 1 file changed, 10 insertions(+), 2 deletions(-) +Reviewed-by: Maxime Chevallier +Link: https://patch.msgid.link/20260614133418.2068201-2-jelonek.jonas@gmail.com +Signed-off-by: Jakub Kicinski --- a/drivers/net/phy/sfp.c +++ b/drivers/net/phy/sfp.c -@@ -809,21 +809,29 @@ static int sfp_smbus_byte_write(struct s +@@ -826,21 +826,29 @@ static int sfp_smbus_byte_write(struct s static int sfp_i2c_configure(struct sfp *sfp, struct i2c_adapter *i2c) { @@ -54,6 +53,6 @@ Signed-off-by: Jonas Jelonek + max_block_size = min(max_block_size, i2c->quirks->max_write_len); + + sfp->i2c_max_block_size = max_block_size; + sfp->i2c_block_size = sfp->i2c_max_block_size; return 0; } - diff --git a/target/linux/realtek/patches-6.18/706-02-v7.2-net-sfp-extend-SMBus-support.patch b/target/linux/realtek/patches-6.18/706-02-v7.2-net-sfp-extend-SMBus-support.patch new file mode 100644 index 0000000000..c00c0d8580 --- /dev/null +++ b/target/linux/realtek/patches-6.18/706-02-v7.2-net-sfp-extend-SMBus-support.patch @@ -0,0 +1,249 @@ +From 58b29bdf6186a8c3f2d725619c0b17cf602ac4e0 Mon Sep 17 00:00:00 2001 +From: Jonas Jelonek +Date: Sun, 14 Jun 2026 13:34:18 +0000 +Subject: [PATCH 2/2] net: sfp: extend SMBus support + +Commit 7662abf4db94 ("net: phy: sfp: Add support for SMBus module access") +added SMBus access for SFP modules, but limited it to single-byte +transfers. As a side effect, hwmon is disabled (16-bit reads cannot be +guaranteed atomic) and a warning is printed. + +Many SMBus-only I2C controllers in the wild support more than just +byte access, and SFP cages are often wired to such controllers +rather than to a full-featured I2C controller -- e.g. the SMBus +controllers in the Realtek longan and mango SoCs, which advertise +word access and I2C block reads. Today, they cannot drive an SFP at +all without falling back to the byte-only path. + +Extend sfp_smbus_read()/sfp_smbus_write() so that, in addition to +the existing byte access, they also use SMBus word access and SMBus +I2C block access whenever the adapter advertises them. Both +directions are handled in a single read and a single write helper +that pick the largest supported transfer per chunk and fall back as +needed. + +I2C-block is preferred unconditionally when available: the protocol +carries any length 1..32, so it can serve every chunk -- including +the 1- and 2-byte tails -- without help from word or byte access. +Note that this requires I2C_FUNC_SMBUS_I2C_BLOCK, which reads a +caller-specified number of bytes. This deviates from the official +SMBus Block Read (length is supplied by the slave) but is widely +supported by Linux I2C controllers/drivers. + +Capability matrix this implementation supports: + + - BYTE only: works (unchanged behaviour); 1-byte + xfers, hwmon disabled. + - BYTE + WORD: word for >=2-byte chunks, byte for + trailing odd byte. + - I2C_BLOCK present (with or + without BYTE/WORD): block as the universal transport for + every chunk. + - WORD only (no BYTE/BLOCK): accepted with WARN_ONCE. Even-length + transfers work; odd-length transfers + (e.g. the 3-byte cotsworks fixup + write) hit the BYTE branch which the + adapter does not implement, so the + xfer returns an error and the + operation is aborted. No mainline + I2C driver was found to advertise + WORD without BYTE; the warning lets + us learn about it if it ever shows + up. + +Adapters with asymmetric R/W capabilities (e.g. only READ_I2C_BLOCK +but not WRITE_I2C_BLOCK) remain functionally correct -- the +per-iteration fallback uses the direction-specific bits -- but the +shared i2c_max_block_size is sized by the all-bits-set check, so a +transfer in the better-supported direction is not upgraded. None of +the mainline I2C bus drivers surveyed during review advertise such +asymmetry; promoting i2c_max_block_size to per-direction sizes can +be revisited if needed. + +Signed-off-by: Jonas Jelonek +Reviewed-by: Maxime Chevallier +Link: https://patch.msgid.link/20260614133418.2068201-3-jelonek.jonas@gmail.com +Signed-off-by: Jakub Kicinski + +--- a/drivers/net/phy/sfp.c ++++ b/drivers/net/phy/sfp.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include + + #include "sfp.h" +@@ -775,50 +776,113 @@ static int sfp_i2c_write(struct sfp *sfp + return ret == ARRAY_SIZE(msgs) ? len : 0; + } + +-static int sfp_smbus_byte_read(struct sfp *sfp, bool a2, u8 dev_addr, +- void *buf, size_t len) ++static int sfp_smbus_read(struct sfp *sfp, bool a2, u8 dev_addr, void *buf, ++ size_t len) + { +- union i2c_smbus_data smbus_data; ++ union i2c_smbus_data smbus_data = {0}; + u8 bus_addr = a2 ? 0x51 : 0x50; ++ size_t this_len, transferred; ++ u32 functionality; + u8 *data = buf; + int ret; + +- while (len) { +- ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, +- I2C_SMBUS_READ, dev_addr, +- I2C_SMBUS_BYTE_DATA, &smbus_data); +- if (ret < 0) +- return ret; ++ functionality = i2c_get_functionality(sfp->i2c); + +- *data = smbus_data.byte; ++ while (len) { ++ this_len = min(len, sfp->i2c_block_size); + +- len--; +- data++; +- dev_addr++; ++ if (functionality & I2C_FUNC_SMBUS_READ_I2C_BLOCK) { ++ smbus_data.block[0] = this_len; ++ ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, ++ I2C_SMBUS_READ, dev_addr, ++ I2C_SMBUS_I2C_BLOCK_DATA, &smbus_data); ++ if (ret < 0) ++ return ret; ++ ++ transferred = min_t(size_t, smbus_data.block[0], this_len); ++ if (!transferred) ++ return -EIO; ++ ++ memcpy(data, &smbus_data.block[1], transferred); ++ } else if (this_len >= 2 && ++ (functionality & I2C_FUNC_SMBUS_READ_WORD_DATA)) { ++ ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, ++ I2C_SMBUS_READ, dev_addr, ++ I2C_SMBUS_WORD_DATA, &smbus_data); ++ if (ret < 0) ++ return ret; ++ ++ put_unaligned_le16(smbus_data.word, data); ++ transferred = 2; ++ } else { ++ ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, ++ I2C_SMBUS_READ, dev_addr, ++ I2C_SMBUS_BYTE_DATA, &smbus_data); ++ if (ret < 0) ++ return ret; ++ ++ *data = smbus_data.byte; ++ transferred = 1; ++ } ++ ++ data += transferred; ++ len -= transferred; ++ dev_addr += transferred; + } + + return data - (u8 *)buf; + } + +-static int sfp_smbus_byte_write(struct sfp *sfp, bool a2, u8 dev_addr, +- void *buf, size_t len) ++static int sfp_smbus_write(struct sfp *sfp, bool a2, u8 dev_addr, void *buf, ++ size_t len) + { + union i2c_smbus_data smbus_data; + u8 bus_addr = a2 ? 0x51 : 0x50; ++ size_t this_len, transferred; ++ u32 functionality; + u8 *data = buf; + int ret; + ++ functionality = i2c_get_functionality(sfp->i2c); ++ + while (len) { +- smbus_data.byte = *data; +- ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, +- I2C_SMBUS_WRITE, dev_addr, +- I2C_SMBUS_BYTE_DATA, &smbus_data); +- if (ret) +- return ret; ++ this_len = min(len, sfp->i2c_block_size); + +- len--; +- data++; +- dev_addr++; ++ if (functionality & I2C_FUNC_SMBUS_WRITE_I2C_BLOCK) { ++ smbus_data.block[0] = this_len; ++ memcpy(&smbus_data.block[1], data, this_len); ++ ++ ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, ++ I2C_SMBUS_WRITE, dev_addr, ++ I2C_SMBUS_I2C_BLOCK_DATA, &smbus_data); ++ if (ret < 0) ++ return ret; ++ ++ transferred = this_len; ++ } else if (this_len >= 2 && ++ (functionality & I2C_FUNC_SMBUS_WRITE_WORD_DATA)) { ++ smbus_data.word = get_unaligned_le16(data); ++ ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, ++ I2C_SMBUS_WRITE, dev_addr, ++ I2C_SMBUS_WORD_DATA, &smbus_data); ++ if (ret < 0) ++ return ret; ++ ++ transferred = 2; ++ } else { ++ smbus_data.byte = *data; ++ ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, ++ I2C_SMBUS_WRITE, dev_addr, ++ I2C_SMBUS_BYTE_DATA, &smbus_data); ++ if (ret < 0) ++ return ret; ++ ++ transferred = 1; ++ } ++ ++ data += transferred; ++ len -= transferred; ++ dev_addr += transferred; + } + + return data - (u8 *)buf; +@@ -834,10 +898,29 @@ static int sfp_i2c_configure(struct sfp + sfp->read = sfp_i2c_read; + sfp->write = sfp_i2c_write; + max_block_size = SFP_EEPROM_BLOCK_SIZE; +- } else if (i2c_check_functionality(i2c, I2C_FUNC_SMBUS_BYTE_DATA)) { +- sfp->read = sfp_smbus_byte_read; +- sfp->write = sfp_smbus_byte_write; +- max_block_size = 1; ++ } else if (i2c_check_functionality(i2c, I2C_FUNC_SMBUS_BYTE_DATA) || ++ i2c_check_functionality(i2c, I2C_FUNC_SMBUS_I2C_BLOCK)) { ++ /* Either protocol alone covers any length: I2C-block carries ++ * 1..32 bytes per xfer, byte iterates one byte at a time. ++ */ ++ sfp->read = sfp_smbus_read; ++ sfp->write = sfp_smbus_write; ++ ++ if (i2c_check_functionality(i2c, I2C_FUNC_SMBUS_I2C_BLOCK)) ++ max_block_size = SFP_EEPROM_BLOCK_SIZE; ++ else if (i2c_check_functionality(i2c, I2C_FUNC_SMBUS_WORD_DATA)) ++ max_block_size = 2; ++ else ++ max_block_size = 1; ++ } else if (WARN_ONCE(i2c_check_functionality(i2c, I2C_FUNC_SMBUS_WORD_DATA), ++ "SMBus word-only adapter; odd-length transfers will fail\n")) { ++ /* Word-only: even-length xfers work; odd-length xfers fall ++ * to BYTE, which the adapter does not advertise and will ++ * likely fail. ++ */ ++ sfp->read = sfp_smbus_read; ++ sfp->write = sfp_smbus_write; ++ max_block_size = 2; + } else { + sfp->i2c = NULL; + return -EINVAL; diff --git a/target/linux/realtek/patches-6.18/714-net-phy-sfp-add-support-for-SMBus.patch b/target/linux/realtek/patches-6.18/714-net-phy-sfp-add-support-for-SMBus.patch index 390ffabb99..42362fc0fd 100644 --- a/target/linux/realtek/patches-6.18/714-net-phy-sfp-add-support-for-SMBus.patch +++ b/target/linux/realtek/patches-6.18/714-net-phy-sfp-add-support-for-SMBus.patch @@ -10,7 +10,7 @@ Signed-off-by: Antoine Tenart --- a/drivers/net/phy/sfp.c +++ b/drivers/net/phy/sfp.c -@@ -850,6 +850,29 @@ static int sfp_i2c_mdiobus_create(struct +@@ -959,6 +959,29 @@ static int sfp_i2c_mdiobus_create(struct return 0; } @@ -40,7 +40,7 @@ Signed-off-by: Antoine Tenart static void sfp_i2c_mdiobus_destroy(struct sfp *sfp) { mdiobus_unregister(sfp->i2c_mii); -@@ -2024,9 +2047,15 @@ static void sfp_sm_fault(struct sfp *sfp +@@ -2173,9 +2196,15 @@ static void sfp_sm_fault(struct sfp *sfp static int sfp_sm_add_mdio_bus(struct sfp *sfp) { diff --git a/target/linux/realtek/patches-6.18/742-net-sfp-extend-SMBus-support.patch b/target/linux/realtek/patches-6.18/742-net-sfp-extend-SMBus-support.patch deleted file mode 100644 index da94989670..0000000000 --- a/target/linux/realtek/patches-6.18/742-net-sfp-extend-SMBus-support.patch +++ /dev/null @@ -1,204 +0,0 @@ -From 475b0dd976de6db975bfef7d6fdb978d2d64c535 Mon Sep 17 00:00:00 2001 -From: Jonas Jelonek -Date: Fri, 9 Jan 2026 21:04:02 +0000 -Subject: [PATCH net-next v6 2/2] net: sfp: extend SMBus support - -Commit 7662abf4db94 ("net: phy: sfp: Add support for SMBus module access") -added support for SMBus-only controllers for module access. However, this -is restricted to single-byte accesses and has the implication that hwmon -is disabled (due to missing atomicity of 16-bit accesses) and warnings -are printed. - -There are probably a lot of SMBus-only I2C controllers out in the wild -which support more than just byte access. And it also seems that in -several devices, SFP slots are attached to these SMBus controllers -instead of full-featured I2C controllers. Right now, they don't work -with SFP modules. This applies - amongst others - to I2C/SMBus-only -controllers in Realtek longan and mango SoCs. They also support word -access and I2C block reads. - -Extend the current read/write SMBus operations to support SMBus I2C -block and SMBus word access. To avoid having dedicated operations for -each kind of transfer, provide generic read and write operations that -covers all kinds of access depending on whats supported. - -For block access, this requires I2C_FUNC_SMBUS_I2C_BLOCK to be -supported as it relies on reading a pre-defined amount of bytes. -This isn't intended by the official SMBus Block Read but supported by -several I2C controllers/drivers. - -Signed-off-by: Jonas Jelonek ---- - drivers/net/phy/sfp.c | 117 +++++++++++++++++++++++++++++++++--------- - 1 file changed, 92 insertions(+), 25 deletions(-) - ---- a/drivers/net/phy/sfp.c -+++ b/drivers/net/phy/sfp.c -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - #include - - #include "sfp.h" -@@ -758,50 +759,101 @@ static int sfp_i2c_write(struct sfp *sfp - return ret == ARRAY_SIZE(msgs) ? len : 0; - } - --static int sfp_smbus_byte_read(struct sfp *sfp, bool a2, u8 dev_addr, -- void *buf, size_t len) -+static int sfp_smbus_read(struct sfp *sfp, bool a2, u8 dev_addr, void *buf, -+ size_t len) - { - union i2c_smbus_data smbus_data; - u8 bus_addr = a2 ? 0x51 : 0x50; -+ size_t this_len, transferred; -+ u32 functionality; - u8 *data = buf; - int ret; - -+ functionality = i2c_get_functionality(sfp->i2c); -+ - while (len) { -- ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, -- I2C_SMBUS_READ, dev_addr, -- I2C_SMBUS_BYTE_DATA, &smbus_data); -+ this_len = min(len, sfp->i2c_max_block_size); -+ -+ if (functionality & I2C_FUNC_SMBUS_READ_I2C_BLOCK) { -+ smbus_data.block[0] = this_len; -+ ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, -+ I2C_SMBUS_READ, dev_addr, -+ I2C_SMBUS_I2C_BLOCK_DATA, &smbus_data); -+ -+ memcpy(data, &smbus_data.block[1], this_len); -+ transferred = this_len; -+ } else if (this_len >= 2 && -+ functionality & I2C_FUNC_SMBUS_READ_WORD_DATA) { -+ ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, -+ I2C_SMBUS_READ, dev_addr, -+ I2C_SMBUS_WORD_DATA, &smbus_data); -+ -+ put_unaligned_le16(smbus_data.word, data); -+ transferred = 2; -+ } else { -+ ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, -+ I2C_SMBUS_READ, dev_addr, -+ I2C_SMBUS_BYTE_DATA, &smbus_data); -+ -+ *data = smbus_data.byte; -+ transferred = 1; -+ } -+ - if (ret < 0) - return ret; - -- *data = smbus_data.byte; -- -- len--; -- data++; -- dev_addr++; -+ data += transferred; -+ len -= transferred; -+ dev_addr += transferred; - } - - return data - (u8 *)buf; - } - --static int sfp_smbus_byte_write(struct sfp *sfp, bool a2, u8 dev_addr, -- void *buf, size_t len) -+static int sfp_smbus_write(struct sfp *sfp, bool a2, u8 dev_addr, void *buf, -+ size_t len) - { - union i2c_smbus_data smbus_data; - u8 bus_addr = a2 ? 0x51 : 0x50; -+ size_t this_len, transferred; -+ u32 functionality; - u8 *data = buf; - int ret; - -+ functionality = i2c_get_functionality(sfp->i2c); -+ - while (len) { -- smbus_data.byte = *data; -- ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, -- I2C_SMBUS_WRITE, dev_addr, -- I2C_SMBUS_BYTE_DATA, &smbus_data); -- if (ret) -+ this_len = min(len, sfp->i2c_max_block_size); -+ -+ if (functionality & I2C_FUNC_SMBUS_WRITE_I2C_BLOCK) { -+ smbus_data.block[0] = this_len; -+ memcpy(&smbus_data.block[1], data, this_len); -+ -+ ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, -+ I2C_SMBUS_WRITE, dev_addr, -+ I2C_SMBUS_I2C_BLOCK_DATA, &smbus_data); -+ transferred = this_len; -+ } else if (this_len >= 2 && -+ functionality & I2C_FUNC_SMBUS_WRITE_WORD_DATA) { -+ smbus_data.word = get_unaligned_le16(data); -+ ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, -+ I2C_SMBUS_WRITE, dev_addr, -+ I2C_SMBUS_WORD_DATA, &smbus_data); -+ transferred = 2; -+ } else { -+ smbus_data.byte = *data; -+ ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, -+ I2C_SMBUS_WRITE, dev_addr, -+ I2C_SMBUS_BYTE_DATA, &smbus_data); -+ transferred = 1; -+ } -+ -+ if (ret < 0) - return ret; - -- len--; -- data++; -- dev_addr++; -+ data += transferred; -+ len -= transferred; -+ dev_addr += transferred; - } - - return data - (u8 *)buf; -@@ -810,17 +862,32 @@ static int sfp_smbus_byte_write(struct s - static int sfp_i2c_configure(struct sfp *sfp, struct i2c_adapter *i2c) - { - size_t max_block_size; -+ u32 functionality; - - sfp->i2c = i2c; -+ functionality = i2c_get_functionality(i2c); - -- if (i2c_check_functionality(i2c, I2C_FUNC_I2C)) { -+ if (functionality & I2C_FUNC_I2C) { - sfp->read = sfp_i2c_read; - sfp->write = sfp_i2c_write; - max_block_size = SFP_EEPROM_BLOCK_SIZE; -- } else if (i2c_check_functionality(i2c, I2C_FUNC_SMBUS_BYTE_DATA)) { -- sfp->read = sfp_smbus_byte_read; -- sfp->write = sfp_smbus_byte_write; -- max_block_size = 1; -+ } else if ((functionality & I2C_FUNC_SMBUS_BYTE_DATA) == I2C_FUNC_SMBUS_BYTE_DATA || -+ (functionality & I2C_FUNC_SMBUS_I2C_BLOCK) == I2C_FUNC_SMBUS_I2C_BLOCK) { -+ sfp->read = sfp_smbus_read; -+ sfp->write = sfp_smbus_write; -+ -+ if ((functionality & I2C_FUNC_SMBUS_I2C_BLOCK) == I2C_FUNC_SMBUS_I2C_BLOCK) -+ max_block_size = SFP_EEPROM_BLOCK_SIZE; -+ else if ((functionality & I2C_FUNC_SMBUS_WORD_DATA) == I2C_FUNC_SMBUS_WORD_DATA) -+ max_block_size = 2; -+ else -+ max_block_size = 1; -+ } else if ((functionality & I2C_FUNC_SMBUS_WORD_DATA) == I2C_FUNC_SMBUS_WORD_DATA) { -+ WARN(1, "SMBus adapter only supports word access, odd reads/writes will fail!\n"); -+ -+ sfp->read = sfp_smbus_read; -+ sfp->write = sfp_smbus_write; -+ max_block_size = 2; - } else { - sfp->i2c = NULL; - return -EINVAL; diff --git a/target/linux/realtek/rtl931x/config-6.18 b/target/linux/realtek/rtl931x/config-6.18 index cdc6233afa..5f97d95869 100644 --- a/target/linux/realtek/rtl931x/config-6.18 +++ b/target/linux/realtek/rtl931x/config-6.18 @@ -1,10 +1,10 @@ +CONFIG_AQUANTIA_PHY=y 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_AQUANTIA_PHY=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 diff --git a/target/linux/rockchip/armv8/config-6.18 b/target/linux/rockchip/armv8/config-6.18 index d3cc2d486b..2a6817864f 100644 --- a/target/linux/rockchip/armv8/config-6.18 +++ b/target/linux/rockchip/armv8/config-6.18 @@ -39,6 +39,7 @@ CONFIG_ARM64_ERRATUM_2441007=y CONFIG_ARM64_ERRATUM_2441009=y CONFIG_ARM64_ERRATUM_2658417=y CONFIG_ARM64_ERRATUM_3117295=y +CONFIG_ARM64_ERRATUM_4118414=y CONFIG_ARM64_ERRATUM_819472=y CONFIG_ARM64_ERRATUM_824069=y CONFIG_ARM64_ERRATUM_826319=y @@ -772,11 +773,14 @@ CONFIG_UNMAP_KERNEL_AT_EL0=y CONFIG_USB=y CONFIG_USB_COMMON=y CONFIG_USB_DWC3=y -CONFIG_USB_DWC3_HOST=y +CONFIG_USB_DWC3_DUAL_ROLE=y +# CONFIG_USB_DWC3_GADGET is not set +# CONFIG_USB_DWC3_HOST is not set CONFIG_USB_DWC3_OF_SIMPLE=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_HCD_PLATFORM=y # CONFIG_USB_EHCI_ROOT_HUB_TT is not set +CONFIG_USB_GADGET=y CONFIG_USB_OHCI_HCD=y CONFIG_USB_OHCI_HCD_PLATFORM=y CONFIG_USB_PHY=y diff --git a/target/linux/rockchip/patches-6.18/121-04-phy-rockchip-inno-usb2-Simplify-rockchip-usbgrf-handling.patch b/target/linux/rockchip/patches-6.18/039-01-v7.2-phy-rockchip-inno-usb2-Simplify-rockchip-usbgrf-hand.patch similarity index 85% rename from target/linux/rockchip/patches-6.18/121-04-phy-rockchip-inno-usb2-Simplify-rockchip-usbgrf-handling.patch rename to target/linux/rockchip/patches-6.18/039-01-v7.2-phy-rockchip-inno-usb2-Simplify-rockchip-usbgrf-hand.patch index 8933ab19b3..281f3dd83e 100644 --- a/target/linux/rockchip/patches-6.18/121-04-phy-rockchip-inno-usb2-Simplify-rockchip-usbgrf-handling.patch +++ b/target/linux/rockchip/patches-6.18/039-01-v7.2-phy-rockchip-inno-usb2-Simplify-rockchip-usbgrf-hand.patch @@ -1,7 +1,8 @@ -From 4e7d472b61625804f585035a54364a6620bf803a Mon Sep 17 00:00:00 2001 +From be29cd958f5393004a24cd7b5b1da88dd90a651b Mon Sep 17 00:00:00 2001 From: Jonas Karlman -Date: Wed, 23 Jul 2025 12:23:00 +0000 -Subject: [PATCH] phy: rockchip: inno-usb2: Simplify rockchip,usbgrf handling +Date: Tue, 5 May 2026 19:04:07 +0200 +Subject: [PATCH] phy: rockchip: inno-usb2: Simplify rockchip,usbgrf + handling The logic to decide if usbgrf or grf should be used is more complex than it needs to be. For RK3568, RV1108 and soon RK3528 we can assign the @@ -15,13 +16,17 @@ The only expected change from this is that RK3528 can be supported because of an addition of a of_property_present() check. Signed-off-by: Jonas Karlman +Signed-off-by: Heiko Stuebner +Reviewed-by: Neil Armstrong +Link: https://patch.msgid.link/20260505170410.3265305-3-heiko@sntech.de +Signed-off-by: Vinod Koul --- drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 68 +++++-------------- 1 file changed, 18 insertions(+), 50 deletions(-) --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c -@@ -235,7 +235,6 @@ struct rockchip_usb2phy_port { +@@ -228,7 +228,6 @@ struct rockchip_usb2phy_port { * struct rockchip_usb2phy - usb2.0 phy driver data. * @dev: pointer to device. * @grf: General Register Files regmap. @@ -29,7 +34,7 @@ Signed-off-by: Jonas Karlman * @clks: array of phy input clocks. * @clk480m: clock struct of phy output clk. * @clk480m_hw: clock struct of phy output clk management. -@@ -253,7 +252,6 @@ struct rockchip_usb2phy_port { +@@ -246,7 +245,6 @@ struct rockchip_usb2phy_port { struct rockchip_usb2phy { struct device *dev; struct regmap *grf; @@ -37,7 +42,7 @@ Signed-off-by: Jonas Karlman struct clk_bulk_data *clks; struct clk *clk480m; struct clk_hw clk480m_hw; -@@ -268,11 +266,6 @@ struct rockchip_usb2phy { +@@ -261,11 +259,6 @@ struct rockchip_usb2phy { struct rockchip_usb2phy_port ports[USB2PHY_NUM_PORTS]; }; @@ -49,7 +54,7 @@ Signed-off-by: Jonas Karlman static inline int property_enable(struct regmap *base, const struct usb2phy_reg *reg, bool en) { -@@ -330,12 +323,11 @@ static int rockchip_usb2phy_clk480m_prep +@@ -323,12 +316,11 @@ static int rockchip_usb2phy_clk480m_prep { struct rockchip_usb2phy *rphy = container_of(hw, struct rockchip_usb2phy, clk480m_hw); @@ -64,7 +69,7 @@ Signed-off-by: Jonas Karlman if (ret) return ret; -@@ -350,19 +342,17 @@ static void rockchip_usb2phy_clk480m_unp +@@ -343,19 +335,17 @@ static void rockchip_usb2phy_clk480m_unp { struct rockchip_usb2phy *rphy = container_of(hw, struct rockchip_usb2phy, clk480m_hw); @@ -86,7 +91,7 @@ Signed-off-by: Jonas Karlman } static unsigned long -@@ -587,7 +577,6 @@ static int rockchip_usb2phy_power_on(str +@@ -574,7 +564,6 @@ static int rockchip_usb2phy_power_on(str { struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy); struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent); @@ -94,7 +99,7 @@ Signed-off-by: Jonas Karlman int ret; dev_dbg(&rport->phy->dev, "port power on\n"); -@@ -599,7 +588,7 @@ static int rockchip_usb2phy_power_on(str +@@ -586,7 +575,7 @@ static int rockchip_usb2phy_power_on(str if (ret) return ret; @@ -103,7 +108,7 @@ Signed-off-by: Jonas Karlman if (ret) { clk_disable_unprepare(rphy->clk480m); return ret; -@@ -628,7 +617,6 @@ static int rockchip_usb2phy_power_off(st +@@ -615,7 +604,6 @@ static int rockchip_usb2phy_power_off(st { struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy); struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent); @@ -111,7 +116,7 @@ Signed-off-by: Jonas Karlman int ret; dev_dbg(&rport->phy->dev, "port power off\n"); -@@ -636,7 +624,7 @@ static int rockchip_usb2phy_power_off(st +@@ -623,7 +611,7 @@ static int rockchip_usb2phy_power_off(st if (rport->suspended) return 0; @@ -120,7 +125,7 @@ Signed-off-by: Jonas Karlman if (ret) return ret; -@@ -804,28 +792,22 @@ static const char *chg_to_string(enum po +@@ -787,28 +775,22 @@ static const char *chg_to_string(enum po static void rockchip_chg_enable_dcd(struct rockchip_usb2phy *rphy, bool en) { @@ -155,7 +160,7 @@ Signed-off-by: Jonas Karlman } #define CHG_DCD_POLL_TIME (100 * HZ / 1000) -@@ -837,7 +819,6 @@ static void rockchip_chg_detect_work(str +@@ -820,7 +802,6 @@ static void rockchip_chg_detect_work(str struct rockchip_usb2phy_port *rport = container_of(work, struct rockchip_usb2phy_port, chg_work.work); struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); @@ -163,7 +168,7 @@ Signed-off-by: Jonas Karlman bool is_dcd, tmout, vout, vbus_attach; unsigned long delay; -@@ -851,7 +832,7 @@ static void rockchip_chg_detect_work(str +@@ -834,7 +815,7 @@ static void rockchip_chg_detect_work(str rockchip_usb2phy_power_off(rport->phy); /* put the controller in non-driving mode */ if (!vbus_attach) @@ -172,7 +177,7 @@ Signed-off-by: Jonas Karlman /* Start DCD processing stage 1 */ rockchip_chg_enable_dcd(rphy, true); rphy->chg_state = USB_CHG_STATE_WAIT_FOR_DCD; -@@ -915,7 +896,7 @@ static void rockchip_chg_detect_work(str +@@ -898,7 +879,7 @@ static void rockchip_chg_detect_work(str case USB_CHG_STATE_DETECTED: /* put the controller in normal mode */ if (!vbus_attach) @@ -181,7 +186,7 @@ Signed-off-by: Jonas Karlman rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work); dev_dbg(&rport->phy->dev, "charger = %s\n", chg_to_string(rphy->chg_type)); -@@ -1449,27 +1430,14 @@ static int rockchip_usb2phy_probe(struct +@@ -1353,27 +1334,14 @@ static int rockchip_usb2phy_probe(struct if (!rphy) return -ENOMEM; diff --git a/target/linux/rockchip/patches-6.18/121-05-phy-rockchip-inno-usb2-Add-clkout_ctl_phy-support.patch b/target/linux/rockchip/patches-6.18/039-02-v7.2-phy-rockchip-inno-usb2-Add-clkout_ctl_phy-support.patch similarity index 84% rename from target/linux/rockchip/patches-6.18/121-05-phy-rockchip-inno-usb2-Add-clkout_ctl_phy-support.patch rename to target/linux/rockchip/patches-6.18/039-02-v7.2-phy-rockchip-inno-usb2-Add-clkout_ctl_phy-support.patch index f6c167048a..f10df5409e 100644 --- a/target/linux/rockchip/patches-6.18/121-05-phy-rockchip-inno-usb2-Add-clkout_ctl_phy-support.patch +++ b/target/linux/rockchip/patches-6.18/039-02-v7.2-phy-rockchip-inno-usb2-Add-clkout_ctl_phy-support.patch @@ -1,6 +1,6 @@ -From 6b767459cf9295f10ee95b8ab78fbce5991132ed Mon Sep 17 00:00:00 2001 +From 2775541de0580ab1cd077dfef710e6316563d567 Mon Sep 17 00:00:00 2001 From: Jonas Karlman -Date: Wed, 23 Jul 2025 12:23:02 +0000 +Date: Tue, 5 May 2026 19:04:09 +0200 Subject: [PATCH] phy: rockchip: inno-usb2: Add clkout_ctl_phy support The 480m clk is controlled using regs in the PHY address space and not @@ -10,13 +10,17 @@ Add a clkout_ctl_phy usb2phy_reg to handle enable/disable of the 480m clk on these SoCs. Signed-off-by: Jonas Karlman +Signed-off-by: Heiko Stuebner +Reviewed-by: Neil Armstrong +Link: https://patch.msgid.link/20260505170410.3265305-5-heiko@sntech.de +Signed-off-by: Vinod Koul --- drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 47 +++++++++++++++---- 1 file changed, 38 insertions(+), 9 deletions(-) --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c -@@ -184,6 +184,7 @@ struct rockchip_usb2phy_cfg { +@@ -179,6 +179,7 @@ struct rockchip_usb2phy_cfg { unsigned int num_ports; int (*phy_tuning)(struct rockchip_usb2phy *rphy); struct usb2phy_reg clkout_ctl; @@ -24,7 +28,7 @@ Signed-off-by: Jonas Karlman const struct rockchip_usb2phy_port_cfg port_cfgs[USB2PHY_NUM_PORTS]; const struct rockchip_chg_det_reg chg_det; }; -@@ -235,6 +236,7 @@ struct rockchip_usb2phy_port { +@@ -228,6 +229,7 @@ struct rockchip_usb2phy_port { * struct rockchip_usb2phy - usb2.0 phy driver data. * @dev: pointer to device. * @grf: General Register Files regmap. @@ -32,7 +36,7 @@ Signed-off-by: Jonas Karlman * @clks: array of phy input clocks. * @clk480m: clock struct of phy output clk. * @clk480m_hw: clock struct of phy output clk management. -@@ -252,6 +254,7 @@ struct rockchip_usb2phy_port { +@@ -245,6 +247,7 @@ struct rockchip_usb2phy_port { struct rockchip_usb2phy { struct device *dev; struct regmap *grf; @@ -40,7 +44,7 @@ Signed-off-by: Jonas Karlman struct clk_bulk_data *clks; struct clk *clk480m; struct clk_hw clk480m_hw; -@@ -319,15 +322,33 @@ static void rockchip_usb2phy_clk_bulk_di +@@ -312,15 +315,33 @@ static void rockchip_usb2phy_clk_bulk_di clk_bulk_disable_unprepare(rphy->num_clks, rphy->clks); } @@ -77,7 +81,7 @@ Signed-off-by: Jonas Karlman if (ret) return ret; -@@ -340,19 +361,23 @@ static int rockchip_usb2phy_clk480m_prep +@@ -333,19 +354,23 @@ static int rockchip_usb2phy_clk480m_prep static void rockchip_usb2phy_clk480m_unprepare(struct clk_hw *hw) { @@ -107,7 +111,7 @@ Signed-off-by: Jonas Karlman } static unsigned long -@@ -1432,9 +1457,13 @@ static int rockchip_usb2phy_probe(struct +@@ -1336,9 +1361,13 @@ static int rockchip_usb2phy_probe(struct if (!dev->parent || !dev->parent->of_node || of_property_present(np, "rockchip,usbgrf")) { diff --git a/target/linux/rockchip/patches-6.18/121-06-phy-rockchip-inno-usb2-Add-support-for-RK3528.patch b/target/linux/rockchip/patches-6.18/039-03-v7.2-phy-rockchip-inno-usb2-Add-support-for-RK3528.patch similarity index 75% rename from target/linux/rockchip/patches-6.18/121-06-phy-rockchip-inno-usb2-Add-support-for-RK3528.patch rename to target/linux/rockchip/patches-6.18/039-03-v7.2-phy-rockchip-inno-usb2-Add-support-for-RK3528.patch index c9b9aadd3a..08bccd70ec 100644 --- a/target/linux/rockchip/patches-6.18/121-06-phy-rockchip-inno-usb2-Add-support-for-RK3528.patch +++ b/target/linux/rockchip/patches-6.18/039-03-v7.2-phy-rockchip-inno-usb2-Add-support-for-RK3528.patch @@ -1,6 +1,6 @@ -From 8faac4ef6206a1c771e1c016e205dcee8164d618 Mon Sep 17 00:00:00 2001 +From 864b3617df827865a95a06f06f09a8d57a795b91 Mon Sep 17 00:00:00 2001 From: Jianwei Zheng -Date: Wed, 23 Jul 2025 12:23:03 +0000 +Date: Tue, 5 May 2026 19:04:10 +0200 Subject: [PATCH] phy: rockchip: inno-usb2: Add support for RK3528 The RK3528 has a single USB2PHY with a otg and host port. @@ -18,46 +18,61 @@ PHY tuning for RK3528: which uses dwc3 controller to improve fs/ls devices compatibility with long cables. -This is based on vendor kernel linux-stan-6.1-rkr5 tag. +Undocumented magic-values are based on the linux-stan-6.1-rkr5 tag of +the vendor-kernel. Signed-off-by: Jianwei Zheng Signed-off-by: Jonas Karlman +Signed-off-by: Heiko Stuebner +Reviewed-by: Neil Armstrong +Link: https://patch.msgid.link/20260505170410.3265305-6-heiko@sntech.de +Signed-off-by: Vinod Koul --- - drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 74 +++++++++++++++++++ - 1 file changed, 74 insertions(+) + drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 84 +++++++++++++++++++ + 1 file changed, 84 insertions(+) --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c -@@ -1607,6 +1607,28 @@ static int rk3128_usb2phy_tuning(struct +@@ -1511,6 +1511,38 @@ static int rk3128_usb2phy_tuning(struct BIT(2) << BIT_WRITEABLE_SHIFT | 0); } +static int rk3528_usb2phy_tuning(struct rockchip_usb2phy *rphy) +{ -+ int ret = 0; ++ int ret; + + /* Turn off otg port differential receiver in suspend mode */ -+ ret |= regmap_write(rphy->phy_base, 0x30, BIT(18) | 0x0000); ++ ret = regmap_write(rphy->phy_base, 0x30, BIT(18) | 0x0000); ++ if (ret) ++ return ret; + + /* Turn off host port differential receiver in suspend mode */ -+ ret |= regmap_write(rphy->phy_base, 0x430, BIT(18) | 0x0000); ++ ret = regmap_write(rphy->phy_base, 0x430, BIT(18) | 0x0000); ++ if (ret) ++ return ret; + + /* Set otg port HS eye height to 400mv (default is 450mv) */ -+ ret |= regmap_write(rphy->phy_base, 0x30, GENMASK(22, 20) | 0x0000); ++ ret = regmap_write(rphy->phy_base, 0x30, GENMASK(22, 20) | 0x0000); ++ if (ret) ++ return ret; + + /* Set host port HS eye height to 400mv (default is 450mv) */ -+ ret |= regmap_write(rphy->phy_base, 0x430, GENMASK(22, 20) | 0x0000); ++ ret = regmap_write(rphy->phy_base, 0x430, GENMASK(22, 20) | 0x0000); ++ if (ret) ++ return ret; + + /* Choose the Tx fs/ls data as linestate from TX driver for otg port */ -+ ret |= regmap_write(rphy->phy_base, 0x94, GENMASK(22, 19) | 0x0018); ++ ret = regmap_write(rphy->phy_base, 0x94, GENMASK(22, 19) | 0x0018); ++ if (ret) ++ return ret; + -+ return ret; ++ return 0; +} + static int rk3576_usb2phy_tuning(struct rockchip_usb2phy *rphy) { int ret; -@@ -2020,6 +2042,57 @@ static const struct rockchip_usb2phy_cfg +@@ -1924,6 +1956,57 @@ static const struct rockchip_usb2phy_cfg { /* sentinel */ } }; @@ -115,7 +130,7 @@ Signed-off-by: Jonas Karlman static const struct rockchip_usb2phy_cfg rk3562_phy_cfgs[] = { { .reg = 0xff740000, -@@ -2391,6 +2464,7 @@ static const struct of_device_id rockchi +@@ -2291,6 +2374,7 @@ static const struct of_device_id rockchi { .compatible = "rockchip,rk3328-usb2phy", .data = &rk3328_phy_cfgs }, { .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs }, { .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs }, diff --git a/target/linux/rockchip/patches-6.18/042-01-v7.1-nvmem-rockchip-otp-Handle-internal-word_size-in-main.patch b/target/linux/rockchip/patches-6.18/042-01-v7.1-nvmem-rockchip-otp-Handle-internal-word_size-in-main.patch index ef873d5189..43b9c7951e 100644 --- a/target/linux/rockchip/patches-6.18/042-01-v7.1-nvmem-rockchip-otp-Handle-internal-word_size-in-main.patch +++ b/target/linux/rockchip/patches-6.18/042-01-v7.1-nvmem-rockchip-otp-Handle-internal-word_size-in-main.patch @@ -1,6 +1,6 @@ -From 9e7aba140eba2aeb72e65ea778c89a245fa235a4 Mon Sep 17 00:00:00 2001 +From 6c403594354d59fb288978c5a23008da89ba2741 Mon Sep 17 00:00:00 2001 From: Jonas Karlman -Date: Thu, 5 Feb 2026 22:18:58 +0100 +Date: Fri, 27 Mar 2026 13:17:48 +0000 Subject: [PATCH] nvmem: rockchip-otp: Handle internal word_size in main reg_read op @@ -24,6 +24,8 @@ Signed-off-by: Heiko Stuebner Reviewed-by: Heiko Stuebner Tested-by: Heiko Stuebner Signed-off-by: Srinivas Kandagatla +Link: https://patch.msgid.link/20260327131751.3026030-7-srini@kernel.org +Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/rockchip-otp.c | 72 ++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 32 deletions(-) diff --git a/target/linux/rockchip/patches-6.18/042-02-v7.1-nvmem-rockchip-otp-Add-support-for-RK3568.patch b/target/linux/rockchip/patches-6.18/042-02-v7.1-nvmem-rockchip-otp-Add-support-for-RK3568.patch index cc88dec1e2..07fafb0d00 100644 --- a/target/linux/rockchip/patches-6.18/042-02-v7.1-nvmem-rockchip-otp-Add-support-for-RK3568.patch +++ b/target/linux/rockchip/patches-6.18/042-02-v7.1-nvmem-rockchip-otp-Add-support-for-RK3568.patch @@ -1,6 +1,6 @@ -From 11e01bcb827d369344f7f0e960698d33db9ced5a Mon Sep 17 00:00:00 2001 +From 902fa931a2095566de6be12c8153f7fa9b31ab5f Mon Sep 17 00:00:00 2001 From: Finley Xiao -Date: Thu, 5 Feb 2026 22:18:59 +0100 +Date: Fri, 27 Mar 2026 13:17:49 +0000 Subject: [PATCH] nvmem: rockchip-otp: Add support for RK3568 This adds the necessary data for handling otp the rk3568. @@ -11,6 +11,8 @@ Signed-off-by: Heiko Stuebner Reviewed-by: Heiko Stuebner Tested-by: Heiko Stuebner Signed-off-by: Srinivas Kandagatla +Link: https://patch.msgid.link/20260327131751.3026030-8-srini@kernel.org +Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/rockchip-otp.c | 69 ++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/target/linux/rockchip/patches-6.18/042-03-v7.1-nvmem-rockchip-otp-Add-support-for-RK3562.patch b/target/linux/rockchip/patches-6.18/042-03-v7.1-nvmem-rockchip-otp-Add-support-for-RK3562.patch new file mode 100644 index 0000000000..49396b5b6c --- /dev/null +++ b/target/linux/rockchip/patches-6.18/042-03-v7.1-nvmem-rockchip-otp-Add-support-for-RK3562.patch @@ -0,0 +1,33 @@ +From 7efe11aace70faa2199bc42d8949cd289b2998da Mon Sep 17 00:00:00 2001 +From: Finley Xiao +Date: Fri, 27 Mar 2026 13:17:50 +0000 +Subject: [PATCH] nvmem: rockchip-otp: Add support for RK3562 + +This adds the necessary data for handling otp on the rk3562. + +Signed-off-by: Finley Xiao +Signed-off-by: Kever Yang +Signed-off-by: Heiko Stuebner +Tested-by: Willy Tarreau +Reviewed-by: Heiko Stuebner +Signed-off-by: Srinivas Kandagatla +Signed-off-by: Jonas Karlman +Link: https://patch.msgid.link/20260327131751.3026030-9-srini@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/rockchip-otp.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/nvmem/rockchip-otp.c ++++ b/drivers/nvmem/rockchip-otp.c +@@ -377,6 +377,10 @@ static const struct of_device_id rockchi + .data = &px30_data, + }, + { ++ .compatible = "rockchip,rk3562-otp", ++ .data = &rk3568_data, ++ }, ++ { + .compatible = "rockchip,rk3568-otp", + .data = &rk3568_data, + }, diff --git a/target/linux/rockchip/patches-6.18/042-03-v7.1-nvmem-rockchip-otp-Add-support-for-RK3528.patch b/target/linux/rockchip/patches-6.18/042-04-v7.1-nvmem-rockchip-otp-Add-support-for-RK3528.patch similarity index 82% rename from target/linux/rockchip/patches-6.18/042-03-v7.1-nvmem-rockchip-otp-Add-support-for-RK3528.patch rename to target/linux/rockchip/patches-6.18/042-04-v7.1-nvmem-rockchip-otp-Add-support-for-RK3528.patch index 8d4fdf1cf8..b8b50cb71a 100644 --- a/target/linux/rockchip/patches-6.18/042-03-v7.1-nvmem-rockchip-otp-Add-support-for-RK3528.patch +++ b/target/linux/rockchip/patches-6.18/042-04-v7.1-nvmem-rockchip-otp-Add-support-for-RK3528.patch @@ -1,6 +1,6 @@ -From 85e2134182e21dc9550a1e316d690b1dda52d8cf Mon Sep 17 00:00:00 2001 +From a255f352b0e0c06d4b91233f112ddd35eac89947 Mon Sep 17 00:00:00 2001 From: Jonas Karlman -Date: Thu, 5 Feb 2026 22:19:01 +0100 +Date: Fri, 27 Mar 2026 13:17:51 +0000 Subject: [PATCH] nvmem: rockchip-otp: Add support for RK3528 Add support for the OTP controller in RK3528. The OTPC is similar to the @@ -10,6 +10,8 @@ Signed-off-by: Jonas Karlman Signed-off-by: Heiko Stuebner Tested-by: Willy Tarreau Signed-off-by: Srinivas Kandagatla +Link: https://patch.msgid.link/20260327131751.3026030-10-srini@kernel.org +Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/rockchip-otp.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) @@ -43,6 +45,6 @@ Signed-off-by: Srinivas Kandagatla + .data = &rk3528_data, + }, + { - .compatible = "rockchip,rk3568-otp", + .compatible = "rockchip,rk3562-otp", .data = &rk3568_data, }, diff --git a/target/linux/rockchip/patches-6.18/053-v6.19-arm64-dts-rockchip-Fix-SD-card-support-for-RK3576-Na.patch b/target/linux/rockchip/patches-6.18/053-v6.19-arm64-dts-rockchip-Fix-SD-card-support-for-RK3576-Na.patch new file mode 100644 index 0000000000..0d4a4a56d3 --- /dev/null +++ b/target/linux/rockchip/patches-6.18/053-v6.19-arm64-dts-rockchip-Fix-SD-card-support-for-RK3576-Na.patch @@ -0,0 +1,77 @@ +From 3256c25e6c833e11e2a574b69f4ba30e86049846 Mon Sep 17 00:00:00 2001 +From: Shawn Lin +Date: Fri, 16 Jan 2026 08:55:32 +0800 +Subject: [PATCH] arm64: dts: rockchip: Fix SD card support for RK3576 Nanopi + R76s + +[ Upstream commit a9c1acebfe0484343a443d082e039ca77186ed22 ] + +When runtime suspend is enabled, the associated power domain is powered +off, which resets the registers, including the power control bit. As a result, +the card loses power during runtime suspend. The card should still be able +to process I/O with the help of mmc_blk_mq_rw_recovery(), which is suboptimal. +To address this issue, we must use vmmc-supply with a GPIO based method to +maintain power to the card and store valid tuning phases. Also, add cd-gpios +method to make hot-plug work correctly during idle periods. + +Fixes: 7fee88882704 ("arm64: dts: rockchip: Add devicetree for the FriendlyElec NanoPi R76S") +Cc: stable@vger.kernel.org +Signed-off-by: Shawn Lin +Tested-by: Marco Schirrmeister +Link: https://patch.msgid.link/1768524932-163929-6-git-send-email-shawn.lin@rock-chips.com +Signed-off-by: Heiko Stuebner +Signed-off-by: Sasha Levin +--- + .../boot/dts/rockchip/rk3576-nanopi-r76s.dts | 23 ++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) + +--- a/arch/arm64/boot/dts/rockchip/rk3576-nanopi-r76s.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3576-nanopi-r76s.dts +@@ -192,6 +192,18 @@ + regulator-name = "vcc_3v3_s0"; + vin-supply = <&vcc_3v3_s3>; + }; ++ ++ vcc3v3_sd: regulator-vcc-3v3-sd { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc_pwren>; ++ regulator-name = "vcc3v3_sd"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vcc_3v3_s0>; ++ }; + }; + + &combphy0_ps { +@@ -726,6 +738,12 @@ + }; + }; + ++ sdmmc { ++ sdmmc_pwren: sdmmc-pwren { ++ rockchip,pins = <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ + usb { + usb_otg0_pwren_h: usb-otg0-pwren-h { + rockchip,pins = <0 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>; +@@ -751,11 +769,14 @@ + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; ++ cd-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>; + disable-wp; + no-mmc; + no-sdio; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_det &sdmmc0_bus4>; + sd-uhs-sdr104; +- vmmc-supply = <&vcc_3v3_s3>; ++ vmmc-supply = <&vcc3v3_sd>; + vqmmc-supply = <&vccio_sd_s0>; + status = "okay"; + }; diff --git a/target/linux/rockchip/patches-6.18/070-27-v7.1-arm64-dts-rockchip-Enable-OTP-controller-for-RK3528.patch b/target/linux/rockchip/patches-6.18/070-27-v7.1-arm64-dts-rockchip-Enable-OTP-controller-for-RK3528.patch index f797b76494..47dc01a2be 100644 --- a/target/linux/rockchip/patches-6.18/070-27-v7.1-arm64-dts-rockchip-Enable-OTP-controller-for-RK3528.patch +++ b/target/linux/rockchip/patches-6.18/070-27-v7.1-arm64-dts-rockchip-Enable-OTP-controller-for-RK3528.patch @@ -1,7 +1,7 @@ -From a956b54f33de96e0d879e679c22a717d390e1afa Mon Sep 17 00:00:00 2001 +From 8c2c73084bd10237a9bc8f1d5fd49fe3107e4562 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Thu, 12 Mar 2026 22:30:19 +0100 -Subject: arm64: dts: rockchip: Enable OTP controller for RK3528 +Subject: [PATCH] arm64: dts: rockchip: Enable OTP controller for RK3528 Enable the One Time Programmable Controller (OTPC) in RK3528 and add an initial nvmem fixed layout. @@ -10,7 +10,7 @@ Signed-off-by: Jonas Karlman Signed-off-by: Heiko Stuebner Link: https://patch.msgid.link/20260312213019.13965-4-heiko@sntech.de --- - arch/arm64/boot/dts/rockchip/rk3528.dtsi | 47 ++++++++++++++++++++++++++++++++ + arch/arm64/boot/dts/rockchip/rk3528.dtsi | 47 ++++++++++++++++++++++++ 1 file changed, 47 insertions(+) --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi diff --git a/target/linux/rockchip/patches-6.18/131-02-arm64-dts-rockchip-Add-USB-nodes-for-RK3528.patch b/target/linux/rockchip/patches-6.18/073-01-v7.2-arm64-dts-rockchip-Add-USB-nodes-for-RK3528.patch similarity index 78% rename from target/linux/rockchip/patches-6.18/131-02-arm64-dts-rockchip-Add-USB-nodes-for-RK3528.patch rename to target/linux/rockchip/patches-6.18/073-01-v7.2-arm64-dts-rockchip-Add-USB-nodes-for-RK3528.patch index 8ecd633b69..95972977f0 100644 --- a/target/linux/rockchip/patches-6.18/131-02-arm64-dts-rockchip-Add-USB-nodes-for-RK3528.patch +++ b/target/linux/rockchip/patches-6.18/073-01-v7.2-arm64-dts-rockchip-Add-USB-nodes-for-RK3528.patch @@ -1,23 +1,28 @@ -From a41519d8b438adc154debd433c3a1436ebb93a10 Mon Sep 17 00:00:00 2001 +From 5f3ae9b12a6c523992a7216bbc4420ac33450b79 Mon Sep 17 00:00:00 2001 From: Jonas Karlman -Date: Wed, 23 Jul 2025 12:23:05 +0000 +Date: Fri, 29 May 2026 21:03:51 +0200 Subject: [PATCH] arm64: dts: rockchip: Add USB nodes for RK3528 -Rockchip RK3528 has one USB 3.0 DWC3 controller, a USB 2.0 EHCI/OHCI -controller and uses a USB2PHY for USB 2.0. The DWC3 controller may also -use the Naneng Combo PHY for USB3. +Rockchip RK3528 has one USB 3.0 DWC3 controller and oneUSB 2.0 EHCI/OHCI +controller and uses an Innosilicon-USB2PHY for USB 2.0. The DWC3 +controller additionally uses the Naneng Combo PHY for USB3. Add device tree nodes to describe these USB controllers along with the USB 2.0 PHYs. +[moved snps,dis_u2_susphy_quirk here from individual boards, + describe both usb2+3 default phy connections, usb2 boards can override] + Signed-off-by: Jonas Karlman +Signed-off-by: Heiko Stuebner +Link: https://patch.msgid.link/20260529190355.4148175-2-heiko@sntech.de --- - arch/arm64/boot/dts/rockchip/rk3528.dtsi | 77 ++++++++++++++++++++++++ - 1 file changed, 77 insertions(+) + arch/arm64/boot/dts/rockchip/rk3528.dtsi | 80 ++++++++++++++++++++++++ + 1 file changed, 80 insertions(+) --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi -@@ -336,6 +336,30 @@ +@@ -336,6 +336,33 @@ }; }; @@ -32,6 +37,8 @@ Signed-off-by: Jonas Karlman + power-domains = <&power RK3528_PD_VPU>; + resets = <&cru SRST_A_USB3OTG>; + dr_mode = "otg"; ++ phys = <&usb2phy_otg>, <&combphy PHY_TYPE_USB3>; ++ phy-names = "usb2-phy", "usb3-phy"; + phy_type = "utmi_wide"; + snps,dis_enblslpm_quirk; + snps,dis_rxdet_inp3_quirk; @@ -40,6 +47,7 @@ Signed-off-by: Jonas Karlman + snps,dis-u1-entry-quirk; + snps,dis-u2-entry-quirk; + snps,dis-u2-freeclk-exists-quirk; ++ snps,dis_u2_susphy_quirk; + snps,parkmode-disable-hs-quirk; + snps,parkmode-disable-ss-quirk; + status = "disabled"; @@ -48,7 +56,7 @@ Signed-off-by: Jonas Karlman gic: interrupt-controller@fed01000 { compatible = "arm,gic-400"; reg = <0x0 0xfed01000 0 0x1000>, -@@ -349,6 +373,30 @@ +@@ -349,6 +376,30 @@ #interrupt-cells = <3>; }; @@ -79,7 +87,7 @@ Signed-off-by: Jonas Karlman qos_crypto_a: qos@ff200000 { compatible = "rockchip,rk3528-qos", "syscon"; reg = <0x0 0xff200000 0x0 0x20>; -@@ -1273,6 +1321,35 @@ +@@ -1273,6 +1324,35 @@ rockchip,pipe-phy-grf = <&pipe_phy_grf>; status = "disabled"; }; diff --git a/target/linux/rockchip/patches-6.18/107-arm64-dts-rockchip-Enable-USB-2-0-ports-on-Radxa-E20C.patch b/target/linux/rockchip/patches-6.18/073-02-v7.2-arm64-dts-rockchip-Enable-USB-2.0-ports-on-Radxa-E20.patch similarity index 61% rename from target/linux/rockchip/patches-6.18/107-arm64-dts-rockchip-Enable-USB-2-0-ports-on-Radxa-E20C.patch rename to target/linux/rockchip/patches-6.18/073-02-v7.2-arm64-dts-rockchip-Enable-USB-2.0-ports-on-Radxa-E20.patch index 24e690c7cd..bb4ba5b7fb 100644 --- a/target/linux/rockchip/patches-6.18/107-arm64-dts-rockchip-Enable-USB-2-0-ports-on-Radxa-E20C.patch +++ b/target/linux/rockchip/patches-6.18/073-02-v7.2-arm64-dts-rockchip-Enable-USB-2.0-ports-on-Radxa-E20.patch @@ -1,21 +1,28 @@ -From d78af3aa816344d6e76dd77fbaf410fcbfa58bef Mon Sep 17 00:00:00 2001 +From e897bcf81dd920bf80ace6d98ec6f9645c5b50f2 Mon Sep 17 00:00:00 2001 From: Jonas Karlman -Date: Wed, 23 Jul 2025 12:23:06 +0000 +Date: Fri, 29 May 2026 21:03:52 +0200 Subject: [PATCH] arm64: dts: rockchip: Enable USB 2.0 ports on Radxa E20C -The Radxa E20C has one USB2.0 Type-A HOST port and one USB2.0 Type-C OTG -port. +The Radxa E20C has one USB2.0 Type-A HOST port and one USB2.0 Type-C port. + +The Type-C port is conneced to a FE1.1s_QFN USB hub on the board, with its +ports being connected to the XHCI usb controller and an usb-uart bridge. + +This also means, the XHCI controller can only be used in device-mode. Add support for using the USB 2.0 ports on Radxa E20C. Signed-off-by: Jonas Karlman +[set xhci to peripheral and add comment about the outward-facing hub] +Signed-off-by: Heiko Stuebner +Link: https://patch.msgid.link/20260529190355.4148175-3-heiko@sntech.de --- - .../boot/dts/rockchip/rk3528-radxa-e20c.dts | 48 +++++++++++++++++++ - 1 file changed, 48 insertions(+) + .../boot/dts/rockchip/rk3528-radxa-e20c.dts | 60 +++++++++++++++++++ + 1 file changed, 60 insertions(+) --- a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts +++ b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts -@@ -136,6 +136,18 @@ +@@ -134,6 +134,18 @@ regulator-max-microvolt = <5000000>; }; @@ -34,7 +41,7 @@ Signed-off-by: Jonas Karlman vccio_sd: regulator-vccio-sd { compatible = "regulator-gpio"; gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>; -@@ -275,6 +287,12 @@ +@@ -273,6 +285,12 @@ rockchip,pins = <4 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>; }; }; @@ -47,7 +54,7 @@ Signed-off-by: Jonas Karlman }; &pwm1 { -@@ -322,3 +340,33 @@ +@@ -320,3 +338,45 @@ pinctrl-0 = <&uart0m0_xfer>; status = "okay"; }; @@ -60,12 +67,24 @@ Signed-off-by: Jonas Karlman + status = "okay"; +}; + ++/* ++ * The usb controller can only work in peripheral mode, as it is ++ * connected to one of the ports of an outward-facing usb hub. ++ * ++ * type_c-port (hub-input) ++ * | ++ * usb-hub ++ * | | ++ * uart-usb usb-host0 ++ * | ++ * uart0 ++ */ +&usb_host0_xhci { ++ dr_mode = "peripheral"; + extcon = <&usb2phy>; + maximum-speed = "high-speed"; + phys = <&usb2phy_otg>; + phy-names = "usb2-phy"; -+ snps,dis_u2_susphy_quirk; + status = "okay"; +}; + diff --git a/target/linux/rockchip/patches-6.18/121-01-phy-rockchip-inno-usb2-add-soft-vbusvalid-control.patch b/target/linux/rockchip/patches-6.18/121-01-phy-rockchip-inno-usb2-add-soft-vbusvalid-control.patch index e5f83dcad2..a0b1c29831 100644 --- a/target/linux/rockchip/patches-6.18/121-01-phy-rockchip-inno-usb2-add-soft-vbusvalid-control.patch +++ b/target/linux/rockchip/patches-6.18/121-01-phy-rockchip-inno-usb2-add-soft-vbusvalid-control.patch @@ -73,7 +73,7 @@ Signed-off-by: Nicolas Frattaroli struct usb2phy_reg bvalid_det_en; struct usb2phy_reg bvalid_det_st; struct usb2phy_reg bvalid_det_clr; -@@ -203,6 +208,7 @@ struct rockchip_usb2phy_cfg { +@@ -204,6 +209,7 @@ struct rockchip_usb2phy_cfg { * @event_nb: hold event notification callback. * @state: define OTG enumeration states before device reset. * @mode: the dr_mode of the controller. @@ -81,7 +81,7 @@ Signed-off-by: Nicolas Frattaroli */ struct rockchip_usb2phy_port { struct phy *phy; -@@ -222,6 +228,7 @@ struct rockchip_usb2phy_port { +@@ -223,6 +229,7 @@ struct rockchip_usb2phy_port { struct notifier_block event_nb; enum usb_otg_state state; enum usb_dr_mode mode; @@ -89,7 +89,7 @@ Signed-off-by: Nicolas Frattaroli }; /** -@@ -495,6 +502,13 @@ static int rockchip_usb2phy_init(struct +@@ -510,6 +517,13 @@ static int rockchip_usb2phy_init(struct mutex_lock(&rport->mutex); if (rport->port_id == USB2PHY_PORT_OTG) { @@ -103,7 +103,7 @@ Signed-off-by: Nicolas Frattaroli if (rport->mode != USB_DR_MODE_HOST && rport->mode != USB_DR_MODE_UNKNOWN) { /* clear bvalid status and enable bvalid detect irq */ -@@ -535,8 +549,7 @@ static int rockchip_usb2phy_init(struct +@@ -550,8 +564,7 @@ static int rockchip_usb2phy_init(struct if (ret) goto out; @@ -113,7 +113,7 @@ Signed-off-by: Nicolas Frattaroli } else { /* If OTG works in host only mode, do nothing. */ dev_dbg(&rport->phy->dev, "mode %d\n", rport->mode); -@@ -666,8 +679,12 @@ static void rockchip_usb2phy_otg_sm_work +@@ -679,8 +692,12 @@ static void rockchip_usb2phy_otg_sm_work unsigned long delay; bool vbus_attach, sch_work, notify_charger; @@ -128,7 +128,7 @@ Signed-off-by: Nicolas Frattaroli sch_work = false; notify_charger = false; -@@ -1280,6 +1297,83 @@ static int rockchip_otg_event(struct not +@@ -1286,6 +1303,83 @@ static int rockchip_otg_event(struct not return NOTIFY_DONE; } @@ -212,7 +212,7 @@ Signed-off-by: Nicolas Frattaroli static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy, struct rockchip_usb2phy_port *rport, struct device_node *child_np) -@@ -1301,6 +1395,8 @@ static int rockchip_usb2phy_otg_port_ini +@@ -1307,6 +1401,8 @@ static int rockchip_usb2phy_otg_port_ini mutex_init(&rport->mutex); @@ -221,7 +221,7 @@ Signed-off-by: Nicolas Frattaroli rport->mode = of_usb_get_dr_mode_by_phy(child_np, -1); if (rport->mode == USB_DR_MODE_HOST || rport->mode == USB_DR_MODE_UNKNOWN) { -@@ -2054,6 +2150,8 @@ static const struct rockchip_usb2phy_cfg +@@ -2134,6 +2230,8 @@ static const struct rockchip_usb2phy_cfg .port_cfgs = { [USB2PHY_PORT_OTG] = { .phy_sus = { 0x0000, 8, 0, 0, 0x1d1 }, @@ -230,7 +230,7 @@ Signed-off-by: Nicolas Frattaroli .bvalid_det_en = { 0x00c0, 1, 1, 0, 1 }, .bvalid_det_st = { 0x00c4, 1, 1, 0, 1 }, .bvalid_det_clr = { 0x00c8, 1, 1, 0, 1 }, -@@ -2091,6 +2189,8 @@ static const struct rockchip_usb2phy_cfg +@@ -2171,6 +2269,8 @@ static const struct rockchip_usb2phy_cfg .port_cfgs = { [USB2PHY_PORT_OTG] = { .phy_sus = { 0x2000, 8, 0, 0, 0x1d1 }, diff --git a/target/linux/rockchip/patches-6.18/131-03-arm64-dts-rockchip-Add-TSADC-controller-for-RK3528.patch b/target/linux/rockchip/patches-6.18/131-03-arm64-dts-rockchip-Add-TSADC-controller-for-RK3528.patch index 21d609e216..2d04e6c851 100644 --- a/target/linux/rockchip/patches-6.18/131-03-arm64-dts-rockchip-Add-TSADC-controller-for-RK3528.patch +++ b/target/linux/rockchip/patches-6.18/131-03-arm64-dts-rockchip-Add-TSADC-controller-for-RK3528.patch @@ -102,7 +102,7 @@ Signed-off-by: Jonas Karlman timer { compatible = "arm,armv8-timer"; interrupts = , -@@ -689,6 +739,7 @@ +@@ -692,6 +742,7 @@ assigned-clock-rates = <297000000>, <300000000>; clocks = <&cru ACLK_GPU_MALI>, <&scmi_clk SCMI_CLK_GPU>; clock-names = "bus", "core"; @@ -110,7 +110,7 @@ Signed-off-by: Jonas Karlman interrupts = , , , -@@ -1031,6 +1082,33 @@ +@@ -1034,6 +1085,33 @@ status = "disabled"; }; diff --git a/target/linux/rockchip/patches-6.18/510-arm64-dts-rockchip-apply-rtl8822cs-quirk-for-nanopi-r76s.patch b/target/linux/rockchip/patches-6.18/510-arm64-dts-rockchip-apply-rtl8822cs-quirk-for-nanopi-r76s.patch index 6b7a331859..5be7c11ee8 100644 --- a/target/linux/rockchip/patches-6.18/510-arm64-dts-rockchip-apply-rtl8822cs-quirk-for-nanopi-r76s.patch +++ b/target/linux/rockchip/patches-6.18/510-arm64-dts-rockchip-apply-rtl8822cs-quirk-for-nanopi-r76s.patch @@ -1,6 +1,6 @@ --- a/arch/arm64/boot/dts/rockchip/rk3576-nanopi-r76s.dts +++ b/arch/arm64/boot/dts/rockchip/rk3576-nanopi-r76s.dts -@@ -783,6 +783,7 @@ +@@ -804,6 +804,7 @@ status = "okay"; rtl8822cs: wifi@1 { diff --git a/target/linux/rockchip/patches-6.18/610-arm64-rockchip-add-OF-node-for-eth.patch b/target/linux/rockchip/patches-6.18/610-arm64-rockchip-add-OF-node-for-eth.patch index e768baed37..189bf35acf 100644 --- a/target/linux/rockchip/patches-6.18/610-arm64-rockchip-add-OF-node-for-eth.patch +++ b/target/linux/rockchip/patches-6.18/610-arm64-rockchip-add-OF-node-for-eth.patch @@ -663,7 +663,7 @@ Signed-off-by: David Bauer --- a/arch/arm64/boot/dts/rockchip/rk3576-nanopi-r76s.dts +++ b/arch/arm64/boot/dts/rockchip/rk3576-nanopi-r76s.dts -@@ -663,6 +663,22 @@ +@@ -675,6 +675,22 @@ reset-gpios = <&gpio2 RK_PB4 GPIO_ACTIVE_HIGH>; vpcie3v3-supply = <&vcc_3v3_s3>; status = "okay"; @@ -686,7 +686,7 @@ Signed-off-by: David Bauer }; &pcie1 { -@@ -671,6 +687,22 @@ +@@ -683,6 +699,22 @@ reset-gpios = <&gpio0 RK_PC7 GPIO_ACTIVE_HIGH>; vpcie3v3-supply = <&vcc_3v3_s3>; status = "okay"; diff --git a/target/linux/rockchip/patches-6.18/801-07-arm64-dts-rockchip-rk3528-add-rng-node.patch b/target/linux/rockchip/patches-6.18/801-07-arm64-dts-rockchip-rk3528-add-rng-node.patch index d52e97c430..c70328d79f 100644 --- a/target/linux/rockchip/patches-6.18/801-07-arm64-dts-rockchip-rk3528-add-rng-node.patch +++ b/target/linux/rockchip/patches-6.18/801-07-arm64-dts-rockchip-rk3528-add-rng-node.patch @@ -1,6 +1,6 @@ --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi -@@ -1369,6 +1369,16 @@ +@@ -1372,6 +1372,16 @@ }; }; diff --git a/target/linux/sunxi/config-6.18 b/target/linux/sunxi/config-6.18 index e536fd6468..b8b4cd1e65 100644 --- a/target/linux/sunxi/config-6.18 +++ b/target/linux/sunxi/config-6.18 @@ -475,6 +475,7 @@ CONFIG_SND_SIMPLE_CARD=y CONFIG_SND_SIMPLE_CARD_UTILS=y CONFIG_SND_SOC=y CONFIG_SND_SOC_I2C_AND_SPI=y +# CONFIG_SND_SUN20I_D1_CODEC_ANALOG is not set # CONFIG_SND_SUN4I_I2S is not set # CONFIG_SND_SUN4I_SPDIF is not set # CONFIG_SND_SUN50I_DMIC is not set @@ -492,7 +493,6 @@ CONFIG_SPI_SUN6I=y CONFIG_SRCU=y CONFIG_STMMAC_ETH=y CONFIG_STMMAC_PLATFORM=y -# CONFIG_SND_SUN20I_D1_CODEC_ANALOG is not set # CONFIG_SUN20I_GPADC is not set # CONFIG_SUN20I_PPU is not set CONFIG_SUN4I_A10_CCU=y diff --git a/target/linux/zynq/base-files/etc/board.d/02_network b/target/linux/zynq/base-files/etc/board.d/02_network index 159b457682..63ff77dacd 100644 --- a/target/linux/zynq/base-files/etc/board.d/02_network +++ b/target/linux/zynq/base-files/etc/board.d/02_network @@ -6,6 +6,7 @@ board_config_update case "$(board_name)" in avnet,zynq-zed | \ +bitmain,antminer-s9 | \ digilent,zynq-zybo | \ digilent,zynq-zybo-z7 | \ xlnx,zynq-zc702) diff --git a/target/linux/zynq/config-6.12 b/target/linux/zynq/config-6.12 index b9453b663d..6fcb884999 100644 --- a/target/linux/zynq/config-6.12 +++ b/target/linux/zynq/config-6.12 @@ -334,7 +334,10 @@ CONFIG_MOUSE_PS2_TRACKPOINT=y # CONFIG_MTD_CFI_INTELEXT is not set CONFIG_MTD_CMDLINE_PARTS=y # CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_PL35X=y CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_RAW_NAND=y CONFIG_MTD_SPI_NOR=y CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y CONFIG_MTD_SPLIT_FIRMWARE=y @@ -411,7 +414,7 @@ CONFIG_PL310_ERRATA_727915=y CONFIG_PL310_ERRATA_753970=y CONFIG_PL310_ERRATA_769419=y CONFIG_PL330_DMA=y -# CONFIG_PL353_SMC is not set +CONFIG_PL353_SMC=y CONFIG_PLAT_VERSATILE=y CONFIG_PM=y CONFIG_PMBUS=y diff --git a/target/linux/zynq/image/Makefile b/target/linux/zynq/image/Makefile index 4a9c2f047d..dca6068a12 100644 --- a/target/linux/zynq/image/Makefile +++ b/target/linux/zynq/image/Makefile @@ -54,6 +54,13 @@ define Device/avnet_zynq-zed endef TARGET_DEVICES += avnet_zynq-zed +define Device/bitmain_zynq-antminer-s9 + $(call Device/FitImageGzip) + DEVICE_VENDOR := Bitmain + DEVICE_MODEL := Antminer S9 control board +endef +TARGET_DEVICES += bitmain_zynq-antminer-s9 + define Device/digilent_zynq-zybo $(call Device/FitImageGzip) DEVICE_VENDOR := Digilent diff --git a/target/linux/zynq/patches/0001-dts-add-antminer-s9.patch b/target/linux/zynq/patches/0001-dts-add-antminer-s9.patch new file mode 100644 index 0000000000..86eac89766 --- /dev/null +++ b/target/linux/zynq/patches/0001-dts-add-antminer-s9.patch @@ -0,0 +1,102 @@ +--- a/arch/arm/boot/dts/xilinx/Makefile ++++ b/arch/arm/boot/dts/xilinx/Makefile +@@ -1,5 +1,6 @@ + # SPDX-License-Identifier: GPL-2.0 + dtb-$(CONFIG_ARCH_ZYNQ) += \ ++ zynq-antminer-s9.dtb \ + zynq-cc108.dtb \ + zynq-ebaz4205.dtb \ + zynq-microzed.dtb \ +--- /dev/null ++++ b/arch/arm/boot/dts/xilinx/zynq-antminer-s9.dts +@@ -0,0 +1,90 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2011 - 2014 Xilinx ++ * Copyright (C) 2012 National Instruments Corp. ++ */ ++/dts-v1/; ++#include "zynq-7000.dtsi" ++ ++/ { ++ model = "Bitmain Antminer S9 control board"; ++ compatible = "bitmain,antminer-s9", "xlnx,zynq-7000"; ++ ++ aliases { ++ ethernet0 = &gem0; ++ serial0 = &uart1; ++ mmc0 = &sdhci0; ++ }; ++ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0x0 0x20000000>; ++ }; ++ ++ chosen { ++ bootargs = ""; ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ usb_phy0: phy0 { ++ compatible = "usb-nop-xceiv"; ++ #phy-cells = <0>; ++ }; ++ ++ gpio-leds { ++ compatible = "gpio-leds"; ++ ++ led_red { ++ label = "s9:red:usr"; ++ gpios = <&gpio0 37 0x0>; ++ default-state = "off"; ++ }; ++ ++ led_green { ++ label = "s9:green:usr"; ++ gpios = <&gpio0 38 0x0>; ++ default-state = "off"; ++ }; ++ }; ++}; ++ ++&clkc { ++ ps-clk-frequency = <33333333>; ++}; ++ ++&gem0 { ++ status = "okay"; ++ phy-mode = "rgmii-id"; ++ phy-handle = <ðernet_phy>; ++ ++ ethernet_phy: ethernet-phy@1 { ++ reg = <1>; ++ device_type = "ethernet-phy"; ++ }; ++}; ++ ++&nfc0 { ++ status = "okay"; ++ ++ nand@0 { ++ reg = <0>; ++ }; ++}; ++ ++&sdhci0 { ++ status = "okay"; ++}; ++ ++&smcc { ++ status = "okay"; ++}; ++ ++&uart1 { ++ status = "okay"; ++}; ++ ++&usb0 { ++ status = "okay"; ++ dr_mode = "host"; ++ usb-phy = <&usb_phy0>; ++}; diff --git a/target/linux/zynq/patches/0002-dts-antminer-s9-led-aliases.patch b/target/linux/zynq/patches/0002-dts-antminer-s9-led-aliases.patch new file mode 100644 index 0000000000..66210d1f99 --- /dev/null +++ b/target/linux/zynq/patches/0002-dts-antminer-s9-led-aliases.patch @@ -0,0 +1,23 @@ +--- a/arch/arm/boot/dts/xilinx/zynq-antminer-s9.dts ++++ b/arch/arm/boot/dts/xilinx/zynq-antminer-s9.dts +@@ -14,6 +14,11 @@ + ethernet0 = &gem0; + serial0 = &uart1; + mmc0 = &sdhci0; ++ ++ led-boot = &led_green; ++ led-failsafe = &led_green; ++ led-running = &led_green; ++ led-upgrade = &led_green; + }; + + memory@0 { +@@ -40,7 +45,7 @@ + default-state = "off"; + }; + +- led_green { ++ led_green: led_green { + label = "s9:green:usr"; + gpios = <&gpio0 38 0x0>; + default-state = "off"; diff --git a/toolchain/binutils/Config.in b/toolchain/binutils/Config.in index a3687af7fc..29ae2e4aa8 100644 --- a/toolchain/binutils/Config.in +++ b/toolchain/binutils/Config.in @@ -2,7 +2,7 @@ choice prompt "Binutils Version" if TOOLCHAINOPTS - default BINUTILS_USE_VERSION_2_44 + default BINUTILS_USE_VERSION_2_46 help Select the version of binutils you wish to use. @@ -15,7 +15,7 @@ choice select BINUTILS_VERSION_2_45 config BINUTILS_USE_VERSION_2_46 - bool "Binutils 2.46" + bool "Binutils 2.46.1" select BINUTILS_VERSION_2_46 endchoice diff --git a/toolchain/binutils/Config.version b/toolchain/binutils/Config.version index 4102dd6dd3..ca38e8c07e 100644 --- a/toolchain/binutils/Config.version +++ b/toolchain/binutils/Config.version @@ -1,16 +1,16 @@ config BINUTILS_VERSION_2_44 - default y if !TOOLCHAINOPTS bool config BINUTILS_VERSION_2_45 bool config BINUTILS_VERSION_2_46 + default y if !TOOLCHAINOPTS bool config BINUTILS_VERSION string default "2.44" if BINUTILS_VERSION_2_44 default "2.45.1" if BINUTILS_VERSION_2_45 - default "2.46.0" if BINUTILS_VERSION_2_46 + default "2.46.1" if BINUTILS_VERSION_2_46 diff --git a/toolchain/binutils/Makefile b/toolchain/binutils/Makefile index 74d7c3c4d6..68ec1c24de 100644 --- a/toolchain/binutils/Makefile +++ b/toolchain/binutils/Makefile @@ -24,8 +24,8 @@ ifeq ($(PKG_VERSION),2.45.1) PKG_HASH:=5fe101e6fe9d18fdec95962d81ed670fdee5f37e3f48f0bef87bddf862513aa5 endif -ifeq ($(PKG_VERSION),2.46.0) - PKG_HASH:=d75a94f4d73e7a4086f7513e67e439e8fcdcbb726ffe63f4661744e6256b2cf2 +ifeq ($(PKG_VERSION),2.46.1) + PKG_HASH:=e127a709cba24c76de8936cb7083dd768f28cd37eb010492e2f19b71eb1294e4 endif HOST_BUILD_PARALLEL:=1 diff --git a/toolchain/binutils/patches/2.45.1/300-001_ld_makefile_patch.patch b/toolchain/binutils/patches/2.45/300-001_ld_makefile_patch.patch similarity index 100% rename from toolchain/binutils/patches/2.45.1/300-001_ld_makefile_patch.patch rename to toolchain/binutils/patches/2.45/300-001_ld_makefile_patch.patch diff --git a/toolchain/binutils/patches/2.45.1/400-mips_no_dynamic_linking_sym.patch b/toolchain/binutils/patches/2.45/400-mips_no_dynamic_linking_sym.patch similarity index 100% rename from toolchain/binutils/patches/2.45.1/400-mips_no_dynamic_linking_sym.patch rename to toolchain/binutils/patches/2.45/400-mips_no_dynamic_linking_sym.patch diff --git a/toolchain/binutils/patches/2.45.1/500-Change-default-emulation-for-mips64-linux.patch b/toolchain/binutils/patches/2.45/500-Change-default-emulation-for-mips64-linux.patch similarity index 100% rename from toolchain/binutils/patches/2.45.1/500-Change-default-emulation-for-mips64-linux.patch rename to toolchain/binutils/patches/2.45/500-Change-default-emulation-for-mips64-linux.patch diff --git a/toolchain/gcc/Config.version b/toolchain/gcc/Config.version index 8dd6e8fc69..0fc67f7b92 100644 --- a/toolchain/gcc/Config.version +++ b/toolchain/gcc/Config.version @@ -10,7 +10,7 @@ config GCC_VERSION string default EXTERNAL_GCC_VERSION if EXTERNAL_TOOLCHAIN && !NATIVE_TOOLCHAIN default "13.4.0" if GCC_VERSION_13 - default "15.2.0" if GCC_VERSION_15 + default "15.3.0" if GCC_VERSION_15 default "14.3.0" config GCC_USE_DEFAULT_VERSION diff --git a/toolchain/gcc/common.mk b/toolchain/gcc/common.mk index c122810d0b..10bc7070bf 100644 --- a/toolchain/gcc/common.mk +++ b/toolchain/gcc/common.mk @@ -38,8 +38,8 @@ ifeq ($(PKG_VERSION),14.3.0) PKG_HASH:=e0dc77297625631ac8e50fa92fffefe899a4eb702592da5c32ef04e2293aca3a endif -ifeq ($(PKG_VERSION),15.2.0) - PKG_HASH:=438fd996826b0c82485a29da03a72d71d6e3541a83ec702df4271f6fe025d24e +ifeq ($(PKG_VERSION),15.3.0) + PKG_HASH:=fa59c1beef8995f27c4d71c1df227587189315d3e6faff1bb4306e61b0c530eb endif PATCH_DIR=../patches-$(GCC_MAJOR_VERSION).x diff --git a/toolchain/gcc/patches-15.x/004-libcody-Make-it-buildable-by-C-11-to-C-26.patch b/toolchain/gcc/patches-15.x/004-libcody-Make-it-buildable-by-C-11-to-C-26.patch deleted file mode 100644 index db25be919a..0000000000 --- a/toolchain/gcc/patches-15.x/004-libcody-Make-it-buildable-by-C-11-to-C-26.patch +++ /dev/null @@ -1,250 +0,0 @@ -From daa3e1ead791bc58208043cfc4595ba1a78cdd34 Mon Sep 17 00:00:00 2001 -From: Jakub Jelinek -Date: Fri, 21 Nov 2025 16:25:58 +0100 -Subject: [PATCH] libcody: Make it buildable by C++11 to C++26 - -The following builds with -std=c++11 and c++14 and c++17 and c++20 and c++23 -and c++26. - -I see the u8 string literals are mixed e.g. with strerror, so in --fexec-charset=IBM1047 there will still be garbage, so am not 100% sure if -the u8 literals everywhere are worth it either. - -2025-11-21 Jakub Jelinek - - * cody.hh (S2C): For __cpp_char8_t >= 201811 use char8_t instead of - char in argument type. - (MessageBuffer::Space): Revert 2025-11-15 change. - (MessageBuffer::Append): For __cpp_char8_t >= 201811 add overload - with char8_t const * type of first argument. - (Packet::Packet): Similarly for first argument. - * client.cc (CommunicationError, Client::ProcessResponse, - Client::Connect, ConnectResponse, PathnameResponse, OKResponse, - IncludeTranslateResponse): Cast u8 string literals to (const char *) - where needed. - * server.cc (Server::ProcessRequests, ConnectRequest): Likewise. - -(cherry picked from commit 07a767c7a50d1daae8ef7d4aba73fe53ad40c0b7) ---- - libcody/client.cc | 36 +++++++++++++++++++----------------- - libcody/cody.hh | 22 ++++++++++++++++++++++ - libcody/server.cc | 28 ++++++++++++++-------------- - 3 files changed, 55 insertions(+), 31 deletions(-) - ---- a/libcody/client.cc -+++ b/libcody/client.cc -@@ -97,7 +97,7 @@ int Client::CommunicateWithServer () - - static Packet CommunicationError (int err) - { -- std::string e {u8"communication error:"}; -+ std::string e {(const char *) u8"communication error:"}; - e.append (strerror (err)); - - return Packet (Client::PC_ERROR, std::move (e)); -@@ -110,33 +110,34 @@ Packet Client::ProcessResponse (std::vec - { - if (e == EINVAL) - { -- std::string msg (u8"malformed string '"); -+ std::string msg ((const char *) u8"malformed string '"); - msg.append (words[0]); -- msg.append (u8"'"); -+ msg.append ((const char *) u8"'"); - return Packet (Client::PC_ERROR, std::move (msg)); - } - else -- return Packet (Client::PC_ERROR, u8"missing response"); -+ return Packet (Client::PC_ERROR, (const char *) u8"missing response"); - } - - Assert (!words.empty ()); -- if (words[0] == u8"ERROR") -+ if (words[0] == (const char *) u8"ERROR") - return Packet (Client::PC_ERROR, -- words.size () == 2 ? words[1]: u8"malformed error response"); -+ words.size () == 2 ? words[1] -+ : (const char *) u8"malformed error response"); - - if (isLast && !read.IsAtEnd ()) - return Packet (Client::PC_ERROR, -- std::string (u8"unexpected extra response")); -+ std::string ((const char *) u8"unexpected extra response")); - - Assert (code < Detail::RC_HWM); - Packet result (responseTable[code] (words)); - result.SetRequest (code); - if (result.GetCode () == Client::PC_ERROR && result.GetString ().empty ()) - { -- std::string msg {u8"malformed response '"}; -+ std::string msg {(const char *) u8"malformed response '"}; - - read.LexedLine (msg); -- msg.append (u8"'"); -+ msg.append ((const char *) u8"'"); - result.GetString () = std::move (msg); - } - else if (result.GetCode () == Client::PC_CONNECT) -@@ -199,7 +200,7 @@ Packet Client::Connect (char const *agen - size_t alen, size_t ilen) - { - write.BeginLine (); -- write.AppendWord (u8"HELLO"); -+ write.AppendWord ((const char *) u8"HELLO"); - write.AppendInteger (Version); - write.AppendWord (agent, true, alen); - write.AppendWord (ident, true, ilen); -@@ -211,7 +212,8 @@ Packet Client::Connect (char const *agen - // HELLO $version $agent [$flags] - Packet ConnectResponse (std::vector &words) - { -- if (words[0] == u8"HELLO" && (words.size () == 3 || words.size () == 4)) -+ if (words[0] == (const char *) u8"HELLO" -+ && (words.size () == 3 || words.size () == 4)) - { - char *eptr; - unsigned long val = strtoul (words[1].c_str (), &eptr, 10); -@@ -247,7 +249,7 @@ Packet Client::ModuleRepo () - // PATHNAME $dir | ERROR - Packet PathnameResponse (std::vector &words) - { -- if (words[0] == u8"PATHNAME" && words.size () == 2) -+ if (words[0] == (const char *) u8"PATHNAME" && words.size () == 2) - return Packet (Client::PC_PATHNAME, std::move (words[1])); - - return Packet (Client::PC_ERROR, u8""); -@@ -256,7 +258,7 @@ Packet PathnameResponse (std::vector &words) - { -- if (words[0] == u8"OK") -+ if (words[0] == (const char *) u8"OK") - return Packet (Client::PC_OK); - else - return Packet (Client::PC_ERROR, -@@ -319,11 +321,11 @@ Packet Client::IncludeTranslate (char co - // PATHNAME $cmifile - Packet IncludeTranslateResponse (std::vector &words) - { -- if (words[0] == u8"BOOL" && words.size () == 2) -+ if (words[0] == (const char *) u8"BOOL" && words.size () == 2) - { -- if (words[1] == u8"FALSE") -- return Packet (Client::PC_BOOL, 0); -- else if (words[1] == u8"TRUE") -+ if (words[1] == (const char *) u8"FALSE") -+ return Packet (Client::PC_BOOL); -+ else if (words[1] == (const char *) u8"TRUE") - return Packet (Client::PC_BOOL, 1); - else - return Packet (Client::PC_ERROR, u8""); ---- a/libcody/cody.hh -+++ b/libcody/cody.hh -@@ -47,12 +47,21 @@ namespace Detail { - - // C++11 doesn't have utf8 character literals :( - -+#if __cpp_char8_t >= 201811 -+template -+constexpr char S2C (char8_t const (&s)[I]) -+{ -+ static_assert (I == 2, "only single octet strings may be converted"); -+ return s[0]; -+} -+#else - template - constexpr char S2C (char const (&s)[I]) - { - static_assert (I == 2, "only single octet strings may be converted"); - return s[0]; - } -+#endif - - /// Internal buffering class. Used to concatenate outgoing messages - /// and Lex incoming ones. -@@ -123,6 +132,13 @@ public: - Space (); - Append (str, maybe_quote, len); - } -+#if __cpp_char8_t >= 201811 -+ void AppendWord (char8_t const *str, bool maybe_quote = false, -+ size_t len = ~size_t (0)) -+ { -+ AppendWord ((const char *) str, maybe_quote, len); -+ } -+#endif - /// Add a word as with AppendWord - /// @param str the string to append - /// @param maybe_quote string might need quoting, as for Append -@@ -264,6 +280,12 @@ public: - : string (s), cat (STRING), code (c) - { - } -+#if __cpp_char8_t >= 201811 -+ Packet (unsigned c, const char8_t *s) -+ : string ((const char *) s), cat (STRING), code (c) -+ { -+ } -+#endif - Packet (unsigned c, std::vector &&v) - : vector (std::move (v)), cat (VECTOR), code (c) - { ---- a/libcody/server.cc -+++ b/libcody/server.cc -@@ -36,12 +36,12 @@ static RequestPair - const requestTable[Detail::RC_HWM] = - { - // Same order as enum RequestCode -- RequestPair {u8"HELLO", nullptr}, -- RequestPair {u8"MODULE-REPO", ModuleRepoRequest}, -- RequestPair {u8"MODULE-EXPORT", ModuleExportRequest}, -- RequestPair {u8"MODULE-IMPORT", ModuleImportRequest}, -- RequestPair {u8"MODULE-COMPILED", ModuleCompiledRequest}, -- RequestPair {u8"INCLUDE-TRANSLATE", IncludeTranslateRequest}, -+ RequestPair {(const char *) u8"HELLO", nullptr}, -+ RequestPair {(const char *) u8"MODULE-REPO", ModuleRepoRequest}, -+ RequestPair {(const char *) u8"MODULE-EXPORT", ModuleExportRequest}, -+ RequestPair {(const char *) u8"MODULE-IMPORT", ModuleImportRequest}, -+ RequestPair {(const char *) u8"MODULE-COMPILED", ModuleCompiledRequest}, -+ RequestPair {(const char *) u8"INCLUDE-TRANSLATE", IncludeTranslateRequest}, - }; - } - -@@ -135,21 +135,21 @@ void Server::ProcessRequests (void) - std::string msg; - - if (err > 0) -- msg = u8"error processing '"; -+ msg = (const char *) u8"error processing '"; - else if (ix >= Detail::RC_HWM) -- msg = u8"unrecognized '"; -+ msg = (const char *) u8"unrecognized '"; - else if (IsConnected () && ix == Detail::RC_CONNECT) -- msg = u8"already connected '"; -+ msg = (const char *) u8"already connected '"; - else if (!IsConnected () && ix != Detail::RC_CONNECT) -- msg = u8"not connected '"; -+ msg = (const char *) u8"not connected '"; - else -- msg = u8"malformed '"; -+ msg = (const char *) u8"malformed '"; - - read.LexedLine (msg); -- msg.append (u8"'"); -+ msg.append ((const char *) u8"'"); - if (err > 0) - { -- msg.append (u8" "); -+ msg.append ((const char *) u8" "); - msg.append (strerror (err)); - } - resolver->ErrorResponse (this, std::move (msg)); -@@ -176,7 +176,7 @@ Resolver *ConnectRequest (Server *s, Res - return nullptr; - - if (words.size () == 3) -- words.emplace_back (u8""); -+ words.emplace_back ((const char *) u8""); - unsigned version = ParseUnsigned (words[1]); - if (version == ~0u) - return nullptr; diff --git a/toolchain/gcc/patches-15.x/820-libgcc_pic.patch b/toolchain/gcc/patches-15.x/820-libgcc_pic.patch index f9691e599f..20f1bac45a 100644 --- a/toolchain/gcc/patches-15.x/820-libgcc_pic.patch +++ b/toolchain/gcc/patches-15.x/820-libgcc_pic.patch @@ -8,7 +8,7 @@ Date: Mon Oct 19 23:26:09 2009 +0000 --- a/libgcc/Makefile.in +++ b/libgcc/Makefile.in -@@ -944,11 +944,12 @@ $(libgcov-driver-objects): %$(objext): $ +@@ -945,11 +945,12 @@ $(libgcov-driver-objects): %$(objext): $ # Static libraries. libgcc.a: $(libgcc-objects) @@ -22,7 +22,7 @@ Date: Mon Oct 19 23:26:09 2009 +0000 -rm -f $@ objects="$(objects)"; \ -@@ -972,7 +973,7 @@ all: libunwind.a +@@ -973,7 +974,7 @@ all: libunwind.a endif ifeq ($(enable_shared),yes) @@ -31,7 +31,7 @@ Date: Mon Oct 19 23:26:09 2009 +0000 ifneq ($(LIBUNWIND),) all: libunwind$(SHLIB_EXT) libgcc_s$(SHLIB_EXT): libunwind$(SHLIB_EXT) -@@ -1181,6 +1182,10 @@ install-shared: +@@ -1182,6 +1183,10 @@ install-shared: chmod 644 $(DESTDIR)$(inst_libdir)/libgcc_eh.a $(RANLIB) $(DESTDIR)$(inst_libdir)/libgcc_eh.a diff --git a/toolchain/gcc/patches-15.x/910-mbsd_multi.patch b/toolchain/gcc/patches-15.x/910-mbsd_multi.patch index 4b29ac01cc..3603b95b40 100644 --- a/toolchain/gcc/patches-15.x/910-mbsd_multi.patch +++ b/toolchain/gcc/patches-15.x/910-mbsd_multi.patch @@ -114,7 +114,7 @@ Date: Tue Jul 31 00:52:27 2007 +0000 ; On SVR4 targets, it also controls whether or not to emit a --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi -@@ -10897,6 +10897,17 @@ This option is only supported for C and +@@ -10901,6 +10901,17 @@ This option is only supported for C and This warning is upgraded to an error by @option{-pedantic-errors}. diff --git a/tools/bc/Makefile b/tools/bc/Makefile index e86a68c05b..1523ad1f65 100644 --- a/tools/bc/Makefile +++ b/tools/bc/Makefile @@ -7,11 +7,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=bc -PKG_VERSION:=1.08.1 +PKG_VERSION:=1.08.2 -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=@GNU/bc -PKG_HASH:=515430115b3334c636317503460a0950dff79940aa3259ce2c1aa67c2881d023 +PKG_HASH:=ae470fec429775653e042015edc928d07c8c3b2fc59765172a330d3d87785f86 PKG_CPE_ID:=cpe:/a:gnu:bc diff --git a/tools/bc/patches/000-getopt-prototype.patch b/tools/bc/patches/000-getopt-prototype.patch deleted file mode 100644 index ca6246963b..0000000000 --- a/tools/bc/patches/000-getopt-prototype.patch +++ /dev/null @@ -1,18 +0,0 @@ ---- a/h/getopt.h -+++ b/h/getopt.h -@@ -135,15 +135,7 @@ struct option - arguments to the option '\0'. This behavior is specific to the GNU - `getopt'. */ - --#ifdef __GNU_LIBRARY__ --/* Many other libraries have conflicting prototypes for getopt, with -- differences in the consts, in stdlib.h. To avoid compilation -- errors, only prototype getopt for the GNU C library. */ - extern int getopt (int ___argc, char *const *___argv, const char *__shortopts); --#else /* not __GNU_LIBRARY__ */ --extern int getopt (); --#endif /* __GNU_LIBRARY__ */ -- - #ifndef __need_getopt - extern int getopt_long (int ___argc, char *const *___argv, - const char *__shortopts, diff --git a/tools/cmake/Makefile b/tools/cmake/Makefile index 09ee956891..45f7df13d2 100644 --- a/tools/cmake/Makefile +++ b/tools/cmake/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=cmake -PKG_VERSION:=4.3.3 +PKG_VERSION:=4.3.4 PKG_VERSION_MAJOR:=$(word 1,$(subst ., ,$(PKG_VERSION))).$(word 2,$(subst ., ,$(PKG_VERSION))) PKG_RELEASE:=1 PKG_CPE_ID:=cpe:/a:kitware:cmake @@ -15,7 +15,7 @@ PKG_CPE_ID:=cpe:/a:kitware:cmake PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://github.com/Kitware/CMake/releases/download/v$(PKG_VERSION)/ \ https://cmake.org/files/v$(PKG_VERSION_MAJOR)/ -PKG_HASH:=cba4bb7a44edf2877bb6f059932896383babe435b3a8c3b5df48b4aa41c9bb85 +PKG_HASH:=fdeff897b9eb49d764539f2b1edc6eb7e1440df325678a97c1978499e931adda HOST_BUILD_PARALLEL:=1 HOST_CONFIGURE_PARALLEL:=1 diff --git a/tools/util-linux/Makefile b/tools/util-linux/Makefile index 07d712295b..6554eff183 100644 --- a/tools/util-linux/Makefile +++ b/tools/util-linux/Makefile @@ -7,11 +7,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=util-linux -PKG_VERSION:=2.42.1 +PKG_VERSION:=2.42.2 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=@KERNEL/linux/utils/$(PKG_NAME)/v2.42 -PKG_HASH:=82e9158eb12a9b0b569d84e1687fed9dd18fe89ccd8ef5ac3427218a7c0d7f7f +PKG_HASH:=03a05d3adf9602ef128f2da05b84b3205ce60c351e5737c0370f74000679ce8a PKG_CPE_ID:=cpe:/a:kernel:util-linux include $(INCLUDE_DIR)/host-build.mk