Merge Official Source
Signed-off-by: Tianling Shen <cnsztl@immortalwrt.org>
This commit is contained in:
@@ -13,7 +13,7 @@ include $(INCLUDE_DIR)/host-build.mk
|
||||
|
||||
define U-Boot/Default
|
||||
BUILD_TARGET:=airoha
|
||||
FIP_COMPRESS:=1
|
||||
LZMA_COMPRESS:=1
|
||||
endef
|
||||
|
||||
define U-Boot/en7523_rfb
|
||||
@@ -46,10 +46,19 @@ 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
|
||||
|
||||
UBOOT_TARGETS := \
|
||||
en7523_rfb \
|
||||
an7581_rfb \
|
||||
an7583_rfb
|
||||
an7583_rfb \
|
||||
an7581_gemtek_w1700k
|
||||
|
||||
UBOOT_CUSTOMIZE_CONFIG := \
|
||||
--disable TOOLS_KWBIMAGE \
|
||||
@@ -65,15 +74,12 @@ define Build/fip-image-bl2
|
||||
endef
|
||||
|
||||
define Build/fip-image
|
||||
$(if $(FIP_COMPRESS), $(STAGING_DIR_HOST)/bin/lzma e \
|
||||
$(PKG_BUILD_DIR)/u-boot.bin \
|
||||
$(PKG_BUILD_DIR)/u-boot.bin.lzma)
|
||||
$(if $(FIP_COMPRESS), $(STAGING_DIR_HOST)/bin/lzma e \
|
||||
$(if $(LZMA_COMPRESS), $(STAGING_DIR_HOST)/bin/lzma e \
|
||||
files/$(BL31_IMAGE) \
|
||||
$(PKG_BUILD_DIR)/bl31.bin.lzma)
|
||||
$(STAGING_DIR_HOST)/bin/fiptool create \
|
||||
--soc-fw $(PKG_BUILD_DIR)/bl31.bin$(if $(FIP_COMPRESS),.lzma) \
|
||||
--nt-fw $(PKG_BUILD_DIR)/u-boot.bin$(if $(FIP_COMPRESS),.lzma) \
|
||||
--soc-fw $(PKG_BUILD_DIR)/bl31.bin$(if $(LZMA_COMPRESS),.lzma) \
|
||||
--nt-fw $(PKG_BUILD_DIR)/u-boot.bin$(if $(LZMA_COMPRESS),.lzma) \
|
||||
$(PKG_BUILD_DIR)/u-boot.fip
|
||||
endef
|
||||
|
||||
@@ -84,6 +90,9 @@ endef
|
||||
|
||||
define Build/Compile
|
||||
$(call Build/Compile/U-Boot)
|
||||
$(if $(LZMA_COMPRESS), $(STAGING_DIR_HOST)/bin/lzma e \
|
||||
$(PKG_BUILD_DIR)/u-boot.bin \
|
||||
$(PKG_BUILD_DIR)/u-boot.bin.lzma)
|
||||
ifeq ($(UBOOT_IMAGE),u-boot.fip)
|
||||
$(call Build/fip-image-bl2)
|
||||
$(call Build/fip-image)
|
||||
@@ -99,6 +108,11 @@ define Build/InstallDev
|
||||
ifeq ($(UBOOT_IMAGE),u-boot.fip)
|
||||
$(INSTALL_DATA) $(PKG_BUILD_DIR)/bl2.fip $(STAGING_DIR_IMAGE)/$(BUILD_VARIANT)-bl2.fip
|
||||
$(INSTALL_DATA) $(PKG_BUILD_DIR)/u-boot.fip $(STAGING_DIR_IMAGE)/$(BUILD_VARIANT)-bl31-u-boot.fip
|
||||
else
|
||||
$(INSTALL_DATA) $(PKG_BUILD_DIR)/u-boot.bin$(if $(LZMA_COMPRESS),.lzma) \
|
||||
$(STAGING_DIR_IMAGE)/$(BUILD_VARIANT)-u-boot.bin$(if $(LZMA_COMPRESS),.lzma)
|
||||
$(INSTALL_DATA) $(PKG_BUILD_DIR)/u-boot.dtb \
|
||||
$(STAGING_DIR_IMAGE)/$(BUILD_VARIANT)-u-boot.dtb
|
||||
endif
|
||||
endef
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
From 4fb890cd92dcf8985e76a544c949ad455784ed81 Mon Sep 17 00:00:00 2001
|
||||
From: Dirk Buchwalder <buchwalder@posteo.de>
|
||||
Date: Sun, 1 Mar 2026 13:48:42 +0100
|
||||
Subject: [PATCH] uboot-airoha: add a label to the spi node
|
||||
|
||||
Signed-off-by: Dirk Buchwalder <buchwalder@posteo.de>
|
||||
---
|
||||
dts/upstream/src/arm64/airoha/en7581.dtsi | 2 -+
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/dts/upstream/src/arm64/airoha/en7581.dtsi
|
||||
+++ b/dts/upstream/src/arm64/airoha/en7581.dtsi
|
||||
@@ -150,7 +150,7 @@
|
||||
interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_LOW>;
|
||||
};
|
||||
|
||||
- spi@1fa10000 {
|
||||
+ snfi: spi@1fa10000 {
|
||||
compatible = "airoha,en7581-snand";
|
||||
reg = <0x0 0x1fa10000 0x0 0x140>,
|
||||
<0x0 0x1fa11000 0x0 0x160>;
|
||||
@@ -0,0 +1,318 @@
|
||||
From d6402eadaa56494b382e389d739b9f80d6883788 Mon Sep 17 00:00:00 2001
|
||||
From: Kenneth Kasilag <kenneth@kasilag.me>
|
||||
Date: Sat, 21 Feb 2026 21:49:46 +0000
|
||||
Subject: [PATCH] an7581: add uboot chainloader for w1700k
|
||||
|
||||
Due to issues surrounding the implementation of the vendor BMT/BBT
|
||||
on Airoha, upstream ATF + uboot has switched to UBI flash partitions.
|
||||
|
||||
However, some devices shipped on this platform are bootloader locked,
|
||||
and thus it is impossible to replace ATF + uboot.
|
||||
|
||||
During testing for the Gemtek W1700K (#17869), sysupgrades from Linux
|
||||
(which is unaware of the underlying BMT/BBT) would occasionally write
|
||||
data into blocks which were remapped by the vendor uboot when it was
|
||||
read on the following reboot, causing a soft brick.
|
||||
|
||||
An acceptable workaround [1],[2] was discussed where an intermediate
|
||||
uboot would be written by the vendor uboot (which is aware of Airoha
|
||||
BMT/BBT). This chainloader would then ignore the regions of flash
|
||||
used by the vendor uboot, and store all relevant data inside of UBI.
|
||||
|
||||
UBI would then be used to handle bad block management. As the vendor
|
||||
ATF + uboot do not read or interact with the UBI region, we would avoid
|
||||
unwanted remaps from BMT/BBT.
|
||||
|
||||
This commit introduces support for building such a chainloader, by
|
||||
packaging u-boot and DTS into a FIT image; to be flashed like a kernel.
|
||||
|
||||
Configuration for the Gemtek W1700K is provided as an example of how the
|
||||
chainloader is used.
|
||||
|
||||
[1] https://github.com/openwrt/openwrt/pull/17869#discussion_r2836066746
|
||||
[2] https://github.com/openwrt/openwrt/pull/17869#discussion_r2838395671
|
||||
|
||||
Signed-off-by: Kenneth Kasilag <kenneth@kasilag.me>
|
||||
---
|
||||
configs/an7581_w1700k_defconfig | 107 ++++++++++
|
||||
defenvs/an7581_w1700k_env | 21 ++
|
||||
dts/upstream/src/arm64/airoha/an7581-w1700k-ubi.dts | 87 +++++
|
||||
3 files changed, 215 insertions(+), 0 deletions(-)
|
||||
create mode 100644 configs/an7581_w1700k_defconfig
|
||||
create mode 100644 defenvs/an7581_w1700k_env
|
||||
create mode 100644 dts/upstream/src/arm64/airoha/an7581-w1700k-ubi.dts
|
||||
|
||||
--- /dev/null
|
||||
+++ b/configs/an7581_w1700k_defconfig
|
||||
@@ -0,0 +1,107 @@
|
||||
+CONFIG_ARM=y
|
||||
+CONFIG_ARCH_AIROHA=y
|
||||
+CONFIG_AUTOBOOT_KEYED=y
|
||||
+CONFIG_AUTOBOOT_MENU_SHOW=y
|
||||
+CONFIG_POSITION_INDEPENDENT=y
|
||||
+CONFIG_TARGET_AN7581=y
|
||||
+CONFIG_TEXT_BASE=0x81E00000
|
||||
+CONFIG_SYS_MALLOC_F_LEN=0x4000
|
||||
+CONFIG_NR_DRAM_BANKS=1
|
||||
+CONFIG_ENV_SIZE=0x4000
|
||||
+CONFIG_ENV_OFFSET=0x7c000
|
||||
+CONFIG_DM_GPIO=y
|
||||
+CONFIG_DEFAULT_DEVICE_TREE="airoha/an7581-w1700k-ubi"
|
||||
+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_BOOTDELAY=30
|
||||
+CONFIG_DEFAULT_FDT_FILE="an7581-w1700k-ubi"
|
||||
+CONFIG_SYS_PBSIZE=1049
|
||||
+CONFIG_SYS_CONSOLE_IS_IN_ENV=y
|
||||
+# CONFIG_DISPLAY_BOARDINFO is not set
|
||||
+CONFIG_HUSH_PARSER=y
|
||||
+CONFIG_SYS_PROMPT="U-Boot> "
|
||||
+CONFIG_SYS_MAXARGS=8
|
||||
+CONFIG_CMD_BOOTZ=y
|
||||
+CONFIG_CMD_BOOTMENU=y
|
||||
+# CONFIG_CMD_ELF is not set
|
||||
+# CONFIG_CMD_XIMG is not set
|
||||
+CONFIG_CMD_BIND=y
|
||||
+CONFIG_CMD_GPIO=y
|
||||
+CONFIG_CMD_MMC=y
|
||||
+CONFIG_CMD_MTD=y
|
||||
+CONFIG_CMD_SF_TEST=y
|
||||
+CONFIG_CMD_SPI=y
|
||||
+# CONFIG_CMD_SETEXPR is not set
|
||||
+CONFIG_CMD_PING=y
|
||||
+CONFIG_CMD_EXT4=y
|
||||
+CONFIG_CMD_FAT=y
|
||||
+CONFIG_CMD_FS_GENERIC=y
|
||||
+CONFIG_CMD_MTDPARTS=y
|
||||
+CONFIG_CMD_LOG=y
|
||||
+CONFIG_OF_UPSTREAM=y
|
||||
+CONFIG_ENV_OVERWRITE=y
|
||||
+CONFIG_ENV_IS_IN_MMC=y
|
||||
+# CONFIG_ENV_IS_IN_MTD is not set
|
||||
+CONFIG_ENV_RELOC_GD_ENV_ADDR=y
|
||||
+CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
|
||||
+CONFIG_NET_RANDOM_ETHADDR=y
|
||||
+CONFIG_SYS_RX_ETH_BUFFER=8
|
||||
+CONFIG_REGMAP=y
|
||||
+CONFIG_SYSCON=y
|
||||
+CONFIG_CLK=y
|
||||
+CONFIG_DMA=y
|
||||
+CONFIG_LED=y
|
||||
+CONFIG_LED_GPIO=y
|
||||
+CONFIG_MMC_HS200_SUPPORT=y
|
||||
+CONFIG_MMC_MTK=y
|
||||
+CONFIG_MTD=y
|
||||
+CONFIG_DM_MTD=y
|
||||
+CONFIG_MTD_SPI_NAND=y
|
||||
+CONFIG_DM_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_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_CMD_UBI=y
|
||||
+# CONFIG_CMD_UBI_RENAME is not set
|
||||
+CONFIG_CMD_UBIFS=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_UBI_VID_OFFSET=0
|
||||
+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_ENV_USE_DEFAULT_ENV_TEXT_FILE=y
|
||||
+CONFIG_ENV_DEFAULT_ENV_TEXT_FILE="defenvs/an7581_w1700k_env"
|
||||
+CONFIG_SHA512=y
|
||||
--- /dev/null
|
||||
+++ b/defenvs/an7581_w1700k_env
|
||||
@@ -0,0 +1,27 @@
|
||||
+loadaddr=0x81800000
|
||||
+initaddr=0x89000000
|
||||
+ipaddr=192.168.1.1
|
||||
+serverip=192.168.1.10
|
||||
+bootfile=immortalwrt-airoha-an7581-gemtek_w1700k-ubi-initramfs-recovery.itb
|
||||
+installfile=immortalwrt-airoha-an7581-gemtek_w1700k-ubi-initramfs-installer.itb
|
||||
+bootled_pwr=status:red
|
||||
+bootled_rec=status:blue
|
||||
+boot_ubi=ubi part ubi && run boot_production ; run boot_recovery
|
||||
+boot_production=led $bootled_pwr on ; run ubi_read_production && bootm $loadaddr#$bootconf ; led $bootled_pwr off
|
||||
+boot_recovery=led $bootled_rec on ; run ubi_read_recovery ; bootm $initaddr#$bootconf ; led $bootled_rec off
|
||||
+boot_tftp=tftpboot $initaddr $bootfile && bootm $initaddr#$bootconf
|
||||
+boot_installer=tftpboot $initaddr $installfile && bootm $initaddr#$bootconf
|
||||
+bootconf=config-1
|
||||
+bootcmd=boot_ubi
|
||||
+bootdelay=3
|
||||
+bootmenu_confirm_return=askenv - Press ENTER to return to menu ; bootmenu 60
|
||||
+bootmenu_default=0
|
||||
+bootmenu_delay=3
|
||||
+bootmenu_title= 34m( ( ( mOpenWrt34m ) ) )
|
||||
+bootmenu_0=Run default boot command.=run boot_production
|
||||
+bootmenu_1=Boot system via TFTP.=run boot_tftp ; run bootmenu_confirm_return
|
||||
+bootmenu_2=Boot recovery system from flash.=run boot_recovery ; run bootmenu_confirm_return
|
||||
+bootmenu_3=Boot installer via TFTP.=run boot_installer ; run bootmenu_confirm_return
|
||||
+bootmenu_4=Reboot.=reset
|
||||
+ubi_read_production=ubi read $loadaddr fit && iminfo $loadaddr
|
||||
+ubi_read_recovery=ubi check recovery && ubi read $initaddr recovery
|
||||
--- /dev/null
|
||||
+++ b/dts/upstream/src/arm64/airoha/an7581-w1700k-ubi.dts
|
||||
@@ -0,0 +1,131 @@
|
||||
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
+/dts-v1/;
|
||||
+
|
||||
+/* Bootloader installs ATF here */
|
||||
+/memreserve/ 0x80000000 0x200000;
|
||||
+
|
||||
+#include <dt-bindings/input/linux-event-codes.h>
|
||||
+#include <dt-bindings/gpio/gpio.h>
|
||||
+#include "en7581.dtsi"
|
||||
+
|
||||
+/ {
|
||||
+ model = "Gemtek W1700K (UBI)";
|
||||
+ compatible = "gemtek,w1700k-ubi", "airoha,an7581", "airoha,en7581";
|
||||
+
|
||||
+ aliases {
|
||||
+ serial0 = &uart1;
|
||||
+ };
|
||||
+
|
||||
+ chosen {
|
||||
+ stdout-path = "serial0:115200n8";
|
||||
+ linux,usable-memory-range = <0x0 0x80200000 0x0 0x7fe00000>;
|
||||
+ };
|
||||
+
|
||||
+ memory@80000000 {
|
||||
+ device_type = "memory";
|
||||
+ reg = <0x0 0x80000000 0x2 0x00000000>;
|
||||
+ };
|
||||
+
|
||||
+ gpio-keys {
|
||||
+ compatible = "gpio-keys";
|
||||
+
|
||||
+ key-restart {
|
||||
+ label = "reset";
|
||||
+ gpios = <&en7581_pinctrl 0 GPIO_ACTIVE_LOW>;
|
||||
+ linux,code = <KEY_RESTART>;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ gpio-leds {
|
||||
+ compatible = "gpio-leds";
|
||||
+
|
||||
+ led_status_green {
|
||||
+ label = "status:green";
|
||||
+ gpios = <&en7581_pinctrl 17 GPIO_ACTIVE_LOW>;
|
||||
+ default-state = "off";
|
||||
+ };
|
||||
+
|
||||
+ led_status_blue {
|
||||
+ label = "status:blue";
|
||||
+ gpios = <&en7581_pinctrl 19 GPIO_ACTIVE_LOW>;
|
||||
+ default-state = "off";
|
||||
+ };
|
||||
+
|
||||
+ led_status_red {
|
||||
+ label = "status:red";
|
||||
+ gpios = <&en7581_pinctrl 29 GPIO_ACTIVE_LOW>;
|
||||
+ default-state = "off";
|
||||
+ };
|
||||
+
|
||||
+ led_status_white {
|
||||
+ label = "status:white";
|
||||
+ gpios = <&en7581_pinctrl 20 GPIO_ACTIVE_LOW>;
|
||||
+ default-state = "off";
|
||||
+ };
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
+&snfi {
|
||||
+ status = "okay";
|
||||
+};
|
||||
+
|
||||
+&spi_nand {
|
||||
+ partitions {
|
||||
+ compatible = "fixed-partitions";
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <1>;
|
||||
+
|
||||
+ vendor@0 {
|
||||
+ label = "vendor";
|
||||
+ reg = <0x00000000 0x00600000>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+
|
||||
+ chainloader@600000 {
|
||||
+ label = "chainloader";
|
||||
+ reg = <0x00600000 0x00100000>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+
|
||||
+ ubi@700000 {
|
||||
+ label = "ubi";
|
||||
+ reg = <0x00700000 0x1f700000>;
|
||||
+ };
|
||||
+
|
||||
+ /* reserved for bad block table */
|
||||
+ reserved_bmt@1fe00000 {
|
||||
+ label = "reserved_bmt";
|
||||
+ reg = <0x1fe00000 0x00200000>;
|
||||
+ read-only;
|
||||
+ };
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
+&en7581_pinctrl {
|
||||
+ gpio-ranges = <&en7581_pinctrl 0 13 47>;
|
||||
+
|
||||
+ pcie0_rst_pins: pcie0-rst-pins {
|
||||
+ conf {
|
||||
+ pins = "pcie_reset0";
|
||||
+ drive-open-drain = <1>;
|
||||
+ };
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
+&pcie0 {
|
||||
+ pinctrl-names = "default";
|
||||
+ pinctrl-0 = <&pcie0_rst_pins>;
|
||||
+ status = "okay";
|
||||
+};
|
||||
+
|
||||
+&i2c0 {
|
||||
+ status = "okay";
|
||||
+};
|
||||
+
|
||||
+ð {
|
||||
+ status = "okay";
|
||||
+};
|
||||
+
|
||||
+&gdm1 {
|
||||
+ status = "okay";
|
||||
+};
|
||||
@@ -10,11 +10,11 @@ include $(INCLUDE_DIR)/kernel.mk
|
||||
|
||||
PKG_SOURCE_URL:=https://github.com/chunkeey/FritzBox-4040-UBOOT
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_VERSION:=9d89013f9cc963eca25856c61fa066091d35f8de
|
||||
PKG_SOURCE_DATE:=2022-05-01
|
||||
PKG_MIRROR_HASH:=4e8106a7877ae6aa8da44bf95401b860d11f7d51417cc5a61ce59a353d4ee866
|
||||
PKG_SOURCE_VERSION:=6909090cb82db96f8ef0cd211ca91e87d69a07fc
|
||||
PKG_SOURCE_DATE:=2026-03-04
|
||||
PKG_MIRROR_HASH:=741da058f24e559befff1f2d28d057dbfe9b3a6af67e60191cbefdbacc9143bb
|
||||
|
||||
PKG_RELEASE:=5
|
||||
PKG_RELEASE:=1
|
||||
|
||||
include $(INCLUDE_DIR)/u-boot.mk
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
@@ -51,6 +51,12 @@ define U-Boot/fritz7530
|
||||
BUILD_DEVICES:=avm_fritzbox-7530
|
||||
endef
|
||||
|
||||
define U-Boot/huawei_ap4050dn
|
||||
NAME:=Huawei AP4050DN
|
||||
BUILD_DEVICES:=huawei_ap4050dn
|
||||
UBOOT_IMAGE:=uImage
|
||||
endef
|
||||
|
||||
UBOOT_CONFIGURE_VARS += USE_PRIVATE_LIBGCC=yes
|
||||
UBOOT_MAKE_FLAGS = USE_PRIVATE_LIBGCC=yes
|
||||
export DTC
|
||||
@@ -64,7 +70,14 @@ endef
|
||||
|
||||
define Build/Compile
|
||||
$(Build/Compile/U-Boot)
|
||||
(cd $(PKG_BUILD_DIR); ./fritz/fritzcreator.sh $(UBOOT_BOARD);)
|
||||
@( \
|
||||
cd $(PKG_BUILD_DIR) ; \
|
||||
if [ "$(UBOOT_BOARD)" = "huawei_ap4050dn" ]; then \
|
||||
./huawei/huaweicreator.sh $(UBOOT_BOARD) ; \
|
||||
else \
|
||||
./fritz/fritzcreator.sh $(UBOOT_BOARD) ; \
|
||||
fi \
|
||||
)
|
||||
endef
|
||||
|
||||
define Build/InstallDev
|
||||
@@ -74,9 +87,9 @@ endef
|
||||
|
||||
define Package/u-boot/install
|
||||
$(Package/u-boot/install/default)
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/upload-to-f4040.sh $(1)/
|
||||
$(if $(filter fritz%,$(BUILD_VARIANT)),$(INSTALL_BIN) $(PKG_BUILD_DIR)/upload-to-f4040.sh $(1)/)
|
||||
endef
|
||||
|
||||
UBOOT_TARGETS := fritz1200 fritz3000 fritz4040 fritz7520 fritz7530
|
||||
UBOOT_TARGETS := fritz1200 fritz3000 fritz4040 fritz7520 fritz7530 huawei_ap4050dn
|
||||
|
||||
$(eval $(call BuildPackage/U-Boot))
|
||||
|
||||
@@ -6,9 +6,9 @@ PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL=$(PROJECT_GIT)/project/firmware/qca-wireless.git
|
||||
PKG_SOURCE_DATE:=2026-02-17
|
||||
PKG_SOURCE_VERSION:=4b7ccdeadfc0eb65c5459234a6d17432052f47f2
|
||||
PKG_MIRROR_HASH:=80f6f8f5692dcf2ffa4f64d45b96aeb93be3c8d438cfba6d47236d2f0360181c
|
||||
PKG_SOURCE_DATE:=2026-03-07
|
||||
PKG_SOURCE_VERSION:=beaf4667b9be6413c6d30994ba38475d77a5ae06
|
||||
PKG_MIRROR_HASH:=b3b3732aeca7ea587b259953909674bd6cff9ce659b94f140fa3186854c4b521
|
||||
PKG_FLAGS:=nonshared
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
@@ -45,6 +45,7 @@ ALLWIFIBOARDS:= \
|
||||
glinet_gl-ax1800 \
|
||||
glinet_gl-axt1800 \
|
||||
glinet_gl-b3000 \
|
||||
huawei_ap4050dn \
|
||||
ignitenet_ss-w2-ac2600 \
|
||||
iodata_wn-dax3000gr \
|
||||
jdcloud_re-cs-02 \
|
||||
@@ -237,6 +238,7 @@ $(eval $(call generate-ipq-wifi-package,elecom_wrc-x3000gs2,ELECOM WRC-X3000GS2)
|
||||
$(eval $(call generate-ipq-wifi-package,glinet_gl-ax1800,GL.iNet GL-AX1800))
|
||||
$(eval $(call generate-ipq-wifi-package,glinet_gl-axt1800,GL.iNet GL-AXT1800))
|
||||
$(eval $(call generate-ipq-wifi-package,glinet_gl-b3000,GL.iNet GL-B3000))
|
||||
$(eval $(call generate-ipq-wifi-package,huawei_ap4050dn,Huawei AP4050DN))
|
||||
$(eval $(call generate-ipq-wifi-package,ignitenet_ss-w2-ac2600,Ignitenet SS-W2-AC2600))
|
||||
$(eval $(call generate-ipq-wifi-package,iodata_wn-dax3000gr,I-O DATA WN-DAX3000GR))
|
||||
$(eval $(call generate-ipq-wifi-package,jdcloud_re-cs-02,JDCloud RE-CS-02))
|
||||
|
||||
@@ -40,22 +40,6 @@ endef
|
||||
$(eval $(call KernelPackage,gpio-beeper))
|
||||
|
||||
|
||||
define KernelPackage/gpio-cascade
|
||||
SUBMENU:=$(GPIO_MENU)
|
||||
TITLE:=Generic GPIO cascade
|
||||
KCONFIG:=CONFIG_GPIO_CASCADE
|
||||
DEPENDS:=@GPIO_SUPPORT +kmod-mux-core
|
||||
FILES:=$(LINUX_DIR)/drivers/gpio/gpio-cascade.ko
|
||||
AUTOLOAD:=$(call AutoLoad,29,gpio-cascade,1)
|
||||
endef
|
||||
|
||||
define KernelPackage/gpio-cascade/description
|
||||
Kernel module for Generic GPIO cascade
|
||||
endef
|
||||
|
||||
$(eval $(call KernelPackage,gpio-cascade))
|
||||
|
||||
|
||||
define KernelPackage/gpio-f7188x
|
||||
SUBMENU:=$(GPIO_MENU)
|
||||
TITLE:=Fintek F718xx/F818xx GPIO Support
|
||||
@@ -90,6 +74,22 @@ endef
|
||||
$(eval $(call KernelPackage,gpio-it87))
|
||||
|
||||
|
||||
define KernelPackage/gpio-line-mux
|
||||
SUBMENU:=$(GPIO_MENU)
|
||||
TITLE:=Virtual GPIO line multiplexer
|
||||
KCONFIG:=CONFIG_GPIO_LINE_MUX
|
||||
DEPENDS:=@GPIO_SUPPORT +kmod-mux-core
|
||||
FILES:=$(LINUX_DIR)/drivers/gpio/gpio-line-mux.ko
|
||||
AUTOLOAD:=$(call AutoLoad,29,gpio-line-mux,1)
|
||||
endef
|
||||
|
||||
define KernelPackage/gpio-line-mux/description
|
||||
Kernel module for Virtual GPIO line multiplexer
|
||||
endef
|
||||
|
||||
$(eval $(call KernelPackage,gpio-line-mux))
|
||||
|
||||
|
||||
define KernelPackage/gpio-nxp-74hc164
|
||||
SUBMENU:=$(GPIO_MENU)
|
||||
TITLE:=NXP 74HC164 GPIO expander support
|
||||
|
||||
@@ -390,6 +390,25 @@ endef
|
||||
$(eval $(call KernelPackage,iio-ccs811))
|
||||
|
||||
|
||||
define KernelPackage/iio-richtek-rtq6056
|
||||
TITLE:=Richtek RTQ6056 Current and Power Monitor ADC
|
||||
DEPENDS:=+kmod-i2c-core +kmod-regmap-i2c +kmod-industrialio-triggered-buffer
|
||||
KCONFIG:= CONFIG_RICHTEK_RTQ6056
|
||||
FILES:=$(LINUX_DIR)/drivers/iio/adc/rtq6056.ko
|
||||
AUTOLOAD:=$(call AutoProbe,rtq6056)
|
||||
$(call AddDepends/iio)
|
||||
endef
|
||||
|
||||
define KernelPackage/iio-richtek-rtq6056/description
|
||||
Support for Richtek RTQ6056 Current and Power Monitor ADC.
|
||||
RTQ6056 is a high accuracy current-sense monitor with I2C and SMBus
|
||||
compatible interface, and the device provides full information for
|
||||
system by reading out the load current and power.
|
||||
endef
|
||||
|
||||
$(eval $(call KernelPackage,iio-richtek-rtq6056))
|
||||
|
||||
|
||||
define KernelPackage/iio-si7020
|
||||
DEPENDS:=+kmod-i2c-core
|
||||
TITLE:=Silicon Labs Si7020 sensor
|
||||
|
||||
@@ -13,7 +13,7 @@ Signed-off-by: Paweł Owoc <frut3k7@gmail.com>
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath11k/wmi.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
|
||||
@@ -2682,7 +2682,7 @@ int ath11k_wmi_send_wmm_update_cmd_tlv(s
|
||||
@@ -2688,7 +2688,7 @@ int ath11k_wmi_send_wmm_update_cmd_tlv(s
|
||||
FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
|
||||
|
||||
cmd->vdev_id = vdev_id;
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ruslan Isaev <legale.legale@gmail.com>
|
||||
Date: Sun, 1 Mar 2026 00:00:00 +0000
|
||||
Subject: [PATCH] wifi: ath11k: ipq807x; ipq60xx: fix monitor rx frame length (+8 tail)
|
||||
|
||||
OpenWrt issue:
|
||||
https://github.com/openwrt/openwrt/issues/16183
|
||||
|
||||
Problem summary:
|
||||
On qualcommax (ipq60xx/ipq807x) with ath11k, monitor-mode captures contain
|
||||
frames that are consistently longer than expected by 8 bytes.
|
||||
|
||||
The symptom is visible in pcap/radiotap captures, and Wireshark parsing
|
||||
becomes correct after manually cutting these 8 bytes from captured frames.
|
||||
|
||||
|
||||
This patch:
|
||||
- Remove merge-stage FCS/tail manipulations in ath11k_dp_rx_mon_merg_msdus().
|
||||
- add length fix in ath11k_dp_rx_mon_deliver(), trim 8 bytes right
|
||||
before radiotap update and delivery to mac80211.
|
||||
|
||||
This targets monitor capture length correctness only and keeps the fix scoped
|
||||
to the monitor RX delivery path.
|
||||
|
||||
Index: backports-6.18.7/drivers/net/wireless/ath/ath11k/dp_rx.c
|
||||
===================================================================
|
||||
--- backports-6.18.7.orig/drivers/net/wireless/ath/ath11k/dp_rx.c
|
||||
+++ backports-6.18.7/drivers/net/wireless/ath/ath11k/dp_rx.c
|
||||
@@ -4931,8 +4931,13 @@ ath11k_dp_rx_mon_merg_msdus(struct ath11
|
||||
}
|
||||
|
||||
prev_buf->next = NULL;
|
||||
+ /* REMOVED: skb_trim(prev_buf, prev_buf->len - HAL_RX_FCS_LEN);
|
||||
+ * Older code trimmed HAL_RX_FCS_LEN here from prev_buf.
|
||||
+ * That only affects the last MSDU in the chain.
|
||||
+ * Length correction is now done in
|
||||
+ * ath11k_dp_rx_mon_deliver() for every delivered monitor skb.
|
||||
+ */
|
||||
|
||||
- skb_trim(prev_buf, prev_buf->len - HAL_RX_FCS_LEN);
|
||||
} else if (decap_format == DP_RX_DECAP_TYPE_NATIVE_WIFI) {
|
||||
u8 qos_pkt = 0;
|
||||
|
||||
@@ -4958,10 +4963,13 @@ ath11k_dp_rx_mon_merg_msdus(struct ath11
|
||||
prev_buf = msdu;
|
||||
msdu = msdu->next;
|
||||
}
|
||||
- dest = skb_put(prev_buf, HAL_RX_FCS_LEN);
|
||||
- if (!dest)
|
||||
- goto err_merge_fail;
|
||||
-
|
||||
+ /* REMOVED: skb_put(prev_buf, HAL_RX_FCS_LEN)
|
||||
+ * Older code did skb_put(), effectively
|
||||
+ * extending the payload tail from merge stage for the last MSDU.
|
||||
+ * This is removed so merge path does not mutate capture length.
|
||||
+ * We keep a single length-fix point in monitor deliver path
|
||||
+ * (trim 8 bytes) right before mac80211 hand-off.
|
||||
+ */
|
||||
ath11k_dbg(ab, ATH11K_DBG_DATA,
|
||||
"mpdu_buf %p mpdu_buf->len %u",
|
||||
prev_buf, prev_buf->len);
|
||||
@@ -5086,12 +5094,27 @@ static int ath11k_dp_rx_mon_deliver(stru
|
||||
|
||||
header = mon_skb;
|
||||
|
||||
- rxs->flag = 0;
|
||||
+ /* Do not clear rxs->flag here to preserve FCS presence information
|
||||
+ * set during MSDU merge/trim.
|
||||
+ */
|
||||
+ rxs->flag |= RX_FLAG_ONLY_MONITOR;
|
||||
|
||||
if (fcs_err)
|
||||
- rxs->flag = RX_FLAG_FAILED_FCS_CRC;
|
||||
+ rxs->flag |= RX_FLAG_FAILED_FCS_CRC;
|
||||
|
||||
do {
|
||||
+ /* HW monitor path on ipq60xx/ipq807x may append FCS + 4-byte tail.
|
||||
+ * Force trim 8 bytes right before delivery to mac80211 so
|
||||
+ * userspace capture length reflects actual 802.11 frame size.
|
||||
+ */
|
||||
+ if (mon_skb->len > (FCS_LEN * 2)) {
|
||||
+ u32 old_len = mon_skb->len;
|
||||
+
|
||||
+ skb_trim(mon_skb, old_len - (FCS_LEN * 2));
|
||||
+ ath11k_warn(ar->ab, "%s:%d DELIVER trim8 len %u -> %u\n",
|
||||
+ __func__, __LINE__, old_len, mon_skb->len);
|
||||
+ }
|
||||
+
|
||||
skb_next = mon_skb->next;
|
||||
if (!skb_next)
|
||||
rxs->flag &= ~RX_FLAG_AMSDU_MORE;
|
||||
@@ -1,38 +0,0 @@
|
||||
--- a/drivers/net/wireless/ath/ath5k/initvals.c
|
||||
+++ b/drivers/net/wireless/ath/ath5k/initvals.c
|
||||
@@ -62,8 +62,14 @@ static const struct ath5k_ini ar5210_ini
|
||||
{ AR5K_IMR, 0 },
|
||||
{ AR5K_IER, AR5K_IER_DISABLE },
|
||||
{ AR5K_BSR, 0, AR5K_INI_READ },
|
||||
+#if !defined(CONFIG_ATHEROS_AR71XX) && !defined(CONFIG_ATH79)
|
||||
{ AR5K_TXCFG, AR5K_DMASIZE_128B },
|
||||
{ AR5K_RXCFG, AR5K_DMASIZE_128B },
|
||||
+#else
|
||||
+ /* WAR for AR71xx PCI bug */
|
||||
+ { AR5K_TXCFG, AR5K_DMASIZE_128B },
|
||||
+ { AR5K_RXCFG, AR5K_DMASIZE_4B },
|
||||
+#endif
|
||||
{ AR5K_CFG, AR5K_INIT_CFG },
|
||||
{ AR5K_TOPS, 8 },
|
||||
{ AR5K_RXNOFRM, 8 },
|
||||
--- a/drivers/net/wireless/ath/ath5k/dma.c
|
||||
+++ b/drivers/net/wireless/ath/ath5k/dma.c
|
||||
@@ -854,10 +854,18 @@ ath5k_hw_dma_init(struct ath5k_hw *ah)
|
||||
* guess we can tweak it and see how it goes ;-)
|
||||
*/
|
||||
if (ah->ah_version != AR5K_AR5210) {
|
||||
+#if !defined(CONFIG_ATHEROS_AR71XX) && !defined(CONFIG_ATH79)
|
||||
AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
|
||||
AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
|
||||
AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
|
||||
AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B);
|
||||
+#else
|
||||
+ /* WAR for AR71xx PCI bug */
|
||||
+ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
|
||||
+ AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
|
||||
+ AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
|
||||
+ AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_4B);
|
||||
+#endif
|
||||
}
|
||||
|
||||
/* Pre-enable interrupts on 5211/5212*/
|
||||
@@ -10,21 +10,22 @@
|
||||
#else
|
||||
static inline void ath_init_leds(struct ath_softc *sc)
|
||||
{
|
||||
@@ -980,6 +983,13 @@ void ath_ant_comb_scan(struct ath_softc
|
||||
@@ -980,6 +983,14 @@ void ath_ant_comb_scan(struct ath_softc
|
||||
|
||||
#define ATH9K_NUM_CHANCTX 2 /* supports 2 operating channels */
|
||||
|
||||
+struct ath_led {
|
||||
+ struct list_head list;
|
||||
+ struct ath_softc *sc;
|
||||
+ const struct gpio_led *gpio;
|
||||
+ struct gpio_led gpio;
|
||||
+ struct led_classdev cdev;
|
||||
+ char name[];
|
||||
+};
|
||||
+
|
||||
struct ath_softc {
|
||||
struct ieee80211_hw *hw;
|
||||
struct device *dev;
|
||||
@@ -1035,9 +1045,8 @@ struct ath_softc {
|
||||
@@ -1035,9 +1046,8 @@ struct ath_softc {
|
||||
spinlock_t chan_lock;
|
||||
|
||||
#ifdef CPTCFG_MAC80211_LEDS
|
||||
@@ -38,7 +39,7 @@
|
||||
#ifdef CPTCFG_ATH9K_DEBUGFS
|
||||
--- a/drivers/net/wireless/ath/ath9k/gpio.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
|
||||
@@ -39,61 +39,111 @@ static void ath_fill_led_pin(struct ath_
|
||||
@@ -39,61 +39,112 @@ static void ath_fill_led_pin(struct ath_
|
||||
else
|
||||
ah->led_pin = ATH_LED_PIN_DEF;
|
||||
}
|
||||
@@ -49,16 +50,17 @@
|
||||
+{
|
||||
+ struct ath_led *led = container_of(led_cdev, struct ath_led, cdev);
|
||||
+ struct ath_softc *sc = led->sc;
|
||||
+ const struct gpio_led *gpio = &led->gpio;
|
||||
+
|
||||
+ ath9k_ps_wakeup(sc);
|
||||
+ ath9k_hw_set_gpio(sc->sc_ah, led->gpio->gpio,
|
||||
+ (brightness != LED_OFF) ^ led->gpio->active_low);
|
||||
+ ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio,
|
||||
+ (brightness != LED_OFF) ^ gpio->active_low);
|
||||
+ ath9k_ps_restore(sc);
|
||||
+}
|
||||
+
|
||||
+static int ath_add_led(struct ath_softc *sc, struct ath_led *led)
|
||||
+{
|
||||
+ const struct gpio_led *gpio = led->gpio;
|
||||
+ const struct gpio_led *gpio = &led->gpio;
|
||||
+ int ret;
|
||||
+
|
||||
+ led->cdev.name = gpio->name;
|
||||
@@ -94,30 +96,28 @@
|
||||
- u32 val = (brightness == LED_OFF);
|
||||
+ struct ath_led *led;
|
||||
+ struct gpio_led *gpio;
|
||||
+ char *_name;
|
||||
+ int ret;
|
||||
|
||||
- if (sc->sc_ah->config.led_active_high)
|
||||
- val = !val;
|
||||
+ led = kzalloc(sizeof(*led) + sizeof(*gpio) + strlen(name) + 1,
|
||||
+ GFP_KERNEL);
|
||||
+ led = kzalloc(struct_size(led, name, strlen(name) + 1), GFP_KERNEL);
|
||||
+ if (!led)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ led->gpio = gpio = (struct gpio_led *) (led + 1);
|
||||
+ _name = (char *) (led->gpio + 1);
|
||||
+ strcpy(led->name, name);
|
||||
+
|
||||
+ strcpy(_name, name);
|
||||
+ gpio->name = _name;
|
||||
+ gpio = &led->gpio;
|
||||
+ gpio->name = led->name;
|
||||
+ gpio->gpio = gpio_num;
|
||||
+ gpio->active_low = active_low;
|
||||
+ gpio->default_trigger = trigger;
|
||||
+
|
||||
+ ret = ath_add_led(sc, led);
|
||||
+ if (unlikely(ret < 0))
|
||||
+ kfree(led);
|
||||
+ if (likely(ret >= 0))
|
||||
+ return ret;
|
||||
|
||||
- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, val);
|
||||
+ kfree(led);
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
@@ -126,6 +126,7 @@
|
||||
- if (!sc->led_registered)
|
||||
- return;
|
||||
+ struct ath_led *led;
|
||||
+ struct gpio_led *gpio;
|
||||
|
||||
- ath_led_brightness(&sc->led_cdev, LED_OFF);
|
||||
- led_classdev_unregister(&sc->led_cdev);
|
||||
@@ -136,7 +137,8 @@
|
||||
+ list_del(&led->list);
|
||||
+ ath_led_brightness(&led->cdev, LED_OFF);
|
||||
+ led_classdev_unregister(&led->cdev);
|
||||
+ ath9k_hw_gpio_free(sc->sc_ah, led->gpio->gpio);
|
||||
+ gpio = &led->gpio;
|
||||
+ ath9k_hw_gpio_free(sc->sc_ah, gpio->gpio);
|
||||
+ kfree(led);
|
||||
+ }
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath9k/gpio.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
|
||||
@@ -73,8 +73,11 @@ static int ath_add_led(struct ath_softc
|
||||
@@ -74,8 +74,11 @@ static int ath_add_led(struct ath_softc
|
||||
ath9k_hw_gpio_request_out(sc->sc_ah, gpio->gpio, gpio->name,
|
||||
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
#include "common.h"
|
||||
#include "debug.h"
|
||||
@@ -1047,6 +1049,10 @@ struct ath_softc {
|
||||
@@ -1048,6 +1050,10 @@ struct ath_softc {
|
||||
#ifdef CPTCFG_MAC80211_LEDS
|
||||
const char *led_default_trigger;
|
||||
struct list_head leds;
|
||||
@@ -157,7 +157,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
static void ath_fill_led_pin(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
@@ -79,6 +189,12 @@ static int ath_add_led(struct ath_softc
|
||||
@@ -80,6 +190,12 @@ static int ath_add_led(struct ath_softc
|
||||
else
|
||||
ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low);
|
||||
|
||||
@@ -170,7 +170,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -117,16 +233,23 @@ void ath_deinit_leds(struct ath_softc *s
|
||||
@@ -117,6 +233,11 @@ void ath_deinit_leds(struct ath_softc *s
|
||||
|
||||
while (!list_empty(&sc->leds)) {
|
||||
led = list_first_entry(&sc->leds, struct ath_led, list);
|
||||
@@ -182,27 +182,20 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
list_del(&led->list);
|
||||
ath_led_brightness(&led->cdev, LED_OFF);
|
||||
led_classdev_unregister(&led->cdev);
|
||||
ath9k_hw_gpio_free(sc->sc_ah, led->gpio->gpio);
|
||||
@@ -124,6 +245,7 @@ void ath_deinit_leds(struct ath_softc *s
|
||||
ath9k_hw_gpio_free(sc->sc_ah, gpio->gpio);
|
||||
kfree(led);
|
||||
}
|
||||
+ ath9k_unregister_gpio_chip(sc);
|
||||
}
|
||||
|
||||
void ath_init_leds(struct ath_softc *sc)
|
||||
{
|
||||
+ struct device_node *np = sc->dev->of_node;
|
||||
char led_name[32];
|
||||
const char *trigger;
|
||||
|
||||
@@ -135,6 +258,15 @@ void ath_init_leds(struct ath_softc *sc)
|
||||
@@ -136,6 +258,12 @@ void ath_init_leds(struct ath_softc *sc)
|
||||
if (AR_SREV_9100(sc->sc_ah))
|
||||
return;
|
||||
|
||||
+ if (!np)
|
||||
+ ath9k_register_gpio_chip(sc);
|
||||
+
|
||||
+ /* setup gpio controller only if requested and skip the led_pin setup */
|
||||
+ if (of_property_read_bool(np, "gpio-controller")) {
|
||||
+ if (device_property_present(sc->dev, "gpio-controller")) {
|
||||
+ ath9k_register_gpio_chip(sc);
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Thu, 5 Mar 2026 17:04:11 +0000
|
||||
Subject: [PATCH] mac80211: fix crash in ieee80211_chan_bw_change for AP_VLAN
|
||||
stations
|
||||
|
||||
ieee80211_chan_bw_change() iterates all stations and accesses
|
||||
link->reserved.oper via sta->sdata->link[link_id]. For stations on
|
||||
AP_VLAN interfaces (e.g. 4addr WDS clients), sta->sdata points to
|
||||
the VLAN sdata, whose link never participates in chanctx reservations.
|
||||
This leaves link->reserved.oper zero-initialized with chan == NULL,
|
||||
causing a NULL pointer dereference in __ieee80211_sta_cap_rx_bw()
|
||||
when accessing chandef->chan->band during CSA.
|
||||
|
||||
Resolve the VLAN sdata to its parent AP sdata using get_bss_sdata()
|
||||
before accessing link data.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/chan.c
|
||||
+++ b/net/mac80211/chan.c
|
||||
@@ -441,13 +441,15 @@ static void ieee80211_chan_bw_change(str
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(sta, &local->sta_list,
|
||||
list) {
|
||||
- struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
+ struct ieee80211_sub_if_data *sdata;
|
||||
enum ieee80211_sta_rx_bandwidth new_sta_bw;
|
||||
unsigned int link_id;
|
||||
|
||||
if (!ieee80211_sdata_running(sta->sdata))
|
||||
continue;
|
||||
|
||||
+ sdata = get_bss_sdata(sta->sdata);
|
||||
+
|
||||
for (link_id = 0; link_id < ARRAY_SIZE(sta->sdata->link); link_id++) {
|
||||
struct ieee80211_link_data *link =
|
||||
rcu_dereference(sdata->link[link_id]);
|
||||
+2
-2
@@ -48,7 +48,7 @@
|
||||
if (sdata->wdev.links[link_id].cac_started)
|
||||
--- a/net/mac80211/chan.c
|
||||
+++ b/net/mac80211/chan.c
|
||||
@@ -644,10 +644,11 @@ ieee80211_find_chanctx(struct ieee80211_
|
||||
@@ -646,10 +646,11 @@ ieee80211_find_chanctx(struct ieee80211_
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
struct ieee80211_link_data *link;
|
||||
struct ieee80211_channel *chan;
|
||||
int radio_idx;
|
||||
@@ -658,14 +659,25 @@ bool ieee80211_is_radar_required(struct
|
||||
@@ -660,14 +661,25 @@ bool ieee80211_is_radar_required(struct
|
||||
return false;
|
||||
|
||||
for_each_sdata_link(local, link) {
|
||||
|
||||
@@ -8,9 +8,9 @@ PKG_LICENSE_FILES:=
|
||||
|
||||
PKG_SOURCE_URL:=https://github.com/openwrt/mt76
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_DATE:=2026-03-01
|
||||
PKG_SOURCE_VERSION:=ee84094d71ba6a361d8cd80392ee79fea64462ec
|
||||
PKG_MIRROR_HASH:=30d9f42e2c5c2583553f384122b4e380f71a3f579d1cda67a2c533485e30ef5d
|
||||
PKG_SOURCE_DATE:=2026-03-05
|
||||
PKG_SOURCE_VERSION:=9f95baf93a070692ed922a2fc57ef8bfde801c84
|
||||
PKG_MIRROR_HASH:=eaca371ec6f8d0f089d098a3f7fc8c5819aea090e05f4f3d9e8a9b2a2d4f2ff8
|
||||
|
||||
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
|
||||
PKG_USE_NINJA:=0
|
||||
@@ -328,6 +328,12 @@ define KernelPackage/mt7996e
|
||||
AUTOLOAD:=$(call AutoProbe,mt7996e)
|
||||
endef
|
||||
|
||||
define KernelPackage/mt7990-firmware
|
||||
$(KernelPackage/mt76-default)
|
||||
TITLE:=MediaTek MT7990 firmware
|
||||
DEPENDS+=+kmod-mt7996e
|
||||
endef
|
||||
|
||||
define KernelPackage/mt7992-firmware
|
||||
$(KernelPackage/mt76-default)
|
||||
TITLE:=MediaTek MT7992 firmware
|
||||
@@ -665,6 +671,16 @@ define KernelPackage/mt7925-firmware/install
|
||||
$(1)/lib/firmware/mediatek/mt7925
|
||||
endef
|
||||
|
||||
define KernelPackage/mt7990-firmware/install
|
||||
$(INSTALL_DIR) $(1)/lib/firmware/mediatek/mt7996
|
||||
cp \
|
||||
$(PKG_BUILD_DIR)/firmware/mt7996/mt7990_eeprom.bin \
|
||||
$(PKG_BUILD_DIR)/firmware/mt7996/mt7990_eeprom_2i5i.bin \
|
||||
$(PKG_BUILD_DIR)/firmware/mt7996/mt7990_rom_patch.bin \
|
||||
$(PKG_BUILD_DIR)/firmware/mt7996/mt7990_wm.bin \
|
||||
$(1)/lib/firmware/mediatek/mt7996
|
||||
endef
|
||||
|
||||
define KernelPackage/mt7992-firmware/install
|
||||
$(INSTALL_DIR) $(1)/lib/firmware/mediatek/mt7996
|
||||
cp \
|
||||
@@ -769,6 +785,7 @@ $(eval $(call KernelPackage,mt7921e))
|
||||
$(eval $(call KernelPackage,mt7925u))
|
||||
$(eval $(call KernelPackage,mt7925e))
|
||||
$(eval $(call KernelPackage,mt7996e))
|
||||
$(eval $(call KernelPackage,mt7990-firmware))
|
||||
$(eval $(call KernelPackage,mt7992-firmware))
|
||||
$(eval $(call KernelPackage,mt7992-23-firmware))
|
||||
$(eval $(call KernelPackage,mt7996-firmware-common))
|
||||
|
||||
@@ -12,9 +12,9 @@ PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL=$(PROJECT_GIT)/project/omcproxy.git
|
||||
PKG_MIRROR_HASH:=4e62452e3b5a6df917e07db6e19b09e0fb67bac246b8fc3f9e6a35a12d90894b
|
||||
PKG_SOURCE_DATE:=2025-10-04
|
||||
PKG_SOURCE_VERSION:=fc2eac19ea031411ab589cd92d713961549d6a46
|
||||
PKG_MIRROR_HASH:=41d85cf544e3833df6a605827ab625a4028274ff46aadee13b8644eb25f8edae
|
||||
PKG_SOURCE_DATE:=2026-03-07
|
||||
PKG_SOURCE_VERSION:=3abb601ab77f5e914a3203e5d0c8ae7fb1579bae
|
||||
PKG_MAINTAINER:=Steven Barth <cyrus@openwrt.org>
|
||||
PKG_LICENSE:=Apache-2.0
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ include $(INCLUDE_DIR)/kernel.mk
|
||||
|
||||
PKG_NAME:=ppp
|
||||
PKG_VERSION:=2.5.2
|
||||
PKG_RELEASE:=2
|
||||
PKG_RELEASE:=3
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://github.com/ppp-project/ppp
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
From f8d994052e3858848ce11318085e04fe7a1cfb28 Mon Sep 17 00:00:00 2001
|
||||
From: LGA1150 <9155358+LGA1150@users.noreply.github.com>
|
||||
Date: Thu, 5 Mar 2026 05:41:30 +0800
|
||||
Subject: [PATCH] pppd: fix memcpy overlap (#579)
|
||||
|
||||
memcpy() with overlapping src and dest buffers is an undefined behavior
|
||||
in C. In the current code, a ConfRej response is generated by copying
|
||||
input data in-place, where the dest address is lower than the src.
|
||||
This happens to work in practice because memcpy() forward-copies data,
|
||||
matching the behavior of memmove() in this case.
|
||||
|
||||
However, if FORTIFY_SOURCE or Address Sanitizer is enabled, memcpy()
|
||||
will detect the overlap at run time and abort the program.
|
||||
|
||||
Replace the memcpy() with memmove() to ensure a well-defined behavior.
|
||||
|
||||
Reported-by: Filippo Carletti <filippo.carletti@gmail.com>
|
||||
Closes: #576
|
||||
|
||||
Signed-off-by: Qingfang Deng <dqfext@gmail.com>
|
||||
---
|
||||
pppd/pppd-private.h | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/pppd/pppd-private.h b/pppd/pppd-private.h
|
||||
index 5f841824..29ea940c 100644
|
||||
--- a/pppd/pppd-private.h
|
||||
+++ b/pppd/pppd-private.h
|
||||
@@ -525,7 +525,7 @@ int parse_dotted_ip(char *, u_int32_t *)
|
||||
#define TIMEOUT(r, f, t) ppp_timeout((r), (f), (t), 0)
|
||||
#define UNTIMEOUT(r, f) ppp_untimeout((r), (f))
|
||||
|
||||
-#define BCOPY(s, d, l) memcpy(d, s, l)
|
||||
+#define BCOPY(s, d, l) memmove(d, s, l)
|
||||
#define BZERO(s, n) memset(s, 0, n)
|
||||
#define BCMP(s1, s2, l) memcmp(s1, s2, l)
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
From f691c224e12ee13a1b317a1838d150f1ffef14a1 Mon Sep 17 00:00:00 2001
|
||||
From: Mateusz Poliwczak <mpoliwczak34@gmail.com>
|
||||
Date: Wed, 11 Feb 2026 00:40:14 +0100
|
||||
Subject: [PATCH] Remove MRU limit on PPPoE (#573)
|
||||
|
||||
Fixes #331
|
||||
|
||||
Signed-off-by: Mateusz Poliwczak <mpoliwczak34@gmail.com>
|
||||
---
|
||||
pppd/plugins/pppoe/plugin.c | 5 -----
|
||||
1 file changed, 5 deletions(-)
|
||||
|
||||
diff --git a/pppd/plugins/pppoe/plugin.c b/pppd/plugins/pppoe/plugin.c
|
||||
index b429a2fd..0f672166 100644
|
||||
--- a/pppd/plugins/pppoe/plugin.c
|
||||
+++ b/pppd/plugins/pppoe/plugin.c
|
||||
@@ -446,11 +446,6 @@ void pppoe_check_options(void)
|
||||
lcp_allowoptions[0].neg_pcompression = 0;
|
||||
lcp_wantoptions[0].neg_pcompression = 0;
|
||||
|
||||
- if (lcp_allowoptions[0].mru > MAX_PPPOE_MTU)
|
||||
- lcp_allowoptions[0].mru = MAX_PPPOE_MTU;
|
||||
- if (lcp_wantoptions[0].mru > MAX_PPPOE_MTU)
|
||||
- lcp_wantoptions[0].mru = MAX_PPPOE_MTU;
|
||||
-
|
||||
/* Save configuration */
|
||||
conn->storedmtu = lcp_allowoptions[0].mru;
|
||||
conn->storedmru = lcp_wantoptions[0].mru;
|
||||
@@ -11,6 +11,7 @@ if len(argv) != 2:
|
||||
exit(1)
|
||||
|
||||
output_path = Path(argv[1])
|
||||
output_dir = output_path.parent
|
||||
|
||||
assert getenv("WORK_DIR"), "$WORK_DIR required"
|
||||
|
||||
@@ -28,6 +29,12 @@ def get_initial_output(image_info):
|
||||
return image_info
|
||||
|
||||
|
||||
def add_artifact(artifact, prefix="openwrt-"):
|
||||
files = list(output_dir.glob(f"{prefix}{artifact}-*"))
|
||||
if len(files) == 1:
|
||||
output[artifact] = str(files[0].name)
|
||||
|
||||
|
||||
for json_file in work_dir.glob("*.json"):
|
||||
image_info = json.loads(json_file.read_text())
|
||||
|
||||
@@ -78,6 +85,11 @@ if output:
|
||||
"release": linux_release,
|
||||
"vermagic": linux_vermagic,
|
||||
}
|
||||
|
||||
for artifact in "imagebuilder", "sdk", "toolchain":
|
||||
filename = add_artifact(artifact)
|
||||
add_artifact("llvm-bpf", prefix="")
|
||||
|
||||
output_path.write_text(json.dumps(output, sort_keys=True, separators=(",", ":")))
|
||||
else:
|
||||
print("JSON info file script could not find any JSON files for target")
|
||||
|
||||
@@ -237,13 +237,14 @@ CONFIG_MTD_SPLIT_FIT_FW=y
|
||||
CONFIG_MTD_UBI=y
|
||||
CONFIG_MTD_UBI_BEB_LIMIT=20
|
||||
CONFIG_MTD_UBI_BLOCK=y
|
||||
CONFIG_MTD_UBI_NVMEM=y
|
||||
CONFIG_MTD_UBI_WL_THRESHOLD=4096
|
||||
CONFIG_MTK_NET_PHYLIB=y
|
||||
CONFIG_MUTEX_SPIN_ON_OWNER=y
|
||||
CONFIG_NEED_DMA_MAP_STATE=y
|
||||
CONFIG_NEED_SG_DMA_LENGTH=y
|
||||
CONFIG_NET_AIROHA=y
|
||||
CONFIG_NET_AIROHA_FLOW_STATS=y
|
||||
# CONFIG_NET_AIROHA_FLOW_STATS is not set
|
||||
CONFIG_NET_AIROHA_NPU=y
|
||||
CONFIG_NET_DEVLINK=y
|
||||
CONFIG_NET_DSA=y
|
||||
@@ -395,6 +396,7 @@ CONFIG_TREE_RCU=y
|
||||
CONFIG_TREE_SRCU=y
|
||||
CONFIG_UBIFS_FS=y
|
||||
# CONFIG_UNMAP_KERNEL_AT_EL0 is not set
|
||||
CONFIG_UIMAGE_FIT_BLK=y
|
||||
CONFIG_USB_SUPPORT=y
|
||||
CONFIG_USER_STACKTRACE_SUPPORT=y
|
||||
CONFIG_VDSO_GETRANDOM=y
|
||||
|
||||
@@ -232,6 +232,12 @@
|
||||
};
|
||||
};
|
||||
|
||||
&npu {
|
||||
firmware-name = "airoha/en7581_MT7996_npu_rv32.bin",
|
||||
"airoha/en7581_MT7996_npu_data.bin";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
ð {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
@@ -54,6 +54,11 @@
|
||||
no-map;
|
||||
reg = <0x0 0x90c00000 0x0 0x6800>;
|
||||
};
|
||||
|
||||
npu_ba: npu-ba@90c06800 {
|
||||
no-map;
|
||||
reg = <0x0 0x90c06800 0x0 0x200000>;
|
||||
};
|
||||
};
|
||||
|
||||
psci {
|
||||
@@ -855,9 +860,10 @@
|
||||
<GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
|
||||
memory-region = <&npu_binary>, <&npu_pkt>, <&npu_txpkt>,
|
||||
<&npu_txbufid>;
|
||||
<&npu_txbufid>, <&npu_ba>;
|
||||
memory-region-names = "binary", "pkt", "tx-pkt",
|
||||
"tx-bufid";
|
||||
"tx-bufid", "ba";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
eth: ethernet@1fb50000 {
|
||||
|
||||
@@ -12,6 +12,33 @@ define Build/an7581-bl31-uboot
|
||||
cat $(STAGING_DIR_IMAGE)/an7581_$1-bl31-u-boot.fip >> $@
|
||||
endef
|
||||
|
||||
define Build/an7581-chainloader
|
||||
$(INSTALL_DIR) $(KDIR)/chainload-fit-$(notdir $@)
|
||||
@if [ -f "$(STAGING_DIR_IMAGE)/an7581_$1-u-boot.bin.lzma" ]; then \
|
||||
KERNEL="$(STAGING_DIR_IMAGE)/an7581_$1-u-boot.bin.lzma"; \
|
||||
COMP="lzma"; \
|
||||
else \
|
||||
KERNEL="$(STAGING_DIR_IMAGE)/an7581_$1-u-boot.bin"; \
|
||||
COMP="none"; \
|
||||
fi; \
|
||||
$(TOPDIR)/scripts/mkits.sh \
|
||||
-D $(DEVICE_NAME) \
|
||||
-o $(KDIR)/chainload-fit-$(notdir $@)/u-boot.its \
|
||||
-k $$KERNEL \
|
||||
-C $$COMP \
|
||||
-a 0x80200000 -e 0x80200000 \
|
||||
-c conf-uboot \
|
||||
-A arm64 -v u-boot \
|
||||
-d $(STAGING_DIR_IMAGE)/an7581_$1-u-boot.dtb \
|
||||
-s 0x82000000
|
||||
PATH=$(LINUX_DIR)/scripts/dtc:$(PATH) \
|
||||
$(STAGING_DIR_HOST)/bin/mkimage \
|
||||
-D "-i $(KDIR)/chainload-fit-$(notdir $@)" \
|
||||
-f $(KDIR)/chainload-fit-$(notdir $@)/u-boot.its \
|
||||
$(STAGING_DIR_IMAGE)/an7581_$1-chainload-u-boot.itb
|
||||
cat $(STAGING_DIR_IMAGE)/an7581_$1-chainload-u-boot.itb >> $@
|
||||
endef
|
||||
|
||||
define Device/FitImageLzma
|
||||
KERNEL_SUFFIX := -uImage.itb
|
||||
KERNEL = kernel-bin | lzma | fit lzma $$(KDIR)/image-$$(DEVICE_DTS).dtb
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
From 875a59c9a9e584d99d8e9e5aa8435ec9300bfe91 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 8 Jan 2026 16:05:08 +0100
|
||||
Subject: [PATCH] net: airoha: npu: Init BA memory region if provided via DTS
|
||||
|
||||
Initialize NPU Block Ack memory region if reserved via DTS.
|
||||
Block Ack memory region is used by NPU MT7996 (Eagle) offloading.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/20260108-airoha-ba-memory-region-v3-2-bf1814e5dcc4@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/airoha/airoha_npu.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/drivers/net/ethernet/airoha/airoha_npu.c b/drivers/net/ethernet/airoha/airoha_npu.c
|
||||
index 22f72c14606599..a56b3780bb627c 100644
|
||||
--- a/drivers/net/ethernet/airoha/airoha_npu.c
|
||||
+++ b/drivers/net/ethernet/airoha/airoha_npu.c
|
||||
@@ -519,6 +519,14 @@ static int airoha_npu_wlan_init_memory(struct airoha_npu *npu)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
+ if (of_property_match_string(npu->dev->of_node, "memory-region-names",
|
||||
+ "ba") >= 0) {
|
||||
+ cmd = WLAN_FUNC_SET_WAIT_DRAM_BA_NODE_ADDR;
|
||||
+ err = airoha_npu_wlan_set_reserved_memory(npu, 0, "ba", cmd);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
cmd = WLAN_FUNC_SET_WAIT_IS_FORCE_TO_CPU;
|
||||
return airoha_npu_wlan_msg_send(npu, 0, cmd, &val, sizeof(val),
|
||||
GFP_KERNEL);
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
From 3847173525e307ebcd23bd4863da943ea78b0057 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 20 Jan 2026 11:17:18 +0100
|
||||
Subject: [PATCH] net: airoha: npu: Add the capability to read firmware names
|
||||
from dts
|
||||
|
||||
Introduce the capability to read the firmware binary names from device-tree
|
||||
using the firmware-name property if available.
|
||||
This patch is needed because NPU firmware binaries are board specific since
|
||||
they depend on the MediaTek WiFi chip used on the board (e.g. MT7996 or
|
||||
MT7992) and the WiFi chip version info is not available in the NPU driver.
|
||||
This is a preliminary patch to enable MT76 NPU offloading if the Airoha SoC
|
||||
is equipped with MT7996 (Eagle) WiFi chipset.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Link: https://patch.msgid.link/20260120-airoha-npu-firmware-name-v4-2-88999628b4c1@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/airoha/airoha_npu.c | 46 ++++++++++++++++++++----
|
||||
1 file changed, 40 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/airoha/airoha_npu.c b/drivers/net/ethernet/airoha/airoha_npu.c
|
||||
index a56b3780bb627c..89f22f3f47dc56 100644
|
||||
--- a/drivers/net/ethernet/airoha/airoha_npu.c
|
||||
+++ b/drivers/net/ethernet/airoha/airoha_npu.c
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
#define NPU_EN7581_FIRMWARE_DATA "airoha/en7581_npu_data.bin"
|
||||
#define NPU_EN7581_FIRMWARE_RV32 "airoha/en7581_npu_rv32.bin"
|
||||
+#define NPU_EN7581_7996_FIRMWARE_DATA "airoha/en7581_MT7996_npu_data.bin"
|
||||
+#define NPU_EN7581_7996_FIRMWARE_RV32 "airoha/en7581_MT7996_npu_rv32.bin"
|
||||
#define NPU_AN7583_FIRMWARE_DATA "airoha/an7583_npu_data.bin"
|
||||
#define NPU_AN7583_FIRMWARE_RV32 "airoha/an7583_npu_rv32.bin"
|
||||
#define NPU_EN7581_FIRMWARE_RV32_MAX_SIZE 0x200000
|
||||
@@ -195,18 +197,18 @@ static int airoha_npu_send_msg(struct airoha_npu *npu, int func_id,
|
||||
}
|
||||
|
||||
static int airoha_npu_load_firmware(struct device *dev, void __iomem *addr,
|
||||
- const struct airoha_npu_fw *fw_info)
|
||||
+ const char *fw_name, int fw_max_size)
|
||||
{
|
||||
const struct firmware *fw;
|
||||
int ret;
|
||||
|
||||
- ret = request_firmware(&fw, fw_info->name, dev);
|
||||
+ ret = request_firmware(&fw, fw_name, dev);
|
||||
if (ret)
|
||||
return ret == -ENOENT ? -EPROBE_DEFER : ret;
|
||||
|
||||
- if (fw->size > fw_info->max_size) {
|
||||
+ if (fw->size > fw_max_size) {
|
||||
dev_err(dev, "%s: fw size too overlimit (%zu)\n",
|
||||
- fw_info->name, fw->size);
|
||||
+ fw_name, fw->size);
|
||||
ret = -E2BIG;
|
||||
goto out;
|
||||
}
|
||||
@@ -218,6 +220,28 @@ static int airoha_npu_load_firmware(struct device *dev, void __iomem *addr,
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static int
|
||||
+airoha_npu_load_firmware_from_dts(struct device *dev, void __iomem *addr,
|
||||
+ void __iomem *base)
|
||||
+{
|
||||
+ const char *fw_names[2];
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = of_property_read_string_array(dev->of_node, "firmware-name",
|
||||
+ fw_names, ARRAY_SIZE(fw_names));
|
||||
+ if (ret != ARRAY_SIZE(fw_names))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ ret = airoha_npu_load_firmware(dev, addr, fw_names[0],
|
||||
+ NPU_EN7581_FIRMWARE_RV32_MAX_SIZE);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return airoha_npu_load_firmware(dev, base + REG_NPU_LOCAL_SRAM,
|
||||
+ fw_names[1],
|
||||
+ NPU_EN7581_FIRMWARE_DATA_MAX_SIZE);
|
||||
+}
|
||||
+
|
||||
static int airoha_npu_run_firmware(struct device *dev, void __iomem *base,
|
||||
struct resource *res)
|
||||
{
|
||||
@@ -233,14 +257,22 @@ static int airoha_npu_run_firmware(struct device *dev, void __iomem *base,
|
||||
if (IS_ERR(addr))
|
||||
return PTR_ERR(addr);
|
||||
|
||||
+ /* Try to load firmware images using the firmware names provided via
|
||||
+ * dts if available.
|
||||
+ */
|
||||
+ if (of_find_property(dev->of_node, "firmware-name", NULL))
|
||||
+ return airoha_npu_load_firmware_from_dts(dev, addr, base);
|
||||
+
|
||||
/* Load rv32 npu firmware */
|
||||
- ret = airoha_npu_load_firmware(dev, addr, &soc->fw_rv32);
|
||||
+ ret = airoha_npu_load_firmware(dev, addr, soc->fw_rv32.name,
|
||||
+ soc->fw_rv32.max_size);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Load data npu firmware */
|
||||
return airoha_npu_load_firmware(dev, base + REG_NPU_LOCAL_SRAM,
|
||||
- &soc->fw_data);
|
||||
+ soc->fw_data.name,
|
||||
+ soc->fw_data.max_size);
|
||||
}
|
||||
|
||||
static irqreturn_t airoha_npu_mbox_handler(int irq, void *npu_instance)
|
||||
@@ -790,6 +822,8 @@ module_platform_driver(airoha_npu_driver);
|
||||
|
||||
MODULE_FIRMWARE(NPU_EN7581_FIRMWARE_DATA);
|
||||
MODULE_FIRMWARE(NPU_EN7581_FIRMWARE_RV32);
|
||||
+MODULE_FIRMWARE(NPU_EN7581_7996_FIRMWARE_DATA);
|
||||
+MODULE_FIRMWARE(NPU_EN7581_7996_FIRMWARE_RV32);
|
||||
MODULE_FIRMWARE(NPU_AN7583_FIRMWARE_DATA);
|
||||
MODULE_FIRMWARE(NPU_AN7583_FIRMWARE_RV32);
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -24,25 +24,27 @@
|
||||
};
|
||||
|
||||
gpio2: key-mux1 {
|
||||
compatible = "gpio-cascade";
|
||||
compatible = "gpio-line-mux";
|
||||
mux-controls = <&mux>;
|
||||
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
// GPIOs used by this node, the mux pin
|
||||
upstream-gpios = <&gpio 12 GPIO_ACTIVE_HIGH>; /* 1y */
|
||||
muxed-gpios = <&gpio 12 GPIO_ACTIVE_HIGH>; /* 1y */
|
||||
gpio-line-mux-states = <0>, <1>, <2>, <3>;
|
||||
};
|
||||
|
||||
gpio3: key-mux2 {
|
||||
compatible = "gpio-cascade";
|
||||
compatible = "gpio-line-mux";
|
||||
mux-controls = <&mux>;
|
||||
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
// GPIOs used by this node, the mux pin
|
||||
upstream-gpios = <&gpio 14 GPIO_ACTIVE_HIGH>; /* 2y */
|
||||
muxed-gpios = <&gpio 14 GPIO_ACTIVE_HIGH>; /* 2y */
|
||||
gpio-line-mux-states = <1>, <2>, <3>;
|
||||
};
|
||||
|
||||
keys {
|
||||
@@ -80,21 +82,21 @@
|
||||
usb {
|
||||
label = "usb";
|
||||
linux,code = <BTN_2>;
|
||||
gpios = <&gpio3 1 GPIO_ACTIVE_LOW>;
|
||||
gpios = <&gpio3 0 GPIO_ACTIVE_LOW>;
|
||||
debounce-interval = <60>;
|
||||
};
|
||||
|
||||
router_auto {
|
||||
label = "router_auto";
|
||||
linux,code = <BTN_6>;
|
||||
gpios = <&gpio3 2 GPIO_ACTIVE_HIGH>;
|
||||
gpios = <&gpio3 1 GPIO_ACTIVE_HIGH>;
|
||||
debounce-interval = <60>;
|
||||
};
|
||||
|
||||
movie_on {
|
||||
label = "movie_on";
|
||||
linux,code = <BTN_4>;
|
||||
gpios = <&gpio3 3 GPIO_ACTIVE_HIGH>;
|
||||
gpios = <&gpio3 2 GPIO_ACTIVE_HIGH>;
|
||||
debounce-interval = <60>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -688,7 +688,7 @@ define Device/buffalo_wzr-hp-g300nh
|
||||
SOC := ar9132
|
||||
BUFFALO_PRODUCT := WZR-HP-G300NH
|
||||
BUFFALO_HWVER := 1
|
||||
DEVICE_PACKAGES := kmod-gpio-cascade kmod-mux-gpio kmod-usb2 kmod-usb-ledtrig-usbport
|
||||
DEVICE_PACKAGES := kmod-gpio-line-mux kmod-mux-gpio kmod-usb2 kmod-usb-ledtrig-usbport
|
||||
BLOCKSIZE := 128k
|
||||
IMAGE_SIZE := 32128k
|
||||
SUPPORTED_DEVICES += wzr-hp-g300nh
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
include ./common-tp-link.mk
|
||||
|
||||
define Device/tplink_rex5x-v1
|
||||
define Device/tplink_rex5x
|
||||
$(Device/tplink-safeloader)
|
||||
SOC := qca9558
|
||||
BLOCKSIZE := 4k
|
||||
IMAGE_SIZE := 7680k
|
||||
KERNEL_SIZE := 6016k
|
||||
DEVICE_PACKAGES := kmod-ath10k-ct-smallbuffers ath10k-firmware-qca988x-ct
|
||||
DEVICE_COMPAT_VERSION := 2.0
|
||||
DEVICE_COMPAT_MESSAGE := Partition layout has changed compared to older versions by utilizing unused flash. \
|
||||
Upgrade via sysupgrade mechanism (-F) will only work if flashed image still fits to the size of old partition (6016 KiB).
|
||||
DEVICE_COMPAT_VERSION := 3.0
|
||||
DEVICE_COMPAT_MESSAGE := Partition layout and blocksize changed. Use sysupgrade -F; image must not exceed 6016 KiB (5.875 MB).
|
||||
IMAGE/sysupgrade.bin := append-kernel | append-rootfs | pad-rootfs | check-size | append-metadata
|
||||
endef
|
||||
|
||||
define Device/tplink_re355-v1
|
||||
$(Device/tplink_rex5x-v1)
|
||||
$(Device/tplink_rex5x)
|
||||
DEVICE_MODEL := RE355
|
||||
DEVICE_VARIANT := v1
|
||||
TPLINK_BOARD_ID := RE355
|
||||
@@ -22,7 +22,7 @@ endef
|
||||
TARGET_DEVICES += tplink_re355-v1
|
||||
|
||||
define Device/tplink_re450-v1
|
||||
$(Device/tplink_rex5x-v1)
|
||||
$(Device/tplink_rex5x)
|
||||
DEVICE_MODEL := RE450
|
||||
DEVICE_VARIANT := v1
|
||||
TPLINK_BOARD_ID := RE450
|
||||
@@ -31,17 +31,10 @@ endef
|
||||
TARGET_DEVICES += tplink_re450-v1
|
||||
|
||||
define Device/tplink_re450-v2
|
||||
$(Device/tplink-safeloader)
|
||||
$(Device/tplink_rex5x)
|
||||
SOC := qca9563
|
||||
IMAGE_SIZE := 7680k
|
||||
KERNEL_SIZE := 6016k
|
||||
DEVICE_MODEL := RE450
|
||||
DEVICE_VARIANT := v2
|
||||
DEVICE_PACKAGES := kmod-ath10k-ct-smallbuffers ath10k-firmware-qca988x-ct
|
||||
DEVICE_COMPAT_VERSION := 2.0
|
||||
DEVICE_COMPAT_MESSAGE := Partition layout has changed compared to older versions by utilizing unused flash. \
|
||||
Upgrade via sysupgrade mechanism (-F) will only work if flashed image still fits to the size of old partition (6016 KiB).
|
||||
IMAGE/sysupgrade.bin := append-kernel | append-rootfs | pad-rootfs | check-size | append-metadata
|
||||
TPLINK_BOARD_ID := RE450-V2
|
||||
LOADER_TYPE := elf
|
||||
endef
|
||||
|
||||
@@ -55,14 +55,14 @@ Tested-by: Koen Vandeputte <koen.vandeputte@ncentric.com>
|
||||
depends on ARCH_RENESAS || COMPILE_TEST
|
||||
--- a/drivers/gpio/Makefile
|
||||
+++ b/drivers/gpio/Makefile
|
||||
@@ -85,6 +85,7 @@ obj-$(CONFIG_GPIO_IXP4XX) += gpio-ixp4x
|
||||
@@ -84,6 +84,7 @@ obj-$(CONFIG_GPIO_IXP4XX) += gpio-ixp4x
|
||||
obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o
|
||||
obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o
|
||||
obj-$(CONFIG_GPIO_LATCH) += gpio-latch.o
|
||||
+obj-$(CONFIG_GPIO_LATCH_MIKROTIK) += gpio-latch-mikrotik.o
|
||||
obj-$(CONFIG_GPIO_LINE_MUX) += gpio-line-mux.o
|
||||
obj-$(CONFIG_GPIO_LJCA) += gpio-ljca.o
|
||||
obj-$(CONFIG_GPIO_LOGICVC) += gpio-logicvc.o
|
||||
obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o
|
||||
@@ -138,6 +139,7 @@ obj-$(CONFIG_GPIO_PMIC_EIC_SPRD) += gpio
|
||||
obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o
|
||||
obj-$(CONFIG_GPIO_RASPBERRYPI_EXP) += gpio-raspberrypi-exp.o
|
||||
|
||||
@@ -16,7 +16,7 @@ case "$(board_name)" in
|
||||
tplink,re355-v1|\
|
||||
tplink,re450-v1|\
|
||||
tplink,re450-v2)
|
||||
ucidef_set_compat_version "2.0"
|
||||
ucidef_set_compat_version "3.0"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
+1
-1
@@ -426,7 +426,7 @@ Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
|
||||
+...
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -21557,6 +21557,14 @@ T: git git://linuxtv.org/media.git
|
||||
@@ -21563,6 +21563,14 @@ T: git git://linuxtv.org/media.git
|
||||
F: Documentation/devicetree/bindings/media/i2c/sony,imx415.yaml
|
||||
F: drivers/media/i2c/imx415.c
|
||||
|
||||
|
||||
+1
-1
@@ -193,7 +193,7 @@ media: i2c: imx519: Squash fixes
|
||||
+...
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -21565,6 +21565,14 @@ T: git git://linuxtv.org/media_tree.git
|
||||
@@ -21571,6 +21571,14 @@ T: git git://linuxtv.org/media_tree.git
|
||||
F: Documentation/devicetree/bindings/media/i2c/imx477.yaml
|
||||
F: drivers/media/i2c/imx477.c
|
||||
|
||||
|
||||
+1
-1
@@ -132,7 +132,7 @@ Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
|
||||
+...
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -21562,6 +21562,7 @@ M: Raspberry Pi Kernel Maintenance <kern
|
||||
@@ -21568,6 +21568,7 @@ M: Raspberry Pi Kernel Maintenance <kern
|
||||
L: linux-media@vger.kernel.org
|
||||
S: Maintained
|
||||
T: git git://linuxtv.org/media_tree.git
|
||||
|
||||
@@ -96,7 +96,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.com>
|
||||
depends on MFD_JANZ_CMODIO
|
||||
--- a/drivers/gpio/Makefile
|
||||
+++ b/drivers/gpio/Makefile
|
||||
@@ -66,6 +66,7 @@ obj-$(CONFIG_GPIO_EN7523) += gpio-en752
|
||||
@@ -65,6 +65,7 @@ obj-$(CONFIG_GPIO_EN7523) += gpio-en752
|
||||
obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o
|
||||
obj-$(CONFIG_GPIO_EXAR) += gpio-exar.o
|
||||
obj-$(CONFIG_GPIO_F7188X) += gpio-f7188x.o
|
||||
|
||||
+1
-1
@@ -137,7 +137,7 @@ Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||||
+...
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -21606,6 +21606,14 @@ T: git git://linuxtv.org/media_tree.git
|
||||
@@ -21612,6 +21612,14 @@ T: git git://linuxtv.org/media_tree.git
|
||||
F: Documentation/devicetree/bindings/media/i2c/imx519.yaml
|
||||
F: drivers/media/i2c/imx519.c
|
||||
|
||||
|
||||
+1
-1
@@ -271,7 +271,7 @@ Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
|
||||
+...
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -21611,7 +21611,7 @@ M: Raspberry Pi Kernel Maintenance <kern
|
||||
@@ -21617,7 +21617,7 @@ M: Raspberry Pi Kernel Maintenance <kern
|
||||
L: linux-media@vger.kernel.org
|
||||
S: Maintained
|
||||
T: git git://linuxtv.org/media_tree.git
|
||||
|
||||
+1
-1
@@ -67,7 +67,7 @@ Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
|
||||
+...
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -20069,6 +20069,13 @@ S: Supported
|
||||
@@ -20075,6 +20075,13 @@ S: Supported
|
||||
F: drivers/iio/light/rohm-bu27008.c
|
||||
F: drivers/iio/light/rohm-bu27034.c
|
||||
|
||||
|
||||
+1
-1
@@ -94,7 +94,7 @@ Signed-off-by: Richard Oliver <richard.oliver@raspberrypi.com>
|
||||
+
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -19362,6 +19362,11 @@ L: linux-edac@vger.kernel.org
|
||||
@@ -19368,6 +19368,11 @@ L: linux-edac@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/ras/amd/fmpm.c
|
||||
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ Signed-off-by: Richard Oliver <richard.oliver@raspberrypi.com>
|
||||
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -19366,6 +19366,7 @@ RASPBERRY PI RP2040 GPIO BRIDGE DRIVER
|
||||
@@ -19372,6 +19372,7 @@ RASPBERRY PI RP2040 GPIO BRIDGE DRIVER
|
||||
M: Raspberry Pi Kernel Maintenance <kernel-list@raspberrypi.com>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/spi/raspberrypi,rp2040-gpio-bridge.yaml
|
||||
|
||||
+1
-1
@@ -150,7 +150,7 @@ Signed-off-by: Richard Oliver <richard.oliver@raspberrypi.com>
|
||||
+
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -21611,6 +21611,13 @@ F: Documentation/devicetree/bindings/med
|
||||
@@ -21617,6 +21617,13 @@ F: Documentation/devicetree/bindings/med
|
||||
F: Documentation/devicetree/bindings/media/i2c/imx477.yaml
|
||||
F: drivers/media/i2c/imx477.c
|
||||
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@ Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
|
||||
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -21617,6 +21617,7 @@ L: linux-media@vger.kernel.org
|
||||
@@ -21623,6 +21623,7 @@ L: linux-media@vger.kernel.org
|
||||
S: Maintained
|
||||
T: git git://linuxtv.org/media_tree.git
|
||||
F: Documentation/devicetree/bindings/media/i2c/sony,imx500.yaml
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||||
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -19368,6 +19368,16 @@ S: Maintained
|
||||
@@ -19374,6 +19374,16 @@ S: Maintained
|
||||
F: Documentation/devicetree/bindings/spi/raspberrypi,rp2040-gpio-bridge.yaml
|
||||
F: drivers/spi/spi-rp2040-gpio-bridge.c
|
||||
|
||||
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
From 2a7618ba8698874e9871a8ec5453e0068e94d9e5 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Jelonek <jelonek.jonas@gmail.com>
|
||||
Date: Sat, 27 Dec 2025 18:01:33 +0000
|
||||
Subject: [PATCH] dt-bindings: gpio: add gpio-line-mux controller
|
||||
|
||||
Add dt-schema for a gpio-line-mux controller which exposes virtual
|
||||
GPIOs for a shared GPIO controlled by a multiplexer, e.g. a gpio-mux.
|
||||
|
||||
The gpio-line-mux controller is a gpio-controller, thus has mostly the
|
||||
same semantics. However, it requires a mux-control to be specified upon
|
||||
which it will operate.
|
||||
|
||||
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
|
||||
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
|
||||
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20251227180134.1262138-2-jelonek.jonas@gmail.com
|
||||
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
|
||||
|
||||
--- /dev/null
|
||||
+++ b/Documentation/devicetree/bindings/gpio/gpio-line-mux.yaml
|
||||
@@ -0,0 +1,107 @@
|
||||
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
+%YAML 1.2
|
||||
+---
|
||||
+$id: http://devicetree.org/schemas/gpio/gpio-line-mux.yaml#
|
||||
+$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
+
|
||||
+title: GPIO line mux
|
||||
+
|
||||
+maintainers:
|
||||
+ - Jonas Jelonek <jelonek.jonas@gmail.com>
|
||||
+
|
||||
+description: |
|
||||
+ A GPIO controller to provide virtual GPIOs for a 1-to-many input-only mapping
|
||||
+ backed by a single shared GPIO and a multiplexer. A simple illustrated
|
||||
+ example is:
|
||||
+
|
||||
+ +----- A
|
||||
+ IN /
|
||||
+ <-----o------- B
|
||||
+ / |\
|
||||
+ | | +----- C
|
||||
+ | | \
|
||||
+ | | +--- D
|
||||
+ | |
|
||||
+ M1 M0
|
||||
+
|
||||
+ MUX CONTROL
|
||||
+
|
||||
+ M1 M0 IN
|
||||
+ 0 0 A
|
||||
+ 0 1 B
|
||||
+ 1 0 C
|
||||
+ 1 1 D
|
||||
+
|
||||
+ This can be used in case a real GPIO is connected to multiple inputs and
|
||||
+ controlled by a multiplexer, and another subsystem/driver does not work
|
||||
+ directly with the multiplexer subsystem.
|
||||
+
|
||||
+properties:
|
||||
+ compatible:
|
||||
+ const: gpio-line-mux
|
||||
+
|
||||
+ gpio-controller: true
|
||||
+
|
||||
+ "#gpio-cells":
|
||||
+ const: 2
|
||||
+
|
||||
+ gpio-line-mux-states:
|
||||
+ description: Mux states corresponding to the virtual GPIOs.
|
||||
+ $ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
+
|
||||
+ gpio-line-names: true
|
||||
+
|
||||
+ mux-controls:
|
||||
+ maxItems: 1
|
||||
+ description:
|
||||
+ Phandle to the multiplexer to control access to the GPIOs.
|
||||
+
|
||||
+ ngpios: false
|
||||
+
|
||||
+ muxed-gpios:
|
||||
+ maxItems: 1
|
||||
+ description:
|
||||
+ GPIO which is the '1' in 1-to-many and is shared by the virtual GPIOs
|
||||
+ and controlled via the mux.
|
||||
+
|
||||
+required:
|
||||
+ - compatible
|
||||
+ - gpio-controller
|
||||
+ - gpio-line-mux-states
|
||||
+ - mux-controls
|
||||
+ - muxed-gpios
|
||||
+
|
||||
+additionalProperties: false
|
||||
+
|
||||
+examples:
|
||||
+ - |
|
||||
+ #include <dt-bindings/gpio/gpio.h>
|
||||
+ #include <dt-bindings/mux/mux.h>
|
||||
+
|
||||
+ sfp_gpio_mux: mux-controller-1 {
|
||||
+ compatible = "gpio-mux";
|
||||
+ mux-gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>,
|
||||
+ <&gpio0 1 GPIO_ACTIVE_HIGH>;
|
||||
+ #mux-control-cells = <0>;
|
||||
+ idle-state = <MUX_IDLE_AS_IS>;
|
||||
+ };
|
||||
+
|
||||
+ sfp1_gpio: sfp-gpio-1 {
|
||||
+ compatible = "gpio-line-mux";
|
||||
+ gpio-controller;
|
||||
+ #gpio-cells = <2>;
|
||||
+
|
||||
+ mux-controls = <&sfp_gpio_mux>;
|
||||
+ muxed-gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>;
|
||||
+
|
||||
+ gpio-line-mux-states = <0>, <1>, <3>;
|
||||
+ };
|
||||
+
|
||||
+ sfp1: sfp-p1 {
|
||||
+ compatible = "sff,sfp";
|
||||
+
|
||||
+ i2c-bus = <&sfp1_i2c>;
|
||||
+ los-gpios = <&sfp1_gpio 0 GPIO_ACTIVE_HIGH>;
|
||||
+ mod-def0-gpios = <&sfp1_gpio 1 GPIO_ACTIVE_LOW>;
|
||||
+ tx-fault-gpios = <&sfp1_gpio 2 GPIO_ACTIVE_HIGH>;
|
||||
+ };
|
||||
@@ -0,0 +1,209 @@
|
||||
From 2b03d9a40cd1fea42fd65d2b66df80edc0f374c8 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Jelonek <jelonek.jonas@gmail.com>
|
||||
Date: Sat, 27 Dec 2025 18:01:34 +0000
|
||||
Subject: [PATCH] gpio: add gpio-line-mux driver
|
||||
|
||||
Add a new driver which provides a 1-to-many mapping for a single real
|
||||
GPIO using a multiplexer. Each virtual GPIO corresponds to a multiplexer
|
||||
state which, if set for the multiplexer, connects the real GPIO to the
|
||||
corresponding virtual GPIO.
|
||||
|
||||
This can help in various usecases. One practical case is the special
|
||||
hardware design of the Realtek-based XS1930-10 switch from Zyxel. It
|
||||
features two SFP+ ports/cages whose signals are wired directly to the
|
||||
switch SoC. Although Realtek SoCs are short on GPIOs, there are usually
|
||||
enough the fit the SFP signals without any hacks.
|
||||
|
||||
However, Zyxel did some weird design and connected RX_LOS, MOD_ABS and
|
||||
TX_FAULT of one SFP cage onto a single GPIO line controlled by a
|
||||
multiplexer (the same for the other SFP cage). The single multiplexer
|
||||
controls the lines for both SFP and depending on the state, the
|
||||
designated 'signal GPIO lines' are connected to one of the three SFP
|
||||
signals.
|
||||
|
||||
Because the SFP core/driver doesn't support multiplexer but needs single
|
||||
GPIOs for each of the signals, this driver fills the gap between both.
|
||||
It registers a gpio_chip, provides multiple virtual GPIOs and sets the
|
||||
backing multiplexer accordingly.
|
||||
|
||||
Due to several practical issues, this is input-only and doesn't support
|
||||
IRQs.
|
||||
|
||||
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
|
||||
Reviewed-by: Thomas Richard <thomas.richard@bootlin.com>
|
||||
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20251227180134.1262138-3-jelonek.jonas@gmail.com
|
||||
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
|
||||
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -9704,6 +9704,12 @@ S: Maintained
|
||||
F: Documentation/devicetree/bindings/leds/irled/gpio-ir-tx.yaml
|
||||
F: drivers/media/rc/gpio-ir-tx.c
|
||||
|
||||
+GPIO LINE MUX
|
||||
+M: Jonas Jelonek <jelonek.jonas@gmail.com>
|
||||
+S: Maintained
|
||||
+F: Documentation/devicetree/bindings/gpio/gpio-line-mux.yaml
|
||||
+F: drivers/gpio/gpio-line-mux.c
|
||||
+
|
||||
GPIO MOCKUP DRIVER
|
||||
M: Bamvor Jian Zhang <bamv2005@gmail.com>
|
||||
L: linux-gpio@vger.kernel.org
|
||||
--- a/drivers/gpio/Kconfig
|
||||
+++ b/drivers/gpio/Kconfig
|
||||
@@ -1866,6 +1866,15 @@ config GPIO_LATCH
|
||||
Say yes here to enable a driver for GPIO multiplexers based on latches
|
||||
connected to other GPIOs.
|
||||
|
||||
+config GPIO_LINE_MUX
|
||||
+ tristate "GPIO line mux driver"
|
||||
+ depends on OF_GPIO
|
||||
+ select MULTIPLEXER
|
||||
+ help
|
||||
+ Say Y here to support the GPIO line mux, which can provide virtual
|
||||
+ GPIOs backed by a shared real GPIO and a multiplexer in a 1-to-many
|
||||
+ fashion.
|
||||
+
|
||||
config GPIO_MOCKUP
|
||||
tristate "GPIO Testing Driver (DEPRECATED)"
|
||||
select IRQ_SIM
|
||||
--- a/drivers/gpio/Makefile
|
||||
+++ b/drivers/gpio/Makefile
|
||||
@@ -84,6 +84,7 @@ obj-$(CONFIG_GPIO_IXP4XX) += gpio-ixp4x
|
||||
obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o
|
||||
obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o
|
||||
obj-$(CONFIG_GPIO_LATCH) += gpio-latch.o
|
||||
+obj-$(CONFIG_GPIO_LINE_MUX) += gpio-line-mux.o
|
||||
obj-$(CONFIG_GPIO_LJCA) += gpio-ljca.o
|
||||
obj-$(CONFIG_GPIO_LOGICVC) += gpio-logicvc.o
|
||||
obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/gpio/gpio-line-mux.c
|
||||
@@ -0,0 +1,126 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * GPIO line mux which acts as virtual gpiochip and provides a 1-to-many
|
||||
+ * mapping between virtual GPIOs and a real GPIO + multiplexer.
|
||||
+ *
|
||||
+ * Copyright (c) 2025 Jonas Jelonek <jelonek.jonas@gmail.com>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/gpio/consumer.h>
|
||||
+#include <linux/gpio/driver.h>
|
||||
+#include <linux/mod_devicetable.h>
|
||||
+#include <linux/mutex.h>
|
||||
+#include <linux/mux/consumer.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+
|
||||
+#define MUX_SELECT_DELAY_US 100
|
||||
+
|
||||
+struct gpio_lmux {
|
||||
+ struct gpio_chip gc;
|
||||
+ struct mux_control *mux;
|
||||
+ struct gpio_desc *muxed_gpio;
|
||||
+
|
||||
+ u32 num_gpio_mux_states;
|
||||
+ unsigned int gpio_mux_states[] __counted_by(num_gpio_mux_states);
|
||||
+};
|
||||
+
|
||||
+static int gpio_lmux_gpio_get(struct gpio_chip *gc, unsigned int offset)
|
||||
+{
|
||||
+ struct gpio_lmux *glm = gpiochip_get_data(gc);
|
||||
+ int ret;
|
||||
+
|
||||
+ if (offset > gc->ngpio)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ ret = mux_control_select_delay(glm->mux, glm->gpio_mux_states[offset],
|
||||
+ MUX_SELECT_DELAY_US);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = gpiod_get_raw_value_cansleep(glm->muxed_gpio);
|
||||
+ mux_control_deselect(glm->mux);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int gpio_lmux_gpio_set(struct gpio_chip *gc, unsigned int offset,
|
||||
+ int value)
|
||||
+{
|
||||
+ return -EOPNOTSUPP;
|
||||
+}
|
||||
+
|
||||
+static int gpio_lmux_gpio_get_direction(struct gpio_chip *gc,
|
||||
+ unsigned int offset)
|
||||
+{
|
||||
+ return GPIO_LINE_DIRECTION_IN;
|
||||
+}
|
||||
+
|
||||
+static int gpio_lmux_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct gpio_lmux *glm;
|
||||
+ unsigned int ngpio;
|
||||
+ size_t size;
|
||||
+ int ret;
|
||||
+
|
||||
+ ngpio = device_property_count_u32(dev, "gpio-line-mux-states");
|
||||
+ if (!ngpio)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ size = struct_size(glm, gpio_mux_states, ngpio);
|
||||
+ glm = devm_kzalloc(dev, size, GFP_KERNEL);
|
||||
+ if (!glm)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ glm->gc.base = -1;
|
||||
+ glm->gc.can_sleep = true;
|
||||
+ glm->gc.fwnode = dev_fwnode(dev);
|
||||
+ glm->gc.label = dev_name(dev);
|
||||
+ glm->gc.ngpio = ngpio;
|
||||
+ glm->gc.owner = THIS_MODULE;
|
||||
+ glm->gc.parent = dev;
|
||||
+
|
||||
+ glm->gc.get = gpio_lmux_gpio_get;
|
||||
+ glm->gc.set = gpio_lmux_gpio_set;
|
||||
+ glm->gc.get_direction = gpio_lmux_gpio_get_direction;
|
||||
+
|
||||
+ glm->mux = devm_mux_control_get(dev, NULL);
|
||||
+ if (IS_ERR(glm->mux))
|
||||
+ return dev_err_probe(dev, PTR_ERR(glm->mux),
|
||||
+ "could not get mux controller\n");
|
||||
+
|
||||
+ glm->muxed_gpio = devm_gpiod_get(dev, "muxed", GPIOD_IN);
|
||||
+ if (IS_ERR(glm->muxed_gpio))
|
||||
+ return dev_err_probe(dev, PTR_ERR(glm->muxed_gpio),
|
||||
+ "could not get muxed-gpio\n");
|
||||
+
|
||||
+ glm->num_gpio_mux_states = ngpio;
|
||||
+ ret = device_property_read_u32_array(dev, "gpio-line-mux-states",
|
||||
+ &glm->gpio_mux_states[0], ngpio);
|
||||
+ if (ret)
|
||||
+ return dev_err_probe(dev, ret, "could not get mux states\n");
|
||||
+
|
||||
+ ret = devm_gpiochip_add_data(dev, &glm->gc, glm);
|
||||
+ if (ret)
|
||||
+ return dev_err_probe(dev, ret, "failed to add gpiochip\n");
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id gpio_lmux_of_match[] = {
|
||||
+ { .compatible = "gpio-line-mux" },
|
||||
+ { }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, gpio_lmux_of_match);
|
||||
+
|
||||
+static struct platform_driver gpio_lmux_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "gpio-line-mux",
|
||||
+ .of_match_table = gpio_lmux_of_match,
|
||||
+ },
|
||||
+ .probe = gpio_lmux_probe,
|
||||
+};
|
||||
+module_platform_driver(gpio_lmux_driver);
|
||||
+
|
||||
+MODULE_AUTHOR("Jonas Jelonek <jelonek.jonas@gmail.com>");
|
||||
+MODULE_DESCRIPTION("GPIO line mux driver");
|
||||
+MODULE_LICENSE("GPL");
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
From e034e058897a12bc856f8b22d1796964c742f732 Mon Sep 17 00:00:00 2001
|
||||
From: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
|
||||
Date: Wed, 7 Jan 2026 09:58:33 +0100
|
||||
Subject: [PATCH] gpio: line-mux: remove bits already handled by GPIO core
|
||||
|
||||
GPIO core already handles checking the offset against the number of
|
||||
GPIOs as well as missing any of the GPIO chip callbacks. Remove the
|
||||
unnecessary bits.
|
||||
|
||||
Also, the offset check was off-by-one as reported by Dan.
|
||||
|
||||
Fixes: 2b03d9a40cd1 ("gpio: add gpio-line-mux driver")
|
||||
Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
|
||||
Closes: https://lore.kernel.org/all/aV4b6GAGz1zyf8Xy@stanley.mountain/
|
||||
Tested-by: Jonas Jelonek <jelonek.jonas@gmail.com>
|
||||
Reviewed-by: Jonas Jelonek <jelonek.jonas@gmail.com>
|
||||
Link: https://lore.kernel.org/r/20260107085833.17338-1-bartosz.golaszewski@oss.qualcomm.com
|
||||
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
|
||||
|
||||
--- a/drivers/gpio/gpio-line-mux.c
|
||||
+++ b/drivers/gpio/gpio-line-mux.c
|
||||
@@ -29,9 +29,6 @@ static int gpio_lmux_gpio_get(struct gpi
|
||||
struct gpio_lmux *glm = gpiochip_get_data(gc);
|
||||
int ret;
|
||||
|
||||
- if (offset > gc->ngpio)
|
||||
- return -EINVAL;
|
||||
-
|
||||
ret = mux_control_select_delay(glm->mux, glm->gpio_mux_states[offset],
|
||||
MUX_SELECT_DELAY_US);
|
||||
if (ret < 0)
|
||||
@@ -42,12 +39,6 @@ static int gpio_lmux_gpio_get(struct gpi
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static int gpio_lmux_gpio_set(struct gpio_chip *gc, unsigned int offset,
|
||||
- int value)
|
||||
-{
|
||||
- return -EOPNOTSUPP;
|
||||
-}
|
||||
-
|
||||
static int gpio_lmux_gpio_get_direction(struct gpio_chip *gc,
|
||||
unsigned int offset)
|
||||
{
|
||||
@@ -80,7 +71,6 @@ static int gpio_lmux_probe(struct platfo
|
||||
glm->gc.parent = dev;
|
||||
|
||||
glm->gc.get = gpio_lmux_gpio_get;
|
||||
- glm->gc.set = gpio_lmux_gpio_set;
|
||||
glm->gc.get_direction = gpio_lmux_gpio_get_direction;
|
||||
|
||||
glm->mux = devm_mux_control_get(dev, NULL);
|
||||
@@ -2232,7 +2232,6 @@ CONFIG_GPIOLIB_FASTPATH_LIMIT=512
|
||||
# CONFIG_GPIO_BRCMSTB is not set
|
||||
# CONFIG_GPIO_BT8XX is not set
|
||||
# CONFIG_GPIO_CADENCE is not set
|
||||
# CONFIG_GPIO_CASCADE is not set
|
||||
# CONFIG_GPIO_CDEV is not set
|
||||
# CONFIG_GPIO_CDEV_V1 is not set
|
||||
# CONFIG_GPIO_CS5535 is not set
|
||||
@@ -2253,6 +2252,7 @@ CONFIG_GPIOLIB_FASTPATH_LIMIT=512
|
||||
# CONFIG_GPIO_IT87 is not set
|
||||
# CONFIG_GPIO_LATCH is not set
|
||||
# CONFIG_GPIO_LOGICVC is not set
|
||||
# CONFIG_GPIO_LINE_MUX is not set
|
||||
# CONFIG_GPIO_MAX3191X is not set
|
||||
# CONFIG_GPIO_MAX7300 is not set
|
||||
# CONFIG_GPIO_MAX7301 is not set
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -23671,6 +23671,12 @@ F: Documentation/filesystems/ubifs-authe
|
||||
@@ -23677,6 +23677,12 @@ F: Documentation/filesystems/ubifs-authe
|
||||
F: Documentation/filesystems/ubifs.rst
|
||||
F: fs/ubifs/
|
||||
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
From patchwork Fri Mar 6 12:29:55 2026
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 8bit
|
||||
X-Patchwork-Submitter: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?=
|
||||
<noltari@gmail.com>
|
||||
X-Patchwork-Id: 14457090
|
||||
X-Patchwork-Delegate: kuba@kernel.org
|
||||
Received: from mail-wr1-f48.google.com (mail-wr1-f48.google.com
|
||||
[209.85.221.48])
|
||||
(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))
|
||||
(No client certificate requested)
|
||||
by smtp.subspace.kernel.org (Postfix) with ESMTPS id AF3F4386459
|
||||
for <netdev@vger.kernel.org>; Fri, 6 Mar 2026 12:52:18 +0000 (UTC)
|
||||
Authentication-Results: smtp.subspace.kernel.org;
|
||||
arc=none smtp.client-ip=209.85.221.48
|
||||
ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;
|
||||
t=1772801540; cv=none;
|
||||
b=LVeywxv8ajenPZ8Kr1arieKosbrf60O9l+ouIPKPFNt5btxWDZ59pIU9BfZjv5n9ifEOyUA/UD0phxnG77+oB/k6UCd7DdGQQASZB3NHq5cvmErbgXm0XG3C8BBxVXU5pF7atPS23kBqM9ptxsv3IaeH/fDFcj6k6SH61rGEpuQ=
|
||||
ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org;
|
||||
s=arc-20240116; t=1772801540; c=relaxed/simple;
|
||||
bh=HAy43ssDo0xlUcBDIU7vQZtNnpxG03JPCL6Ldi51ASI=;
|
||||
h=From:To:Cc:Subject:Date:Message-ID:MIME-Version:Content-Type;
|
||||
b=OBk8kI0I91psFRaIxb6nCnAzQlsc7jrXkOPW8lL7cYCosY08yfQDwAlWBFfdFs/VDuVJjD5VEdeQeMt2K4kWGgjLNXhTrRqgs6JNe7PxALDJKvt+kcJ833TRz3hKl2eb2Ft6WnKPf/6hp5Q3qm8+/Q703ixD4sF/0aDNw1BrDY4=
|
||||
ARC-Authentication-Results: i=1; smtp.subspace.kernel.org;
|
||||
dmarc=pass (p=none dis=none) header.from=gmail.com;
|
||||
spf=pass smtp.mailfrom=gmail.com;
|
||||
dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com
|
||||
header.b=RCEse1HL; arc=none smtp.client-ip=209.85.221.48
|
||||
Authentication-Results: smtp.subspace.kernel.org;
|
||||
dmarc=pass (p=none dis=none) header.from=gmail.com
|
||||
Authentication-Results: smtp.subspace.kernel.org;
|
||||
spf=pass smtp.mailfrom=gmail.com
|
||||
Authentication-Results: smtp.subspace.kernel.org;
|
||||
dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com
|
||||
header.b="RCEse1HL"
|
||||
Received: by mail-wr1-f48.google.com with SMTP id
|
||||
ffacd0b85a97d-439b7c2788dso4008389f8f.1
|
||||
for <netdev@vger.kernel.org>; Fri, 06 Mar 2026 04:52:18 -0800 (PST)
|
||||
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=gmail.com; s=20230601; t=1772801537; x=1773406337;
|
||||
darn=vger.kernel.org;
|
||||
h=content-transfer-encoding:mime-version:message-id:date:subject:cc
|
||||
:to:from:from:to:cc:subject:date:message-id:reply-to;
|
||||
bh=y8B8kg8ACcCsMXy3SgsyRYngVEpIsqkcoCsLOS/nNqQ=;
|
||||
b=RCEse1HLoUtQApOdbPXFvYItGrEKWhMZ5FH1L4npAxteGeWOhAEAekijg3Ur83ovNu
|
||||
D7j0Aio5nwazNQz3y4rO88a+svlEbLx5fyxypjkMFUV4PDnOpv7HYjT9Aw1NVdIwO6l+
|
||||
sTgZ1jssfWdVnLQwQe6naotyBRoBV2AugdTmASE0Okxrsi3juIOafyTCxnp4K0weRpaH
|
||||
XodiSWNrkHzZSWM6/wl3D42yExGGPiuDybF+9otR/5TaBWNzrcLkSb73hvP6va35kQWK
|
||||
mnp6OV+L7iHTbxYpTfTm4axD+IZ/Q/dtFxxA6XolA28oMQbRPK0SIHepheSZx4bgl64w
|
||||
FM4w==
|
||||
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
|
||||
d=1e100.net; s=20230601; t=1772801537; x=1773406337;
|
||||
h=content-transfer-encoding:mime-version:message-id:date:subject:cc
|
||||
:to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date
|
||||
:message-id:reply-to;
|
||||
bh=y8B8kg8ACcCsMXy3SgsyRYngVEpIsqkcoCsLOS/nNqQ=;
|
||||
b=KomubXrbvHQI4WbFxBztyfrvNNRRWm7V46yQSwx0bP8PXKIJP38kAYzK+ZKWhmcd7e
|
||||
LpS7422VcYyLywLRxlevD2YaXsF0CK6e00YpTtixakHxYs/4KxGaU21vfwYV8mRhfu7g
|
||||
HVmxKvNQ6DTdC7wAIGT6TrcZCK4VCvgCx3z9yC62hQc8C6w+9mDnnGPvXNR74ofvvXdC
|
||||
eVZjm56layRoEr4PTpR2F33OVSt8+HRikH7eBzIKtQ5n/lEKtmJKDHRaodAaCyFGWMWa
|
||||
qDVoOR8VI4NIJABfsOT6OqisXLPLf+jkKpGkCY2ioRPRKK9GzW4PgIuNcKvPQilQQkgD
|
||||
Xlnw==
|
||||
X-Forwarded-Encrypted: i=1;
|
||||
AJvYcCVcziiSg1n0cDakmiQXH3869FECP24dcIqrZzs8zKakP+vHT958hnq9Bp0alDnLeVtXgo0B8T4=@vger.kernel.org
|
||||
X-Gm-Message-State: AOJu0Yx2OF1e3PiuR4Zqpe9qXA6kz6T2CCtro6kv8eL2j4Zh2HCjWywo
|
||||
/rZTavazOZRoq7zTvc4fGZ/yupjkTT9xRPZCKRkM9pc0UuK/KDSP4pan
|
||||
X-Gm-Gg: ATEYQzx75s3OlYg8XKMgu042++2+ZPa/CZDw09DYtnwEHHBsuylQF0+eXzcFM166JtP
|
||||
EMuM6Nq/sGQx2WNTPNEyu1BRGci/SV005CzkExhd1KK52D/nC1c76MBxvAtioaI/+5tgNoyCg8v
|
||||
ZFRyiqDReKfJ6JHa3YRI213dTzMluN1sZTYNSqlWI1MwW66gaDCf0myU81ehAfiAff34wmxnm8C
|
||||
PUF0YrLYtgZl1I/ZcYM1npoL3PBOnrhaulSqhbn7S5NaZMkHLrNQm6ns1lof+7Ciju05dQpEcBe
|
||||
pumVg15Dy+PcSXQSSQt4CULH7bbuJvZ0PHJ7dS+74i/OqFSgxD4E7LCqM5ufHYdbESx0/ERaR/z
|
||||
CAyT3oTz6S1oMQCUTPevHjHjTbDOWhu74SqyTZETzwGnjZnfrPMa56ebQVRfYgOYW0bbx6j3O2M
|
||||
v3CSEBiXpdFTdaLuRcqIb56JeDryaHx87SOThqnYP6gMiu7EljKYIhr572Rpgz+UIRkrYyNjL9c
|
||||
BLmrcmhsXX4hU4X5KocoApkO04w
|
||||
X-Received: by 2002:a05:600c:8b8b:b0:483:103c:b1ee with SMTP id
|
||||
5b1f17b1804b1-48526922599mr34173745e9.8.1772801536778;
|
||||
Fri, 06 Mar 2026 04:52:16 -0800 (PST)
|
||||
Received: from skynet.lan
|
||||
(2a02-9142-4581-3c00-0000-0000-0000-0008.red-2a02-914.customerbaf.ipv6.rima-tde.net.
|
||||
[2a02:9142:4581:3c00::8])
|
||||
by smtp.gmail.com with ESMTPSA id
|
||||
5b1f17b1804b1-48527681a3esm76085715e9.4.2026.03.06.04.52.14
|
||||
(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
|
||||
Fri, 06 Mar 2026 04:52:15 -0800 (PST)
|
||||
From: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= <noltari@gmail.com>
|
||||
To: linux@armlinux.org.uk,
|
||||
andrew@lunn.ch,
|
||||
hkallweit1@gmail.com,
|
||||
davem@davemloft.net,
|
||||
edumazet@google.com,
|
||||
kuba@kernel.org,
|
||||
pabeni@redhat.com,
|
||||
mnhagan88@gmail.com,
|
||||
netdev@vger.kernel.org,
|
||||
linux-kernel@vger.kernel.org
|
||||
Cc: =?utf-8?q?=C3=81lvaro_Fern=C3=A1ndez_Rojas?= <noltari@gmail.com>
|
||||
Subject: [PATCH net v3] net: sfp: improve Huawei MA5671a fixup
|
||||
Date: Fri, 6 Mar 2026 13:29:55 +0100
|
||||
Message-ID: <20260306125139.213637-1-noltari@gmail.com>
|
||||
X-Mailer: git-send-email 2.47.3
|
||||
Precedence: bulk
|
||||
X-Mailing-List: netdev@vger.kernel.org
|
||||
List-Id: <netdev.vger.kernel.org>
|
||||
List-Subscribe: <mailto:netdev+subscribe@vger.kernel.org>
|
||||
List-Unsubscribe: <mailto:netdev+unsubscribe@vger.kernel.org>
|
||||
MIME-Version: 1.0
|
||||
X-Patchwork-Delegate: kuba@kernel.org
|
||||
|
||||
With the current sfp_fixup_ignore_tx_fault() fixup we ignore the TX_FAULT
|
||||
signal, but we also need to apply sfp_fixup_ignore_los() in order to be
|
||||
able to communicate with the module even if the fiber isn't connected for
|
||||
configuration purposes.
|
||||
This is needed for all the MA5671a firmwares, excluding the FS modded
|
||||
firmware.
|
||||
|
||||
Fixes: 2069624dac19 ("net: sfp: Add tx-fault workaround for Huawei MA5671A SFP ONT")
|
||||
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
|
||||
---
|
||||
v3: avoid using a vendor name in the function
|
||||
v2: rebase on top of net/main instead of linux/master
|
||||
|
||||
drivers/net/phy/sfp.c | 8 +++++++-
|
||||
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/phy/sfp.c
|
||||
+++ b/drivers/net/phy/sfp.c
|
||||
@@ -360,6 +360,12 @@ static void sfp_fixup_ignore_tx_fault(st
|
||||
sfp->state_ignore_mask |= SFP_F_TX_FAULT;
|
||||
}
|
||||
|
||||
+static void sfp_fixup_ignore_tx_fault_and_los(struct sfp *sfp)
|
||||
+{
|
||||
+ sfp_fixup_ignore_tx_fault(sfp);
|
||||
+ sfp_fixup_ignore_los(sfp);
|
||||
+}
|
||||
+
|
||||
static void sfp_fixup_ignore_hw(struct sfp *sfp, unsigned int mask)
|
||||
{
|
||||
sfp->state_hw_mask &= ~mask;
|
||||
@@ -523,7 +529,7 @@ static const struct sfp_quirk sfp_quirks
|
||||
// Huawei MA5671A can operate at 2500base-X, but report 1.2GBd NRZ in
|
||||
// their EEPROM
|
||||
SFP_QUIRK("HUAWEI", "MA5671A", sfp_quirk_2500basex,
|
||||
- sfp_fixup_ignore_tx_fault),
|
||||
+ sfp_fixup_ignore_tx_fault_and_los),
|
||||
|
||||
// Lantech 8330-262D-E can operate at 2500base-X, but incorrectly report
|
||||
// 2500MBd NRZ in their EEPROM
|
||||
+1
-1
@@ -19,7 +19,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -14427,7 +14427,9 @@ M: Daniel Golle <daniel@makrotopia.org>
|
||||
@@ -14432,7 +14432,9 @@ M: Daniel Golle <daniel@makrotopia.org>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/net/pcs/pcs-mtk-lynxi.c
|
||||
|
||||
-217
@@ -1,217 +0,0 @@
|
||||
From fc23ea48ba52c24f201fe5ca0132ee1a3de5a70a Mon Sep 17 00:00:00 2001
|
||||
From: Mauri Sandberg <maukka@ext.kapsi.fi>
|
||||
Date: Thu, 25 Mar 2021 11:48:05 +0200
|
||||
Subject: [PATCH 2/2] gpio: gpio-cascade: add generic GPIO cascade
|
||||
|
||||
Adds support for building cascades of GPIO lines. That is, it allows
|
||||
setups when there is one upstream line and multiple cascaded lines, out
|
||||
of which one can be chosen at a time. The status of the upstream line
|
||||
can be conveyed to the selected cascaded line or, vice versa, the status
|
||||
of the cascaded line can be conveyed to the upstream line.
|
||||
|
||||
A multiplexer is being used to select, which cascaded GPIO line is being
|
||||
used at any given time.
|
||||
|
||||
At the moment only input direction is supported. In future it should be
|
||||
possible to add support for output direction, too.
|
||||
|
||||
Signed-off-by: Mauri Sandberg <maukka@ext.kapsi.fi>
|
||||
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
|
||||
---
|
||||
v7 -> v8:
|
||||
- rearrange members in struct gpio_cascade
|
||||
- cosmetic changes in file header and in one function declaration
|
||||
- added Reviewed-by tags by Linus and Andy
|
||||
v6 -> v7:
|
||||
- In Kconfig add info about module name
|
||||
- adhere to new convention that allows lines longer than 80 chars
|
||||
- use dev_probe_err with upstream gpio line too
|
||||
- refactor for cleaner exit of probe function.
|
||||
v5 -> v6:
|
||||
- In Kconfig, remove dependency to OF_GPIO and select only MULTIPLEXER
|
||||
- refactor code preferring one-liners
|
||||
- clean up prints, removing them from success-path.
|
||||
- don't explicitly set gpio_chip.of_node as it's done in the GPIO library
|
||||
- use devm_gpiochip_add_data instead of gpiochip_add
|
||||
v4 -> v5:
|
||||
- renamed gpio-mux-input -> gpio-cascade. refactored code accordingly
|
||||
here and there and changed to use new bindings and compatible string
|
||||
- ambigious and vague 'pin' was rename to 'upstream_line'
|
||||
- dropped Tested-by and Reviewed-by due to changes in bindings
|
||||
- dropped Reported-by suggested by an automatic bot as it was not really
|
||||
appropriate to begin with
|
||||
- functionally it's the same as v4
|
||||
v3 -> v4:
|
||||
- Changed author email
|
||||
- Included Tested-by and Reviewed-by from Drew
|
||||
v2 -> v3:
|
||||
- use managed device resources
|
||||
- update Kconfig description
|
||||
v1 -> v2:
|
||||
- removed .owner from platform_driver as per test bot's instruction
|
||||
- added MODULE_AUTHOR, MODULE_DESCRIPTION, MODULE_LICENSE
|
||||
- added gpio_mux_input_get_direction as it's recommended for all chips
|
||||
- removed because this is input only chip: gpio_mux_input_set_value
|
||||
- removed because they are not needed for input/output only chips:
|
||||
gpio_mux_input_direction_input
|
||||
gpio_mux_input_direction_output
|
||||
- fixed typo in an error message
|
||||
- added info message about successful registration
|
||||
- removed can_sleep flag as this does not sleep while getting GPIO value
|
||||
like I2C or SPI do
|
||||
- Updated description in Kconfig
|
||||
---
|
||||
drivers/gpio/Kconfig | 15 +++++
|
||||
drivers/gpio/Makefile | 1 +
|
||||
drivers/gpio/gpio-cascade.c | 117 ++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 133 insertions(+)
|
||||
create mode 100644 drivers/gpio/gpio-cascade.c
|
||||
|
||||
--- a/drivers/gpio/Kconfig
|
||||
+++ b/drivers/gpio/Kconfig
|
||||
@@ -1929,4 +1929,19 @@ config GPIO_VIRTUSER
|
||||
|
||||
endmenu
|
||||
|
||||
+comment "Other GPIO expanders"
|
||||
+
|
||||
+config GPIO_CASCADE
|
||||
+ tristate "General GPIO cascade"
|
||||
+ select MULTIPLEXER
|
||||
+ help
|
||||
+ Say yes here to enable support for generic GPIO cascade.
|
||||
+
|
||||
+ This allows building one-to-many cascades of GPIO lines using
|
||||
+ different types of multiplexers readily available. At the
|
||||
+ moment only input lines are supported.
|
||||
+
|
||||
+ To build the driver as a module choose 'm' and the resulting module
|
||||
+ will be called 'gpio-cascade'.
|
||||
+
|
||||
endif
|
||||
--- a/drivers/gpio/Makefile
|
||||
+++ b/drivers/gpio/Makefile
|
||||
@@ -46,6 +46,7 @@ obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd
|
||||
obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o
|
||||
obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
|
||||
obj-$(CONFIG_GPIO_CADENCE) += gpio-cadence.o
|
||||
+obj-$(CONFIG_GPIO_CASCADE) += gpio-cascade.o
|
||||
obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o
|
||||
obj-$(CONFIG_GPIO_SNPS_CREG) += gpio-creg-snps.o
|
||||
obj-$(CONFIG_GPIO_CROS_EC) += gpio-cros-ec.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/gpio/gpio-cascade.c
|
||||
@@ -0,0 +1,112 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-only
|
||||
+/*
|
||||
+ * A generic GPIO cascade driver
|
||||
+ *
|
||||
+ * Copyright (C) 2021 Mauri Sandberg <maukka@ext.kapsi.fi>
|
||||
+ *
|
||||
+ * This allows building cascades of GPIO lines in a manner illustrated
|
||||
+ * below:
|
||||
+ *
|
||||
+ * /|---- Cascaded GPIO line 0
|
||||
+ * Upstream | |---- Cascaded GPIO line 1
|
||||
+ * GPIO line ----+ | .
|
||||
+ * | | .
|
||||
+ * \|---- Cascaded GPIO line n
|
||||
+ *
|
||||
+ * A multiplexer is being used to select, which cascaded line is being
|
||||
+ * addressed at any given time.
|
||||
+ *
|
||||
+ * At the moment only input mode is supported due to lack of means for
|
||||
+ * testing output functionality. At least theoretically output should be
|
||||
+ * possible with open drain constructions.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/mux/consumer.h>
|
||||
+
|
||||
+#include <linux/gpio/consumer.h>
|
||||
+#include <linux/gpio/driver.h>
|
||||
+
|
||||
+struct gpio_cascade {
|
||||
+ struct gpio_chip gpio_chip;
|
||||
+ struct device *parent;
|
||||
+ struct mux_control *mux_control;
|
||||
+ struct gpio_desc *upstream_line;
|
||||
+};
|
||||
+
|
||||
+static int gpio_cascade_get_direction(struct gpio_chip *gc, unsigned int offset)
|
||||
+{
|
||||
+ return GPIO_LINE_DIRECTION_IN;
|
||||
+}
|
||||
+
|
||||
+static int gpio_cascade_get_value(struct gpio_chip *gc, unsigned int offset)
|
||||
+{
|
||||
+ struct gpio_cascade *cas = gpiochip_get_data(gc);
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = mux_control_select(cas->mux_control, offset);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = gpiod_get_value(cas->upstream_line);
|
||||
+ mux_control_deselect(cas->mux_control);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int gpio_cascade_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct gpio_cascade *cas;
|
||||
+ struct mux_control *mc;
|
||||
+ struct gpio_desc *upstream;
|
||||
+ struct gpio_chip *gc;
|
||||
+
|
||||
+ cas = devm_kzalloc(dev, sizeof(*cas), GFP_KERNEL);
|
||||
+ if (!cas)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ mc = devm_mux_control_get(dev, NULL);
|
||||
+ if (IS_ERR(mc))
|
||||
+ return dev_err_probe(dev, PTR_ERR(mc), "unable to get mux-control\n");
|
||||
+
|
||||
+ cas->mux_control = mc;
|
||||
+ upstream = devm_gpiod_get(dev, "upstream", GPIOD_IN);
|
||||
+ if (IS_ERR(upstream))
|
||||
+ return dev_err_probe(dev, PTR_ERR(upstream), "unable to claim upstream GPIO line\n");
|
||||
+
|
||||
+ cas->upstream_line = upstream;
|
||||
+ cas->parent = dev;
|
||||
+
|
||||
+ gc = &cas->gpio_chip;
|
||||
+ gc->get = gpio_cascade_get_value;
|
||||
+ gc->get_direction = gpio_cascade_get_direction;
|
||||
+ gc->base = -1;
|
||||
+ gc->ngpio = mux_control_states(mc);
|
||||
+ gc->label = dev_name(cas->parent);
|
||||
+ gc->parent = cas->parent;
|
||||
+ gc->owner = THIS_MODULE;
|
||||
+
|
||||
+ platform_set_drvdata(pdev, cas);
|
||||
+ return devm_gpiochip_add_data(dev, &cas->gpio_chip, cas);
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id gpio_cascade_id[] = {
|
||||
+ { .compatible = "gpio-cascade" },
|
||||
+ { /* sentinel */ }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, gpio_cascade_id);
|
||||
+
|
||||
+static struct platform_driver gpio_cascade_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "gpio-cascade",
|
||||
+ .of_match_table = gpio_cascade_id,
|
||||
+ },
|
||||
+ .probe = gpio_cascade_probe,
|
||||
+};
|
||||
+module_platform_driver(gpio_cascade_driver);
|
||||
+
|
||||
+MODULE_AUTHOR("Mauri Sandberg <maukka@ext.kapsi.fi>");
|
||||
+MODULE_DESCRIPTION("Generic GPIO cascade");
|
||||
+MODULE_LICENSE("GPL");
|
||||
@@ -57,6 +57,7 @@ ipq40xx_setup_interfaces()
|
||||
dlink,dap-2610|\
|
||||
engenius,eap1300|\
|
||||
extreme-networks,ws-ap3915i|\
|
||||
huawei,ap4050dn|\
|
||||
meraki,mr20|\
|
||||
meraki,mr33|\
|
||||
meraki,mr70|\
|
||||
|
||||
@@ -77,6 +77,10 @@ case "$FIRMWARE" in
|
||||
caldata_extract "ART" 0x1000 0x2f20
|
||||
ath10k_patch_mac $(mtd_get_mac_ascii CFG1 RADIOADDR0)
|
||||
;;
|
||||
huawei,ap4050dn)
|
||||
caldata_extract "0:ART" 0x1000 0x2f20
|
||||
ath10k_patch_mac $(macaddr_add "$(cat /sys/class/net/eth0/address)" 1)
|
||||
;;
|
||||
mikrotik,cap-ac|\
|
||||
mikrotik,hap-ac2|\
|
||||
mikrotik,hap-ac3|\
|
||||
@@ -159,6 +163,10 @@ case "$FIRMWARE" in
|
||||
caldata_extract "ART" 0x5000 0x2f20
|
||||
ath10k_patch_mac $(mtd_get_mac_ascii CFG1 RADIOADDR1)
|
||||
;;
|
||||
huawei,ap4050dn)
|
||||
caldata_extract "0:ART" 0x5000 0x2f20
|
||||
ath10k_patch_mac $(macaddr_add "$(cat /sys/class/net/eth0/address)" 2)
|
||||
;;
|
||||
mikrotik,cap-ac|\
|
||||
mikrotik,hap-ac2|\
|
||||
mikrotik,hap-ac3|\
|
||||
|
||||
@@ -167,6 +167,16 @@ platform_do_upgrade() {
|
||||
CI_ROOTPART="rootfs"
|
||||
emmc_do_upgrade "$1"
|
||||
;;
|
||||
huawei,ap4050dn)
|
||||
# Store beginning address of the "uboot" partition
|
||||
# as KernelA address and KernelB address, each to ResultA & ResultB
|
||||
# This is the address from which the bootloader will try to load the u-boot that we use as loader.
|
||||
HUAWEI_AP4050DN_LOADADDR="\x00\x00\x70\x00\x00\x00\x70\x00"
|
||||
echo -n -e $HUAWEI_AP4050DN_LOADADDR | dd of=$(find_mtd_part ResultA) bs=1 seek=$((0x4264)) conv=notrunc
|
||||
echo -n -e $HUAWEI_AP4050DN_LOADADDR | dd of=$(find_mtd_part ResultA) bs=1 seek=$((0x40264)) conv=notrunc
|
||||
echo -n -e $HUAWEI_AP4050DN_LOADADDR | dd of=$(find_mtd_part ResultB) bs=1 seek=$((0x4264)) conv=notrunc
|
||||
default_do_upgrade "$1"
|
||||
;;
|
||||
linksys,ea6350v3|\
|
||||
linksys,ea8300|\
|
||||
linksys,mr6350|\
|
||||
|
||||
@@ -309,6 +309,7 @@ CONFIG_MTD_SPI_NOR=y
|
||||
CONFIG_MTD_SPLIT_FIRMWARE=y
|
||||
CONFIG_MTD_SPLIT_FIT_FW=y
|
||||
CONFIG_MTD_SPLIT_WRGG_FW=y
|
||||
CONFIG_MTD_VIRT_CONCAT=y
|
||||
CONFIG_MUTEX_SPIN_ON_OWNER=y
|
||||
CONFIG_NEED_DMA_MAP_STATE=y
|
||||
CONFIG_NEED_SRCU_NMI_SAFE=y
|
||||
@@ -323,6 +324,7 @@ CONFIG_NET_FLOW_LIMIT=y
|
||||
CONFIG_NET_INGRESS=y
|
||||
CONFIG_NET_PTP_CLASSIFY=y
|
||||
CONFIG_NET_SELFTESTS=y
|
||||
CONFIG_NET_SWITCHDEV=y
|
||||
CONFIG_NET_XGRESS=y
|
||||
CONFIG_NLS=y
|
||||
CONFIG_NO_HZ=y
|
||||
@@ -353,6 +355,7 @@ CONFIG_PAGE_OFFSET=0xC0000000
|
||||
CONFIG_PAGE_POOL=y
|
||||
CONFIG_PAGE_SIZE_LESS_THAN_256KB=y
|
||||
CONFIG_PAGE_SIZE_LESS_THAN_64KB=y
|
||||
CONFIG_PAHOLE_HAS_LANG_EXCLUDE=y
|
||||
CONFIG_PCI=y
|
||||
CONFIG_PCIEAER=y
|
||||
CONFIG_PCIEPORTBUS=y
|
||||
@@ -480,6 +483,7 @@ CONFIG_SGL_ALLOC=y
|
||||
CONFIG_SKB_EXTENSIONS=y
|
||||
CONFIG_SMP=y
|
||||
CONFIG_SMP_ON_UP=y
|
||||
# CONFIG_SM_GCC_7150 is not set
|
||||
CONFIG_SOCK_RX_QUEUE_MAPPING=y
|
||||
CONFIG_SOFTIRQ_ON_OWN_STACK=y
|
||||
CONFIG_SPARSE_IRQ=y
|
||||
|
||||
@@ -0,0 +1,381 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
|
||||
#include "qcom-ipq4019.dtsi"
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/leds/common.h>
|
||||
#include <dt-bindings/soc/qcom,tcsr.h>
|
||||
|
||||
/ {
|
||||
model = "Huawei AP4050DN";
|
||||
compatible = "huawei,ap4050dn", "qcom,ipq40xx";
|
||||
|
||||
chosen {
|
||||
bootargs = "console=ttyMSM0,9600n8";
|
||||
};
|
||||
|
||||
aliases {
|
||||
ethernet0 = &gmac;
|
||||
led-boot = &led_function_green;
|
||||
led-failsafe = &led_function_red;
|
||||
led-running = &led_function_green;
|
||||
led-upgrade = &led_function_red;
|
||||
label-mac-device = &gmac;
|
||||
};
|
||||
|
||||
soc {
|
||||
rng@22000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
counter@4a1000 {
|
||||
compatible = "qcom,qca-gcnt";
|
||||
reg = <0x4a1000 0x4>;
|
||||
};
|
||||
|
||||
tcsr@1949000 {
|
||||
compatible = "qcom,tcsr";
|
||||
reg = <0x1949000 0x100>;
|
||||
qcom,wifi_glb_cfg = <TCSR_WIFI_GLB_CFG>;
|
||||
};
|
||||
|
||||
ess_tcsr@1953000 {
|
||||
compatible = "qcom,tcsr";
|
||||
reg = <0x1953000 0x1000>;
|
||||
qcom,ess-interface-select = <TCSR_ESS_PSGMII>;
|
||||
};
|
||||
|
||||
tcsr@1957000 {
|
||||
compatible = "qcom,tcsr";
|
||||
reg = <0x1957000 0x100>;
|
||||
qcom,wifi_noc_memtype_m0_m2 = <TCSR_WIFI_NOC_MEMTYPE_M0_M2>;
|
||||
};
|
||||
|
||||
crypto@8e3a000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
watchdog@b017000 {
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
keys {
|
||||
compatible = "gpio-keys";
|
||||
|
||||
restart {
|
||||
label = "reset";
|
||||
linux,code = <KEY_RESTART>;
|
||||
gpios = <&tlmm 63 GPIO_ACTIVE_LOW>;
|
||||
debounce-interval = <60>;
|
||||
};
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
|
||||
led_function_green: led-status-green {
|
||||
function = LED_FUNCTION_STATUS;
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
led_function_red: led-status-red {
|
||||
function = LED_FUNCTION_STATUS;
|
||||
color = <LED_COLOR_ID_RED>;
|
||||
gpios = <&tlmm 4 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
||||
watchdog {
|
||||
compatible = "linux,wdt-gpio";
|
||||
gpios = <&tlmm 3 GPIO_ACTIVE_LOW>;
|
||||
hw_algo = "toggle";
|
||||
hw_margin_ms = <2>;
|
||||
always-running;
|
||||
};
|
||||
|
||||
virtual_flash {
|
||||
compatible = "mtd-concat";
|
||||
devices = <&fwconcat0 &fwconcat1>;
|
||||
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
label = "firmware";
|
||||
reg = <0x0 0x3200000>;
|
||||
compatible = "denx,fit";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&tlmm {
|
||||
serial_pins: serial_pinmux {
|
||||
mux {
|
||||
pins = "gpio60", "gpio61";
|
||||
function = "blsp_uart0";
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
spi_0_pins: spi_0_pinmux {
|
||||
pin {
|
||||
function = "blsp_spi0";
|
||||
pins = "gpio55", "gpio56", "gpio57";
|
||||
drive-strength = <12>;
|
||||
bias-disable;
|
||||
};
|
||||
pin_cs {
|
||||
function = "gpio";
|
||||
pins = "gpio54";
|
||||
drive-strength = <2>;
|
||||
bias-disable;
|
||||
output-high;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&blsp_dma {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&blsp1_spi1 {
|
||||
pinctrl-0 = <&spi_0_pins>;
|
||||
pinctrl-names = "default";
|
||||
status = "okay";
|
||||
cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
flash@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "jedec,spi-nor";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <24000000>;
|
||||
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition-flash-all@0 {
|
||||
label = "flash-all";
|
||||
reg = <0x00000000 0x4000000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@0 {
|
||||
label = "0:SBL1";
|
||||
reg = <0x00 0x40000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@40000 {
|
||||
label = "0:MIBIB";
|
||||
reg = <0x40000 0x40000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@80000 {
|
||||
label = "0:QSEE";
|
||||
reg = <0x80000 0x80000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@100000 {
|
||||
label = "0:CDT";
|
||||
reg = <0x100000 0x40000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@140000 {
|
||||
label = "0:DDRPARAMS";
|
||||
reg = <0x140000 0x40000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@180000 {
|
||||
label = "0:APPSBL";
|
||||
reg = <0x180000 0x100000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@280000 {
|
||||
label = "0:ART";
|
||||
reg = <0x280000 0x40000>;
|
||||
read-only;
|
||||
|
||||
nvmem-layout {
|
||||
compatible = "fixed-layout";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
precal_art_1000: precal@1000 {
|
||||
reg = <0x1000 0x2f20>;
|
||||
};
|
||||
|
||||
precal_art_5000: precal@5000 {
|
||||
reg = <0x5000 0x2f20>;
|
||||
};
|
||||
|
||||
precal_art_9000: precal@9000 {
|
||||
reg = <0x9000 0x2f20>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
partition@2c0000 {
|
||||
label = "0:APPSBLENV";
|
||||
reg = <0x2c0000 0x40000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@300000 {
|
||||
label = "ResultA";
|
||||
reg = <0x300000 0x80000>;
|
||||
|
||||
nvmem-layout {
|
||||
compatible = "fixed-layout";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
macaddr_resulta_10190: macaddr@10190 {
|
||||
reg = <0x10190 0x6>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
partition@380000 {
|
||||
label = "configA";
|
||||
reg = <0x380000 0x280000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@600000 {
|
||||
label = "bootimageA";
|
||||
reg = <0x600000 0x100000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
// In the vendor layout, the partition "SysImageA" lies here
|
||||
// which encompassed the space of "uboot" and "fwconcat0"
|
||||
partition@700000 {
|
||||
label = "uboot";
|
||||
reg = <0x700000 0x80000>;
|
||||
};
|
||||
|
||||
fwconcat0: partition@780000 {
|
||||
label = "fwconcat0";
|
||||
reg = <0x780000 0x1880000>;
|
||||
};
|
||||
|
||||
partition@2000000 {
|
||||
label = "1:SBL1";
|
||||
reg = <0x2000000 0x40000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@2040000 {
|
||||
label = "1:MIBIB";
|
||||
reg = <0x2040000 0x40000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@2080000 {
|
||||
label = "1:QSEE";
|
||||
reg = <0x2080000 0x80000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@2100000 {
|
||||
label = "1:CDT";
|
||||
reg = <0x2100000 0x40000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@2140000 {
|
||||
label = "1:DDRPARAMS";
|
||||
reg = <0x2140000 0x40000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@2180000 {
|
||||
label = "1:APPSBL";
|
||||
reg = <0x2180000 0x100000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@2280000 {
|
||||
label = "Reservel";
|
||||
reg = <0x2280000 0x80000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@2300000 {
|
||||
label = "ResultB";
|
||||
reg = <0x2300000 0x80000>;
|
||||
};
|
||||
|
||||
partition@2380000 {
|
||||
label = "configB";
|
||||
reg = <0x2380000 0x280000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@2600000 {
|
||||
label = "bootimageB";
|
||||
reg = <0x2600000 0x100000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
// In the vendor layout, the partition "SysImageB" lies here
|
||||
fwconcat1: partition@2700000 {
|
||||
label = "fwconcat1";
|
||||
reg = <0x2700000 0x1900000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&blsp1_uart1 {
|
||||
pinctrl-0 = <&serial_pins>;
|
||||
pinctrl-names = "default";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&wifi0 {
|
||||
status = "okay";
|
||||
qcom,ath10k-calibration-variant = "huawei-ap4050dn";
|
||||
};
|
||||
|
||||
&wifi1 {
|
||||
status = "okay";
|
||||
qcom,ath10k-calibration-variant = "huawei-ap4050dn";
|
||||
};
|
||||
|
||||
&cryptobam {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mdio {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gmac {
|
||||
status = "okay";
|
||||
|
||||
nvmem-cells = <&macaddr_resulta_10190 0>;
|
||||
nvmem-cell-names = "mac-address";
|
||||
};
|
||||
|
||||
&switch {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&swport4 {
|
||||
status = "okay";
|
||||
label = "lan";
|
||||
};
|
||||
@@ -645,6 +645,18 @@ define Device/glinet_gl-s1300
|
||||
endef
|
||||
TARGET_DEVICES += glinet_gl-s1300
|
||||
|
||||
define Device/huawei_ap4050dn
|
||||
$(call Device/FitImageLzma)
|
||||
DEVICE_VENDOR := Huawei
|
||||
DEVICE_MODEL := AP4050DN
|
||||
SOC := qcom-ipq4018
|
||||
IMAGE_SIZE := 51200k
|
||||
DEVICE_PACKAGES := ipq-wifi-huawei_ap4050dn
|
||||
KERNEL = kernel-bin | lzma | fit lzma $$(KDIR)/image-$$(DEVICE_DTS).dtb
|
||||
IMAGE/sysupgrade.bin := append-kernel | append-rootfs | pad-rootfs | check-size | append-metadata
|
||||
endef
|
||||
TARGET_DEVICES += huawei_ap4050dn
|
||||
|
||||
define Device/kernel-size-6350-8300
|
||||
DEVICE_COMPAT_VERSION := 2.0
|
||||
DEVICE_COMPAT_MESSAGE := Kernel partition size must be increased for \
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
|
||||
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -19032,6 +19032,13 @@ L: netdev@vger.kernel.org
|
||||
@@ -19038,6 +19038,13 @@ L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/net/ethernet/qualcomm/emac/
|
||||
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@ Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
|
||||
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -19038,6 +19038,7 @@ L: netdev@vger.kernel.org
|
||||
@@ -19044,6 +19044,7 @@ L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/net/qcom,ipq4019-ess-edma.yaml
|
||||
F: drivers/net/ethernet/qualcomm/ipqess/
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ Signed-off-by: Sky Huang <skylake.huang@mediatek.com>
|
||||
+ };
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -14434,9 +14434,10 @@ F: include/linux/pcs/pcs-mtk-usxgmii.h
|
||||
@@ -14439,9 +14439,10 @@ F: include/linux/pcs/pcs-mtk-usxgmii.h
|
||||
MEDIATEK ETHERNET PHY DRIVERS
|
||||
M: Daniel Golle <daniel@makrotopia.org>
|
||||
M: Qingfang Deng <dqfext@gmail.com>
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ Signed-off-by: Sky Huang <skylake.huang@mediatek.com>
|
||||
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -14438,6 +14438,7 @@ M: Sky Huang <SkyLake.Huang@mediatek.com
|
||||
@@ -14443,6 +14443,7 @@ M: Sky Huang <SkyLake.Huang@mediatek.com
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/net/mediatek,2p5gphy-fw.yaml
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -15154,6 +15154,13 @@ S: Maintained
|
||||
@@ -15160,6 +15160,13 @@ S: Maintained
|
||||
F: Documentation/devicetree/bindings/interrupt-controller/microchip,lan966x-oic.yaml
|
||||
F: drivers/irqchip/irq-lan966x-oic.c
|
||||
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -15159,7 +15159,7 @@ M: Daniel Machon <daniel.machon@microchi
|
||||
@@ -15165,7 +15165,7 @@ M: Daniel Machon <daniel.machon@microchi
|
||||
M: UNGLinuxDriver@microchip.com
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
@@ -226,7 +226,6 @@
|
||||
};
|
||||
|
||||
enet0: ethernet@b0000 {
|
||||
status = "okay";
|
||||
phy-connection-type = "rgmii-id";
|
||||
nvmem-cells = <&macaddr_hwinfo_0 0>;
|
||||
nvmem-cell-names = "mac-address";
|
||||
@@ -259,13 +258,27 @@
|
||||
};
|
||||
|
||||
pci0: pcie@ffe09000 {
|
||||
reg = <0 0xffe09000 0 0x1000>;
|
||||
ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
|
||||
0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
|
||||
|
||||
status = "disabled";
|
||||
|
||||
pcie@0 {
|
||||
ranges = <0x2000000 0x0 0xa0000000
|
||||
0x2000000 0x0 0xa0000000
|
||||
0x0 0x20000000
|
||||
|
||||
0x1000000 0x0 0x0
|
||||
0x1000000 0x0 0x0
|
||||
0x0 0x100000>;
|
||||
};
|
||||
};
|
||||
|
||||
pci1: pcie@ffe0a000 {
|
||||
reg = <0x0 0xffe0a000 0x0 0x1000>;
|
||||
ranges = <0x2000000 0x0 0xc0000000 0x0 0xc0000000 0x0 0x20000000
|
||||
0x1000000 0x0 0x00000000 0x0 0xffc20000 0x0 0x10000>;
|
||||
0x1000000 0x0 0x00000000 0x0 0xffc20000 0x0 0x10000>;
|
||||
|
||||
reset-gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
|
||||
|
||||
|
||||
@@ -232,7 +232,22 @@
|
||||
};
|
||||
|
||||
pci0: pcie@ffe09000 {
|
||||
reg = <0 0xffe09000 0 0x1000>;
|
||||
ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
|
||||
0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
|
||||
|
||||
status = "disabled";
|
||||
|
||||
pcie@0 {
|
||||
ranges = <0x2000000 0x0 0xa0000000
|
||||
0x2000000 0x0 0xa0000000
|
||||
0x0 0x20000000
|
||||
|
||||
0x1000000 0x0 0x0
|
||||
0x1000000 0x0 0x0
|
||||
0x0 0x100000>;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
pci1: pcie@ffe0a000 {
|
||||
|
||||
@@ -49,7 +49,6 @@
|
||||
d-cache-sets = <0x80>;
|
||||
d-cache-size = <0x8000>;
|
||||
d-cache-block-size = <0x20>;
|
||||
status = "okay";
|
||||
clock-frequency = <533333328>; /* 533.33 MHz */
|
||||
bus-frequency = <266666664>; /* 266.66 MHz */
|
||||
timebase-frequency = <33333333>; /* 33.33 MHz */
|
||||
@@ -130,8 +129,6 @@
|
||||
ranges = <0x0 0x0 0x0 0xec000000 0x4000000>;
|
||||
|
||||
nor@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "cfi-flash";
|
||||
reg = <0x0 0x0 0x4000000>;
|
||||
bank-width = <2>;
|
||||
@@ -334,7 +331,6 @@
|
||||
rx-stash-idx = <0x00>;
|
||||
rx-stash-len = <0x60>;
|
||||
bd-stash;
|
||||
status = "okay";
|
||||
phy-handle = <&phy0>;
|
||||
phy-connection-type = "rgmii-id";
|
||||
nvmem-cells = <&macaddr_hwinfo_0 0>;
|
||||
@@ -349,7 +345,6 @@
|
||||
rx-stash-idx = <0x00>;
|
||||
rx-stash-len = <0x60>;
|
||||
bd-stash;
|
||||
status = "okay";
|
||||
phy-handle = <&phy1>;
|
||||
phy-connection-type = "rgmii-id";
|
||||
nvmem-cells = <&macaddr_hwinfo_0 1>;
|
||||
|
||||
@@ -194,13 +194,28 @@
|
||||
};
|
||||
|
||||
pci0: pcie@ffe09000 {
|
||||
reg = <0 0xffe09000 0 0x1000>;
|
||||
ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
|
||||
0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
|
||||
|
||||
status = "disabled";
|
||||
|
||||
pcie@0 {
|
||||
ranges = <0x2000000 0x0 0xa0000000
|
||||
0x2000000 0x0 0xa0000000
|
||||
0x0 0x20000000
|
||||
|
||||
0x1000000 0x0 0x0
|
||||
0x1000000 0x0 0x0
|
||||
0x0 0x100000>;
|
||||
};
|
||||
};
|
||||
|
||||
pci1: pcie@ffe0a000 {
|
||||
reg = <0 0xffe0a000 0 0x1000>;
|
||||
ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000
|
||||
0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
|
||||
|
||||
pcie@0 {
|
||||
ranges = <0x2000000 0x0 0x80000000
|
||||
0x2000000 0x0 0x80000000
|
||||
|
||||
@@ -391,6 +391,8 @@
|
||||
};
|
||||
|
||||
ifc: ifc@ffe1e000 {
|
||||
reg = <0x0 0xffe1e000 0 0x2000>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
||||
@@ -67,8 +67,6 @@
|
||||
ranges = <0x0 0x0 0x0 0xee000000 0x2000000>;
|
||||
|
||||
nor@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "cfi-flash";
|
||||
reg = <0x0 0x0 0x2000000>;
|
||||
bank-width = <2>;
|
||||
@@ -207,7 +205,6 @@
|
||||
i-cache-size = <0x8000>;
|
||||
i-cache-sets = <0x80>;
|
||||
cpu-release-addr = <0x0 0x0ffff280>;
|
||||
status = "okay";
|
||||
enable-method = "spin-table";
|
||||
};
|
||||
|
||||
|
||||
@@ -140,6 +140,9 @@
|
||||
};
|
||||
|
||||
ifc: ifc@ffe1e000 {
|
||||
reg = <0x0 0xffe1e000 0 0x2000>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pci0: pcie@ffe09000 {
|
||||
|
||||
@@ -94,8 +94,6 @@
|
||||
ranges = <0x0 0x0 0x0 0xec000000 0x4000000>;
|
||||
|
||||
nor@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "cfi-flash";
|
||||
reg = <0x0 0x0 0x4000000>;
|
||||
bank-width = <2>;
|
||||
@@ -176,7 +174,6 @@
|
||||
};
|
||||
|
||||
enet0: ethernet@b0000 {
|
||||
status = "okay";
|
||||
phy-handle = <&phy0>;
|
||||
phy-connection-type = "rgmii-id";
|
||||
};
|
||||
@@ -186,7 +183,6 @@
|
||||
};
|
||||
|
||||
enet2: ethernet@b2000 {
|
||||
status = "okay";
|
||||
phy-handle = <&phy2>;
|
||||
phy-connection-type = "rgmii-id";
|
||||
};
|
||||
@@ -286,7 +282,6 @@
|
||||
i-cache-size = <0x8000>;
|
||||
i-cache-sets = <0x80>;
|
||||
cpu-release-addr = <0x0 0x0ffff280>;
|
||||
status = "okay";
|
||||
enable-method = "spin-table";
|
||||
};
|
||||
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ Cc: Robert Marko <robert.marko@sartura.hr>
|
||||
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -10972,6 +10972,22 @@ L: virtualization@lists.linux.dev
|
||||
@@ -10978,6 +10978,22 @@ L: virtualization@lists.linux.dev
|
||||
S: Supported
|
||||
F: drivers/vdpa/ifcvf/
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <linux/of_mdio.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <net/arp.h>
|
||||
#include <net/lag.h>
|
||||
#include <net/nexthop.h>
|
||||
#include <net/neighbour.h>
|
||||
#include <net/netevent.h>
|
||||
@@ -287,7 +288,6 @@ static int rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv)
|
||||
led_node = of_find_compatible_node(NULL, NULL, "realtek,rtl9300-leds");
|
||||
|
||||
for_each_node_by_name(dn, "port") {
|
||||
phy_interface_t interface;
|
||||
u32 led_set;
|
||||
char led_set_str[16] = {0};
|
||||
|
||||
@@ -305,24 +305,15 @@ static int rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv)
|
||||
}
|
||||
|
||||
if (pcs_node) {
|
||||
priv->pcs[pn] = rtpcs_create(priv->dev, pcs_node, pn);
|
||||
if (IS_ERR(priv->pcs[pn])) {
|
||||
priv->ports[pn].pcs = rtpcs_create(priv->dev, pcs_node, pn);
|
||||
if (IS_ERR(priv->ports[pn].pcs)) {
|
||||
dev_err(priv->dev, "port %u failed to create PCS instance: %ld\n",
|
||||
pn, PTR_ERR(priv->pcs[pn]));
|
||||
priv->pcs[pn] = NULL;
|
||||
pn, PTR_ERR(priv->ports[pn].pcs));
|
||||
priv->ports[pn].pcs = NULL;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (of_get_phy_mode(dn, &interface))
|
||||
interface = PHY_INTERFACE_MODE_NA;
|
||||
if (interface == PHY_INTERFACE_MODE_10G_QXGMII)
|
||||
priv->ports[pn].is2G5 = true;
|
||||
if (interface == PHY_INTERFACE_MODE_USXGMII)
|
||||
priv->ports[pn].is2G5 = priv->ports[pn].is10G = true;
|
||||
if (interface == PHY_INTERFACE_MODE_10GBASER)
|
||||
priv->ports[pn].is10G = true;
|
||||
|
||||
priv->ports[pn].leds_on_this_port = 0;
|
||||
if (led_node) {
|
||||
if (of_property_read_u32(dn, "led-set", &led_set))
|
||||
@@ -338,7 +329,7 @@ static int rtl83xx_mdio_probe(struct rtl838x_switch_priv *priv)
|
||||
}
|
||||
|
||||
if (!phy_node) {
|
||||
if (priv->pcs[pn])
|
||||
if (priv->ports[pn].pcs)
|
||||
priv->ports[pn].phy_is_integrated = true;
|
||||
|
||||
continue;
|
||||
@@ -394,9 +385,8 @@ static int rtl83xx_get_l2aging(struct rtl838x_switch_priv *priv)
|
||||
int rtl83xx_lag_add(struct dsa_switch *ds, int group, int port, struct netdev_lag_upper_info *info)
|
||||
{
|
||||
struct rtl838x_switch_priv *priv = ds->priv;
|
||||
int ret;
|
||||
int i;
|
||||
u32 algomsk = 0;
|
||||
u32 algoidx = 0;
|
||||
|
||||
for (i = 0; i < priv->ds->num_lag_ids; i++) {
|
||||
if (priv->lags_port_members[i] & BIT_ULL(port))
|
||||
@@ -407,31 +397,16 @@ int rtl83xx_lag_add(struct dsa_switch *ds, int group, int port, struct netdev_la
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
switch (info->hash_type) {
|
||||
case NETDEV_LAG_HASH_L2:
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_DMAC_BIT;
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_SMAC_BIT;
|
||||
break;
|
||||
case NETDEV_LAG_HASH_L23:
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_DMAC_BIT;
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_SMAC_BIT;
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_SIP_BIT; /* source ip */
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_DIP_BIT; /* dest ip */
|
||||
algoidx = 1;
|
||||
break;
|
||||
case NETDEV_LAG_HASH_L34:
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_SRC_L4PORT_BIT; /* sport */
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_DST_L4PORT_BIT; /* dport */
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_SIP_BIT; /* source ip */
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_DIP_BIT; /* dest ip */
|
||||
algoidx = 2;
|
||||
break;
|
||||
default:
|
||||
algomsk |= 0x7f;
|
||||
if (priv->r->lag_setup_algomask) {
|
||||
ret = priv->r->lag_setup_algomask(priv, group, info);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
priv->r->set_distribution_algorithm(group, algoidx, algomsk);
|
||||
priv->r->mask_port_reg_be(0, BIT_ULL(port), priv->r->trk_mbr_ctr(group));
|
||||
priv->lags_port_members[group] |= BIT_ULL(port);
|
||||
|
||||
ret = priv->r->lag_set_port_members(priv, group,
|
||||
priv->lags_port_members[group] | BIT_ULL(port), info);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pr_info("%s: Added port %d to LAG %d. Members now %016llx.\n",
|
||||
__func__, port, group, priv->lags_port_members[group]);
|
||||
@@ -443,6 +418,7 @@ int rtl83xx_lag_add(struct dsa_switch *ds, int group, int port, struct netdev_la
|
||||
int rtl83xx_lag_del(struct dsa_switch *ds, int group, int port)
|
||||
{
|
||||
struct rtl838x_switch_priv *priv = ds->priv;
|
||||
int ret;
|
||||
|
||||
if (group >= priv->ds->num_lag_ids) {
|
||||
pr_err("%s: LAG %d invalid.\n", __func__, group);
|
||||
@@ -454,9 +430,17 @@ int rtl83xx_lag_del(struct dsa_switch *ds, int group, int port)
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
/* 0x7f algo mask all */
|
||||
priv->r->mask_port_reg_be(BIT_ULL(port), 0, priv->r->trk_mbr_ctr(group));
|
||||
priv->lags_port_members[group] &= ~BIT_ULL(port);
|
||||
/* Don't touch hash mask bits, as only the port might be removed from
|
||||
* the LAG group. This means the lag group stays valid with existing
|
||||
* mask algo bits. If there are no lag members left, then
|
||||
* rtl83xx_lag_add will reconfigure hash mask when new LAG group is
|
||||
* created.
|
||||
*/
|
||||
ret = priv->r->lag_set_port_members(priv, group,
|
||||
priv->lags_port_members[group] & ~BIT_ULL(port),
|
||||
NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pr_info("%s: Removed port %d from LAG %d. Members now %016llx.\n",
|
||||
__func__, port, group, priv->lags_port_members[group]);
|
||||
@@ -464,6 +448,234 @@ int rtl83xx_lag_del(struct dsa_switch *ds, int group, int port)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtldsa_93xx_lag_set_distribution_algorithm(struct rtl838x_switch_priv *priv,
|
||||
int group, int algoidx, u32 algomsk)
|
||||
{
|
||||
bool is_l3 = false;
|
||||
u32 newmask = 0;
|
||||
|
||||
if (algomsk & TRUNK_DISTRIBUTION_ALGO_SIP_BIT) {
|
||||
is_l3 = true;
|
||||
newmask |= TRUNK_DISTRIBUTION_ALGO_L3_SIP_BIT;
|
||||
}
|
||||
if (algomsk & TRUNK_DISTRIBUTION_ALGO_DIP_BIT) {
|
||||
is_l3 = true;
|
||||
newmask |= TRUNK_DISTRIBUTION_ALGO_L3_DIP_BIT;
|
||||
}
|
||||
if (algomsk & TRUNK_DISTRIBUTION_ALGO_SRC_L4PORT_BIT) {
|
||||
is_l3 = true;
|
||||
newmask |= TRUNK_DISTRIBUTION_ALGO_L3_SRC_L4PORT_BIT;
|
||||
}
|
||||
|
||||
if (algomsk & TRUNK_DISTRIBUTION_ALGO_DST_L4PORT_BIT) {
|
||||
is_l3 = true;
|
||||
newmask |= TRUNK_DISTRIBUTION_ALGO_L3_DST_L4PORT_BIT;
|
||||
}
|
||||
|
||||
if (is_l3) {
|
||||
if (algomsk & TRUNK_DISTRIBUTION_ALGO_SPA_BIT)
|
||||
newmask |= TRUNK_DISTRIBUTION_ALGO_L3_SPA_BIT;
|
||||
if (algomsk & TRUNK_DISTRIBUTION_ALGO_SMAC_BIT)
|
||||
newmask |= TRUNK_DISTRIBUTION_ALGO_L3_SMAC_BIT;
|
||||
if (algomsk & TRUNK_DISTRIBUTION_ALGO_DMAC_BIT)
|
||||
newmask |= TRUNK_DISTRIBUTION_ALGO_L3_DMAC_BIT;
|
||||
if (algomsk & TRUNK_DISTRIBUTION_ALGO_VLAN_BIT)
|
||||
newmask |= TRUNK_DISTRIBUTION_ALGO_L3_VLAN_BIT;
|
||||
} else {
|
||||
if (algomsk & TRUNK_DISTRIBUTION_ALGO_SPA_BIT)
|
||||
newmask |= TRUNK_DISTRIBUTION_ALGO_L2_SPA_BIT;
|
||||
if (algomsk & TRUNK_DISTRIBUTION_ALGO_SMAC_BIT)
|
||||
newmask |= TRUNK_DISTRIBUTION_ALGO_L2_SMAC_BIT;
|
||||
if (algomsk & TRUNK_DISTRIBUTION_ALGO_DMAC_BIT)
|
||||
newmask |= TRUNK_DISTRIBUTION_ALGO_L2_DMAC_BIT;
|
||||
if (algomsk & TRUNK_DISTRIBUTION_ALGO_VLAN_BIT)
|
||||
newmask |= TRUNK_DISTRIBUTION_ALGO_L2_VLAN_BIT;
|
||||
}
|
||||
|
||||
sw_w32(newmask, priv->r->trk_hash_ctrl + (algoidx << 2));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtldsa_83xx_lag_setup_algomask(struct rtl838x_switch_priv *priv, int group,
|
||||
struct netdev_lag_upper_info *info)
|
||||
{
|
||||
u32 algomsk = 0;
|
||||
u32 algoidx = 0;
|
||||
|
||||
switch (info->hash_type) {
|
||||
case NETDEV_LAG_HASH_L2:
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_DMAC_BIT;
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_SMAC_BIT;
|
||||
break;
|
||||
case NETDEV_LAG_HASH_L23:
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_DMAC_BIT;
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_SMAC_BIT;
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_SIP_BIT; /* source ip */
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_DIP_BIT; /* dest ip */
|
||||
algoidx = 1;
|
||||
break;
|
||||
case NETDEV_LAG_HASH_L34:
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_SRC_L4PORT_BIT; /* sport */
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_DST_L4PORT_BIT; /* dport */
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_SIP_BIT; /* source ip */
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_DIP_BIT; /* dest ip */
|
||||
algoidx = 2;
|
||||
break;
|
||||
default:
|
||||
algomsk |= TRUNK_DISTRIBUTION_ALGO_MASKALL;
|
||||
}
|
||||
|
||||
return priv->r->lag_set_distribution_algorithm(priv, group, algoidx, algomsk);
|
||||
}
|
||||
|
||||
static int rtldsa_93xx_lag_set_group2ports(struct rtl838x_switch_priv *priv, int group,
|
||||
struct netdev_lag_upper_info *info)
|
||||
{
|
||||
DECLARE_BITMAP(ports, ARRAY_SIZE(priv->ports));
|
||||
struct rtldsa_93xx_lag_entry e;
|
||||
unsigned int table_pos = 0;
|
||||
u8 num_of_lag_ports = 0;
|
||||
u8 group_ports[8];
|
||||
u32 data[3];
|
||||
int i;
|
||||
|
||||
/* Read lag table using Table control register 2 */
|
||||
struct table_reg *r = priv->r->lag_table();
|
||||
|
||||
rtl_table_read(r, group);
|
||||
|
||||
bitmap_clear(ports, 0, ARRAY_SIZE(priv->ports));
|
||||
bitmap_from_arr64(ports, &priv->lags_port_members[group],
|
||||
ARRAY_SIZE(priv->ports));
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
data[i] = sw_r32(rtl_table_data(r, i));
|
||||
|
||||
priv->r->lag_fill_data(data, &e);
|
||||
|
||||
num_of_lag_ports = bitmap_weight(ports, ARRAY_SIZE(priv->ports));
|
||||
if (num_of_lag_ports > ARRAY_SIZE(group_ports)) {
|
||||
pr_err("%s: Number of LAG ports too high: %u", __func__,
|
||||
num_of_lag_ports);
|
||||
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
memset(group_ports, 0x3f, sizeof(group_ports));
|
||||
|
||||
table_pos = 0;
|
||||
for_each_set_bit(i, ports, ARRAY_SIZE(priv->ports)) {
|
||||
struct net_device *lag_slave = priv->ports[i].dp->user;
|
||||
|
||||
if (lag_slave && !net_lag_port_dev_txable(lag_slave))
|
||||
continue;
|
||||
|
||||
group_ports[table_pos] = i;
|
||||
table_pos++;
|
||||
}
|
||||
|
||||
/* Remove tx disabled ports */
|
||||
num_of_lag_ports = table_pos;
|
||||
|
||||
e.trk_dev0 = 0;
|
||||
e.trk_port0 = group_ports[0];
|
||||
e.trk_dev1 = 0;
|
||||
e.trk_port1 = group_ports[1];
|
||||
e.trk_dev2 = 0;
|
||||
e.trk_port2 = group_ports[2];
|
||||
e.trk_dev3 = 0;
|
||||
e.trk_port3 = group_ports[3];
|
||||
e.trk_dev4 = 0;
|
||||
e.trk_port4 = group_ports[4];
|
||||
e.trk_dev5 = 0;
|
||||
e.trk_port5 = group_ports[5];
|
||||
e.trk_dev6 = 0;
|
||||
e.trk_port6 = group_ports[6];
|
||||
e.trk_dev7 = 0;
|
||||
e.trk_port7 = group_ports[7];
|
||||
|
||||
e.num_tx_candi = num_of_lag_ports;
|
||||
|
||||
/* set hash_mask_idx to 0 if we are deleting lag group */
|
||||
if (info) {
|
||||
if (info->hash_type == NETDEV_LAG_HASH_L2) {
|
||||
e.l2_hash_mask_idx = RTL93XX_HASH_MASK_INDEX_L2;
|
||||
e.ip4_hash_mask_idx = RTL93XX_HASH_MASK_INDEX_L2;
|
||||
e.ip6_hash_mask_idx = RTL93XX_HASH_MASK_INDEX_L2;
|
||||
} else if (info->hash_type == NETDEV_LAG_HASH_L23) {
|
||||
e.l2_hash_mask_idx = RTL93XX_HASH_MASK_INDEX_L23;
|
||||
e.ip4_hash_mask_idx = RTL93XX_HASH_MASK_INDEX_L23;
|
||||
e.ip6_hash_mask_idx = RTL93XX_HASH_MASK_INDEX_L23;
|
||||
} else {
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
priv->r->lag_write_data(data, &e);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
sw_w32(data[i], rtl_table_data(r, i));
|
||||
rtl_table_write(r, group);
|
||||
rtl_table_release(r);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void rtldsa_93xx_lag_set_local_group2ports(struct rtl838x_switch_priv *priv, int group,
|
||||
u64 ports)
|
||||
{
|
||||
priv->r->set_port_reg_be(ports, priv->r->trk_mbr_ctr(group));
|
||||
}
|
||||
|
||||
int rtldsa_93xx_lag_set_port_members(struct rtl838x_switch_priv *priv, int group,
|
||||
u64 members, struct netdev_lag_upper_info *info)
|
||||
{
|
||||
DECLARE_BITMAP(affected_members, ARRAY_SIZE(priv->ports));
|
||||
bool valid_group;
|
||||
u64 old_members;
|
||||
u64 affected;
|
||||
size_t port;
|
||||
int ret;
|
||||
|
||||
/* calculate modifications of the LAG group */
|
||||
old_members = priv->lags_port_members[group];
|
||||
priv->lags_port_members[group] = members;
|
||||
|
||||
affected = old_members | priv->lags_port_members[group];
|
||||
|
||||
bitmap_clear(affected_members, 0, ARRAY_SIZE(priv->ports));
|
||||
bitmap_from_arr64(affected_members, &affected, BITS_PER_TYPE(affected));
|
||||
|
||||
valid_group = __sw_hweight64(priv->lags_port_members[group]);
|
||||
|
||||
/* apply global group and port settings */
|
||||
ret = rtldsa_93xx_lag_set_group2ports(priv, group, info);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for_each_set_bit(port, affected_members, ARRAY_SIZE(priv->ports)) {
|
||||
bool valid = priv->lags_port_members[group] & BIT_ULL(port);
|
||||
|
||||
priv->r->lag_set_port2group(group, port, valid);
|
||||
}
|
||||
|
||||
/* apply local group and port settings */
|
||||
priv->r->lag_set_local_group_id(group, group, valid_group);
|
||||
rtldsa_93xx_lag_set_local_group2ports(priv, group, priv->lags_port_members[group]);
|
||||
|
||||
for_each_set_bit(port, affected_members, ARRAY_SIZE(priv->ports)) {
|
||||
bool valid = priv->lags_port_members[group] & BIT_ULL(port);
|
||||
|
||||
priv->r->lag_set_local_port2group(group, port, valid);
|
||||
}
|
||||
|
||||
/* write lag table (and maybe additional information) to SRAM */
|
||||
priv->r->lag_sync_tables();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Currently Unused
|
||||
// /* Allocate a 64 bit octet counter located in the LOG HW table */
|
||||
// static int rtl83xx_octet_cntr_alloc(struct rtl838x_switch_priv *priv)
|
||||
@@ -1574,6 +1786,9 @@ static int rtl83xx_sw_probe(struct platform_device *pdev)
|
||||
break;
|
||||
}
|
||||
|
||||
if (priv->r->lag_switch_init)
|
||||
priv->r->lag_switch_init(priv);
|
||||
|
||||
return 0;
|
||||
|
||||
err_register_fib_nb:
|
||||
@@ -1586,6 +1801,30 @@ err_register_switch:
|
||||
return err;
|
||||
}
|
||||
|
||||
void rtldsa_93xx_lag_switch_init(struct rtl838x_switch_priv *priv)
|
||||
{
|
||||
u32 trk_ctrlmask = 0;
|
||||
u32 algomask;
|
||||
|
||||
trk_ctrlmask |= RTL93XX_TRK_CTRL_NON_TMN_TUNNEL_HASH_SEL;
|
||||
trk_ctrlmask |= RTL93XX_TRK_CTRL_TRK_STAND_ALONE_MODE;
|
||||
trk_ctrlmask |= RTL93XX_TRK_CTRL_LOCAL_FIRST;
|
||||
|
||||
sw_w32(trk_ctrlmask, priv->r->trk_ctrl);
|
||||
|
||||
/* Setup NETDEV_LAG_HASH_L2 on slot 0 */
|
||||
algomask = TRUNK_DISTRIBUTION_ALGO_SMAC_BIT |
|
||||
TRUNK_DISTRIBUTION_ALGO_DMAC_BIT;
|
||||
priv->r->lag_set_distribution_algorithm(priv, 0, RTL93XX_HASH_MASK_INDEX_L2, algomask);
|
||||
|
||||
/* Setup NETDEV_LAG_HASH_L23 on slot 1 */
|
||||
algomask = TRUNK_DISTRIBUTION_ALGO_SMAC_BIT |
|
||||
TRUNK_DISTRIBUTION_ALGO_DMAC_BIT |
|
||||
TRUNK_DISTRIBUTION_ALGO_SIP_BIT |
|
||||
TRUNK_DISTRIBUTION_ALGO_DIP_BIT;
|
||||
priv->r->lag_set_distribution_algorithm(priv, 0, RTL93XX_HASH_MASK_INDEX_L23, algomask);
|
||||
}
|
||||
|
||||
static void rtl83xx_sw_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rtl838x_switch_priv *priv = platform_get_drvdata(pdev);
|
||||
|
||||
@@ -160,7 +160,7 @@ static ssize_t rtl838x_common_write(const char __user *buffer, size_t count,
|
||||
static ssize_t stp_state_read(struct file *filp, char __user *buffer, size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct rtl838x_port *p = filp->private_data;
|
||||
struct rtldsa_port *p = filp->private_data;
|
||||
struct dsa_switch *ds = p->dp->ds;
|
||||
int state = rtldsa_port_get_stp_state(ds->priv, p->dp->index);
|
||||
|
||||
@@ -173,7 +173,7 @@ static ssize_t stp_state_read(struct file *filp, char __user *buffer, size_t cou
|
||||
static ssize_t stp_state_write(struct file *filp, const char __user *buffer,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct rtl838x_port *p = filp->private_data;
|
||||
struct rtldsa_port *p = filp->private_data;
|
||||
u32 value;
|
||||
size_t res = rtl838x_common_write(buffer, count, ppos, &value);
|
||||
|
||||
@@ -268,6 +268,13 @@ static void l2_table_print_entry(struct seq_file *m, struct rtl838x_switch_priv
|
||||
e->vid, e->rvid);
|
||||
|
||||
seq_printf(m, " port %d age %d", e->port, e->age);
|
||||
if (e->is_trunk) {
|
||||
seq_printf(m, " trunk %d trunk_members: 0x%08llx non-primary: 0x%08llx primary-port: %d",
|
||||
e->trunk,
|
||||
priv->lags_port_members[e->trunk],
|
||||
priv->lag_non_primary,
|
||||
priv->lag_primary[e->trunk]);
|
||||
}
|
||||
if (e->is_static)
|
||||
seq_puts(m, " static");
|
||||
if (e->block_da)
|
||||
@@ -586,7 +593,7 @@ static const struct file_operations rtldsa_vlan_table_fops = {
|
||||
static ssize_t age_out_read(struct file *filp, char __user *buffer, size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct rtl838x_port *p = filp->private_data;
|
||||
struct rtldsa_port *p = filp->private_data;
|
||||
struct dsa_switch *ds = p->dp->ds;
|
||||
struct rtl838x_switch_priv *priv = ds->priv;
|
||||
int value = sw_r32(priv->r->l2_port_aging_out);
|
||||
@@ -600,7 +607,7 @@ static ssize_t age_out_read(struct file *filp, char __user *buffer, size_t count
|
||||
static ssize_t age_out_write(struct file *filp, const char __user *buffer,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct rtl838x_port *p = filp->private_data;
|
||||
struct rtldsa_port *p = filp->private_data;
|
||||
u32 value;
|
||||
size_t res = rtl838x_common_write(buffer, count, ppos, &value);
|
||||
|
||||
@@ -622,7 +629,7 @@ static const struct file_operations age_out_fops = {
|
||||
static ssize_t port_egress_rate_read(struct file *filp, char __user *buffer, size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct rtl838x_port *p = filp->private_data;
|
||||
struct rtldsa_port *p = filp->private_data;
|
||||
struct dsa_switch *ds = p->dp->ds;
|
||||
struct rtl838x_switch_priv *priv = ds->priv;
|
||||
int value;
|
||||
@@ -641,7 +648,7 @@ static ssize_t port_egress_rate_read(struct file *filp, char __user *buffer, siz
|
||||
static ssize_t port_egress_rate_write(struct file *filp, const char __user *buffer,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct rtl838x_port *p = filp->private_data;
|
||||
struct rtldsa_port *p = filp->private_data;
|
||||
struct dsa_switch *ds = p->dp->ds;
|
||||
struct rtl838x_switch_priv *priv = ds->priv;
|
||||
u32 value;
|
||||
|
||||
@@ -50,7 +50,7 @@ static void rtldsa_enable_phy_polling(struct rtl838x_switch_priv *priv)
|
||||
msleep(1000);
|
||||
/* Enable all ports with a PHY, including the SFP-ports */
|
||||
for (int i = 0; i < priv->cpu_port; i++) {
|
||||
if (priv->ports[i].phy || priv->pcs[i])
|
||||
if (priv->ports[i].phy || priv->ports[i].pcs)
|
||||
v |= BIT_ULL(i);
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ static int rtldsa_83xx_setup(struct dsa_switch *ds)
|
||||
* they will work in isolated mode (only traffic between port and CPU).
|
||||
*/
|
||||
for (int i = 0; i < priv->cpu_port; i++) {
|
||||
if (priv->ports[i].phy || priv->pcs[i]) {
|
||||
if (priv->ports[i].phy || priv->ports[i].pcs) {
|
||||
priv->ports[i].pm = BIT_ULL(priv->cpu_port);
|
||||
priv->r->traffic_set(i, BIT_ULL(i));
|
||||
}
|
||||
@@ -253,7 +253,7 @@ static int rtldsa_93xx_setup(struct dsa_switch *ds)
|
||||
* they will work in isolated mode (only traffic between port and CPU).
|
||||
*/
|
||||
for (int i = 0; i < priv->cpu_port; i++) {
|
||||
if (priv->ports[i].phy || priv->pcs[i]) {
|
||||
if (priv->ports[i].phy || priv->ports[i].pcs) {
|
||||
priv->ports[i].pm = BIT_ULL(priv->cpu_port);
|
||||
priv->r->traffic_set(i, BIT_ULL(i));
|
||||
}
|
||||
@@ -291,7 +291,7 @@ static struct phylink_pcs *rtldsa_phylink_mac_select_pcs(struct dsa_switch *ds,
|
||||
{
|
||||
struct rtl838x_switch_priv *priv = ds->priv;
|
||||
|
||||
return priv->pcs[port];
|
||||
return priv->ports[port].pcs;
|
||||
}
|
||||
|
||||
static void rtldsa_83xx_phylink_get_caps(struct dsa_switch *ds, int port,
|
||||
@@ -767,7 +767,7 @@ static void rtldsa_poll_counters(struct work_struct *work)
|
||||
counters_work);
|
||||
|
||||
for (int port = 0; port < priv->cpu_port; port++) {
|
||||
if (!priv->ports[port].phy && !priv->pcs[port])
|
||||
if (!priv->ports[port].phy && !priv->ports[port].pcs)
|
||||
continue;
|
||||
|
||||
rtldsa_counters_lock(priv, port);
|
||||
@@ -784,7 +784,7 @@ static void rtldsa_init_counters(struct rtl838x_switch_priv *priv)
|
||||
struct rtldsa_counter_state *counters;
|
||||
|
||||
for (int port = 0; port < priv->cpu_port; port++) {
|
||||
if (!priv->ports[port].phy && !priv->pcs[port])
|
||||
if (!priv->ports[port].phy && !priv->ports[port].pcs)
|
||||
continue;
|
||||
|
||||
counters = &priv->ports[port].counters;
|
||||
@@ -1360,10 +1360,10 @@ static void rtldsa_update_port_member(struct rtl838x_switch_priv *priv, int port
|
||||
__must_hold(&priv->reg_mutex)
|
||||
{
|
||||
struct dsa_port *dp = dsa_to_port(priv->ds, port);
|
||||
struct rtl838x_port *p = &priv->ports[port];
|
||||
struct rtldsa_port *p = &priv->ports[port];
|
||||
struct dsa_port *cpu_dp = dp->cpu_dp;
|
||||
u64 port_mask = BIT_ULL(cpu_dp->index);
|
||||
struct rtl838x_port *other_p;
|
||||
struct rtldsa_port *other_p;
|
||||
struct dsa_port *other_dp;
|
||||
int other_port;
|
||||
bool isolated;
|
||||
@@ -1865,6 +1865,39 @@ static int rtldsa_find_l2_cam_entry(struct rtl838x_switch_priv *priv, u64 seed,
|
||||
return idx;
|
||||
}
|
||||
|
||||
/**
|
||||
* rtldsa_find_lag_group_from_port() - Find lag group of current port
|
||||
* @priv: private data of rtldsa switch
|
||||
* @port: port id of potential LAG member
|
||||
* Return: -ENOENT when port does not belong to any lag group, lag id otherwise
|
||||
*/
|
||||
static int rtldsa_find_lag_group_from_port(struct rtl838x_switch_priv *priv, int port)
|
||||
{
|
||||
if (!(priv->lagmembers & BIT_ULL(port)))
|
||||
return -ENOENT;
|
||||
|
||||
/* port is a lag member */
|
||||
for (int lag_group = 0; lag_group < MAX_LAGS; lag_group++) {
|
||||
if (priv->lags_port_members[lag_group] & BIT_ULL(port))
|
||||
return lag_group;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* rtldsa_93xx_prepare_lag_fdb() - Prepare fdb entry for LAG
|
||||
* @e: L2 entry data
|
||||
* @lag_group: lag id of the trunk group
|
||||
*/
|
||||
inline void rtldsa_93xx_prepare_lag_fdb(struct rtl838x_l2_entry *e, int lag_group)
|
||||
{
|
||||
if (e && lag_group >= 0) {
|
||||
e->is_trunk = true;
|
||||
e->trunk = lag_group;
|
||||
}
|
||||
}
|
||||
|
||||
static int rtldsa_port_fdb_add(struct dsa_switch *ds, int port,
|
||||
const unsigned char *addr, u16 vid,
|
||||
const struct dsa_db db)
|
||||
@@ -1874,10 +1907,16 @@ static int rtldsa_port_fdb_add(struct dsa_switch *ds, int port,
|
||||
struct rtl838x_l2_entry e;
|
||||
int err = 0, idx;
|
||||
u64 seed = priv->r->l2_hash_seed(mac, vid);
|
||||
int lag_group = rtldsa_find_lag_group_from_port(priv, port);
|
||||
|
||||
if (priv->lag_non_primary & BIT_ULL(port)) {
|
||||
pr_debug("%s: %d is lag slave. ignore\n", __func__, port);
|
||||
return 0;
|
||||
if (lag_group >= 0 && priv->r->prepare_lag_fdb) {
|
||||
priv->r->prepare_lag_fdb(&e, lag_group);
|
||||
} else {
|
||||
if (priv->lag_non_primary & BIT_ULL(port)) {
|
||||
pr_debug("%s: %d is lag slave but prepare_lag_fdb is not supported. ignore\n",
|
||||
__func__, port);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
@@ -1917,8 +1956,13 @@ static int rtldsa_port_fdb_del(struct dsa_switch *ds, int port,
|
||||
struct rtl838x_l2_entry e;
|
||||
int err = 0, idx;
|
||||
u64 seed = priv->r->l2_hash_seed(mac, vid);
|
||||
int lag_group = rtldsa_find_lag_group_from_port(priv, port);
|
||||
|
||||
if (lag_group >= 0 && priv->r->prepare_lag_fdb)
|
||||
priv->r->prepare_lag_fdb(&e, lag_group);
|
||||
|
||||
pr_debug("In %s, mac %llx, vid: %d\n", __func__, mac, vid);
|
||||
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
|
||||
idx = rtldsa_find_l2_hash_entry(priv, seed, true, &e);
|
||||
@@ -1960,6 +2004,10 @@ static int rtldsa_port_fdb_dump(struct dsa_switch *ds, int port,
|
||||
if (!e.valid)
|
||||
continue;
|
||||
|
||||
// Ignore trunk fdb entries
|
||||
if (e.is_trunk)
|
||||
continue;
|
||||
|
||||
if (e.port == port || e.port == RTL930X_PORT_IGNORE)
|
||||
cb(e.mac, e.vid, e.is_static, data);
|
||||
|
||||
@@ -1973,6 +2021,10 @@ static int rtldsa_port_fdb_dump(struct dsa_switch *ds, int port,
|
||||
if (!e.valid)
|
||||
continue;
|
||||
|
||||
// Ignore trunk fdb entries
|
||||
if (e.is_trunk)
|
||||
continue;
|
||||
|
||||
if (e.port == port)
|
||||
cb(e.mac, e.vid, e.is_static, data);
|
||||
}
|
||||
@@ -2325,8 +2377,28 @@ static bool rtldsa_83xx_lag_can_offload(struct dsa_switch *ds,
|
||||
|
||||
static int rtldsa_port_lag_change(struct dsa_switch *ds, int port)
|
||||
{
|
||||
pr_debug("%s: %d\n", __func__, port);
|
||||
/* Nothing to be done... */
|
||||
struct dsa_port *dp = dsa_to_port(ds, port);
|
||||
struct rtl838x_switch_priv *priv = ds->priv;
|
||||
int lag_group;
|
||||
int ret;
|
||||
|
||||
if (!dp)
|
||||
return -EINVAL;
|
||||
|
||||
lag_group = rtldsa_find_lag_group_from_port(priv, port);
|
||||
if (lag_group < 0)
|
||||
return lag_group;
|
||||
|
||||
if (priv->r->lag_set_port_members) {
|
||||
/* Set same port members again, the function should check against
|
||||
* lag_tx_enabled and set egress ports accordingly.
|
||||
*/
|
||||
ret = priv->r->lag_set_port_members(priv, lag_group,
|
||||
priv->lags_port_members[lag_group],
|
||||
NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2396,7 +2468,6 @@ static int rtldsa_port_lag_leave(struct dsa_switch *ds, int port,
|
||||
}
|
||||
pr_info("port_lag_del: group %d, port %d\n", group, port);
|
||||
priv->lagmembers &= ~BIT_ULL(port);
|
||||
priv->lag_primary[group] = -1;
|
||||
priv->lag_non_primary &= ~BIT_ULL(port);
|
||||
pr_debug("lag_members = %llX\n", priv->lagmembers);
|
||||
err = rtl83xx_lag_del(priv->ds, group, port);
|
||||
@@ -2405,6 +2476,19 @@ static int rtldsa_port_lag_leave(struct dsa_switch *ds, int port,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* To re-elect primary interface, just remove the first interface in
|
||||
* this-group's interfaces from non-primary
|
||||
*/
|
||||
if (priv->lags_port_members[group]) {
|
||||
priv->lag_primary[group] = fls64(priv->lags_port_members[group]);
|
||||
priv->lag_non_primary &= ~BIT_ULL(priv->lag_primary[group]);
|
||||
}
|
||||
|
||||
/* No need to update fdb entries since they make use of trunk_id for entry.
|
||||
* The primary interface is only calculated at time of
|
||||
* port_fdb_dump
|
||||
*/
|
||||
|
||||
out:
|
||||
mutex_unlock(&priv->reg_mutex);
|
||||
return 0;
|
||||
@@ -2467,7 +2551,7 @@ static int rtldsa_cls_flower_add(struct dsa_switch *ds, int port,
|
||||
bool ingress)
|
||||
{
|
||||
struct rtl838x_switch_priv *priv = ds->priv;
|
||||
struct rtl838x_port *p = &priv->ports[port];
|
||||
struct rtldsa_port *p = &priv->ports[port];
|
||||
const struct flow_action_entry *act;
|
||||
int ret;
|
||||
|
||||
@@ -2513,7 +2597,7 @@ static int rtldsa_cls_flower_del(struct dsa_switch *ds, int port,
|
||||
bool ingress)
|
||||
{
|
||||
struct rtl838x_switch_priv *priv = ds->priv;
|
||||
struct rtl838x_port *p = &priv->ports[port];
|
||||
struct rtldsa_port *p = &priv->ports[port];
|
||||
int ret;
|
||||
|
||||
if (!priv->r->port_rate_police_del)
|
||||
|
||||
@@ -1748,12 +1748,14 @@ static void rtl838x_set_egr_filter(int port, enum egr_filter state)
|
||||
RTL838X_VLAN_PORT_EGR_FLTR + (((port / 29) << 2)));
|
||||
}
|
||||
|
||||
static void rtl838x_set_distribution_algorithm(int group, int algoidx, u32 algomsk)
|
||||
static int rtldsa_838x_set_distribution_algorithm(struct rtl838x_switch_priv *priv,
|
||||
int group, int algoidx, u32 algomsk)
|
||||
{
|
||||
algoidx &= 1; /* RTL838X only supports 2 concurrent algorithms */
|
||||
sw_w32_mask(1 << (group % 8), algoidx << (group % 8),
|
||||
RTL838X_TRK_HASH_IDX_CTRL + ((group >> 3) << 2));
|
||||
sw_w32(algomsk, RTL838X_TRK_HASH_CTRL + (algoidx << 2));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtl838x_set_receive_management_action(int port, rma_ctrl_t type, action_type_t action)
|
||||
@@ -1790,6 +1792,20 @@ rtldsa_838x_vlan_profile_dump(struct rtl838x_switch_priv *priv, int idx)
|
||||
p.unkn_mc_fld.pmsks_idx.ip, p.unkn_mc_fld.pmsks_idx.ip6);
|
||||
}
|
||||
|
||||
static int rtldsa_838x_lag_set_port_members(struct rtl838x_switch_priv *priv, int group,
|
||||
u64 members, struct netdev_lag_upper_info *info)
|
||||
{
|
||||
priv->lags_port_members[group] = members;
|
||||
|
||||
priv->r->set_port_reg_be(priv->lags_port_members[group],
|
||||
priv->r->trk_mbr_ctr(group));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtldsa_83xx_lag_setup_algomask(struct rtl838x_switch_priv *priv, int group,
|
||||
struct netdev_lag_upper_info *info);
|
||||
|
||||
const struct rtldsa_config rtldsa_838x_cfg = {
|
||||
.mask_port_reg_be = rtl838x_mask_port_reg,
|
||||
.set_port_reg_be = rtl838x_set_port_reg,
|
||||
@@ -1875,9 +1891,11 @@ const struct rtldsa_config rtldsa_838x_cfg = {
|
||||
.route_read = rtl838x_route_read,
|
||||
.route_write = rtl838x_route_write,
|
||||
.l3_setup = rtl838x_l3_setup,
|
||||
.set_distribution_algorithm = rtl838x_set_distribution_algorithm,
|
||||
.set_receive_management_action = rtl838x_set_receive_management_action,
|
||||
.qos_init = rtldsa_838x_qos_init,
|
||||
.lag_set_distribution_algorithm = rtldsa_838x_set_distribution_algorithm,
|
||||
.lag_set_port_members = rtldsa_838x_lag_set_port_members,
|
||||
.lag_setup_algomask = rtldsa_83xx_lag_setup_algomask,
|
||||
};
|
||||
|
||||
irqreturn_t rtl838x_switch_irq(int irq, void *dev_id)
|
||||
|
||||
@@ -371,32 +371,32 @@
|
||||
#define RTL839X_IGR_BWCTRL_CTRL_LB_THR (0x1614)
|
||||
|
||||
/* Link aggregation (Trunking) */
|
||||
#define TRUNK_DISTRIBUTION_ALGO_SPA_BIT 0x01
|
||||
#define TRUNK_DISTRIBUTION_ALGO_SMAC_BIT 0x02
|
||||
#define TRUNK_DISTRIBUTION_ALGO_DMAC_BIT 0x04
|
||||
#define TRUNK_DISTRIBUTION_ALGO_SIP_BIT 0x08
|
||||
#define TRUNK_DISTRIBUTION_ALGO_DIP_BIT 0x10
|
||||
#define TRUNK_DISTRIBUTION_ALGO_SRC_L4PORT_BIT 0x20
|
||||
#define TRUNK_DISTRIBUTION_ALGO_DST_L4PORT_BIT 0x40
|
||||
#define TRUNK_DISTRIBUTION_ALGO_MASKALL 0x7F
|
||||
#define TRUNK_DISTRIBUTION_ALGO_SPA_BIT BIT(0)
|
||||
#define TRUNK_DISTRIBUTION_ALGO_SMAC_BIT BIT(1)
|
||||
#define TRUNK_DISTRIBUTION_ALGO_DMAC_BIT BIT(2)
|
||||
|
||||
#define TRUNK_DISTRIBUTION_ALGO_L2_SPA_BIT 0x01
|
||||
#define TRUNK_DISTRIBUTION_ALGO_L2_SMAC_BIT 0x02
|
||||
#define TRUNK_DISTRIBUTION_ALGO_L2_DMAC_BIT 0x04
|
||||
#define TRUNK_DISTRIBUTION_ALGO_L2_VLAN_BIT 0x08
|
||||
#define TRUNK_DISTRIBUTION_ALGO_L2_MASKALL 0xF
|
||||
#define TRUNK_DISTRIBUTION_ALGO_SIP_BIT BIT(3)
|
||||
#define TRUNK_DISTRIBUTION_ALGO_DIP_BIT BIT(4)
|
||||
#define TRUNK_DISTRIBUTION_ALGO_SRC_L4PORT_BIT BIT(5)
|
||||
#define TRUNK_DISTRIBUTION_ALGO_DST_L4PORT_BIT BIT(6)
|
||||
#define TRUNK_DISTRIBUTION_ALGO_VLAN_BIT BIT(7)
|
||||
#define TRUNK_DISTRIBUTION_ALGO_MASKALL GENMASK(6, 0)
|
||||
|
||||
#define TRUNK_DISTRIBUTION_ALGO_L3_SPA_BIT 0x01
|
||||
#define TRUNK_DISTRIBUTION_ALGO_L3_SMAC_BIT 0x02
|
||||
#define TRUNK_DISTRIBUTION_ALGO_L3_DMAC_BIT 0x04
|
||||
#define TRUNK_DISTRIBUTION_ALGO_L3_VLAN_BIT 0x08
|
||||
#define TRUNK_DISTRIBUTION_ALGO_L3_SIP_BIT 0x10
|
||||
#define TRUNK_DISTRIBUTION_ALGO_L3_DIP_BIT 0x20
|
||||
#define TRUNK_DISTRIBUTION_ALGO_L3_SRC_L4PORT_BIT 0x40
|
||||
#define TRUNK_DISTRIBUTION_ALGO_L3_DST_L4PORT_BIT 0x80
|
||||
#define TRUNK_DISTRIBUTION_ALGO_L3_PROTO_BIT 0x100
|
||||
#define TRUNK_DISTRIBUTION_ALGO_L3_FLOW_LABEL_BIT 0x200
|
||||
#define TRUNK_DISTRIBUTION_ALGO_L3_MASKALL 0x3FF
|
||||
#define TRUNK_DISTRIBUTION_ALGO_L2_SPA_BIT BIT(0)
|
||||
#define TRUNK_DISTRIBUTION_ALGO_L2_SMAC_BIT BIT(1)
|
||||
#define TRUNK_DISTRIBUTION_ALGO_L2_DMAC_BIT BIT(2)
|
||||
#define TRUNK_DISTRIBUTION_ALGO_L2_VLAN_BIT BIT(3)
|
||||
|
||||
#define TRUNK_DISTRIBUTION_ALGO_L3_SPA_BIT BIT(4 + 0)
|
||||
#define TRUNK_DISTRIBUTION_ALGO_L3_SMAC_BIT BIT(4 + 1)
|
||||
#define TRUNK_DISTRIBUTION_ALGO_L3_DMAC_BIT BIT(4 + 2)
|
||||
#define TRUNK_DISTRIBUTION_ALGO_L3_VLAN_BIT BIT(4 + 3)
|
||||
#define TRUNK_DISTRIBUTION_ALGO_L3_SIP_BIT BIT(4 + 4)
|
||||
#define TRUNK_DISTRIBUTION_ALGO_L3_DIP_BIT BIT(4 + 5)
|
||||
#define TRUNK_DISTRIBUTION_ALGO_L3_SRC_L4PORT_BIT BIT(4 + 6)
|
||||
#define TRUNK_DISTRIBUTION_ALGO_L3_DST_L4PORT_BIT BIT(4 + 7)
|
||||
#define TRUNK_DISTRIBUTION_ALGO_L3_PROTO_BIT BIT(4 + 8)
|
||||
#define TRUNK_DISTRIBUTION_ALGO_L3_FLOW_LABEL_BIT BIT(4 + 9)
|
||||
|
||||
#define RTL838X_TRK_MBR_CTR (0x3E00)
|
||||
#define RTL838X_TRK_HASH_IDX_CTRL (0x3E20)
|
||||
@@ -406,11 +406,98 @@
|
||||
#define RTL839X_TRK_HASH_IDX_CTRL (0x2280)
|
||||
#define RTL839X_TRK_HASH_CTRL (0x2284)
|
||||
|
||||
#define RTL930X_LOCAL_PORT_TRK_MAP (0xD0C8)
|
||||
#define RTL930X_TRK_ID_CTRL (0xA3A8)
|
||||
#define RTL930X_TRK_MBR_CTRL (0xA41C)
|
||||
#define RTL930X_TRK_HASH_CTRL (0x9F80)
|
||||
#define RTL930X_TRK_CTRL (0x9F88)
|
||||
#define RTL930X_TRK_SHIFT_CTRL (0x9F8C)
|
||||
#define RTL930X_TRK_LOCAL_TBL_REFRESH (0x9F90)
|
||||
#define RTL930X_TRK_LOCAL_TBL (0x9F94)
|
||||
#define RTL930X_TRK_STK_CTRL (0xA07C)
|
||||
|
||||
#define RTL930X_TRK_ID_CTRL_TRK_VALID BIT(6)
|
||||
#define RTL930X_TRK_ID_CTRL_TRK_ID GENMASK(5, 0)
|
||||
|
||||
#define RTL930X_LOCAL_PORT_TRK_MAP_IS_TRK_MBR BIT(6)
|
||||
#define RTL930X_LOCAL_PORT_TRK_MAP_TRK_ID GENMASK(5, 0)
|
||||
|
||||
#define RTL930X_SRC_TRK_MAP_TRK_VALID BIT(31)
|
||||
#define RTL930X_SRC_TRK_MAP_TRK_ID GENMASK(30, 25)
|
||||
|
||||
#define RTL931X_LOCAL_PORT_TRK_MAP (0x4CAC)
|
||||
#define RTL931X_TRK_ID_CTRL (0xB800)
|
||||
#define RTL931X_TRK_MBR_CTRL (0xB8D0)
|
||||
#define RTL931X_TRK_HASH_CTRL (0xBA70)
|
||||
#define RTL931X_TRK_CTRL (0xBA78)
|
||||
#define RTL931X_TRK_SHIFT_CTRL (0xBA7C)
|
||||
#define RTL931X_TRK_LOCAL_TBL_REFRESH (0xBA80)
|
||||
#define RTL931X_TRK_LOCAL_TBL (0xBA84)
|
||||
#define RTL931X_TRK_STK_CTRL (0xBE94)
|
||||
|
||||
#define RLT931X_TRK_ID_CTRL_TRK_ID GENMASK(6, 0)
|
||||
#define RTL931X_TRK_ID_CTRL_TRK_VALID BIT(7)
|
||||
|
||||
#define RTL931X_LOCAL_PORT_TRK_MAP_IS_TRK_MBR BIT(7)
|
||||
#define RTL931X_LOCAL_PORT_TRK_MAP_TRK_ID GENMASK(6, 0)
|
||||
|
||||
#define RTL931X_SRC_TRK_MAP_TRK_ID GENMASK(30, 24)
|
||||
#define RTL931X_SRC_TRK_MAP_TRK_ID_VALID BIT(31)
|
||||
|
||||
#define GENMASK_MOD(high, low) GENMASK((high) % 32, (low) % 32)
|
||||
#define BIT_MOD(bit) BIT((bit) % 32)
|
||||
|
||||
/* RTL930X LAG Table offsets */
|
||||
#define RTL930X_LAG_NUM_TX_CANDI GENMASK_MOD(92, 89)
|
||||
#define RTL930X_LAG_L2_HASH_MSK_IDX BIT_MOD(88)
|
||||
#define RTL930X_LAG_IP4_HASH_MSK_IDX BIT_MOD(87)
|
||||
#define RTL930X_LAG_IP6_HASH_MSK_IDX BIT_MOD(86)
|
||||
#define RTL930X_LAG_SEP_DLF_BCAST_EN BIT_MOD(85)
|
||||
#define RTL930X_LAG_SEP_KWN_MC_EN BIT_MOD(84)
|
||||
#define RTL930X_LAG_TRK_DEV7 GENMASK_MOD(83, 80)
|
||||
#define RTL930X_LAG_TRK_PORT7 GENMASK_MOD(79, 74)
|
||||
#define RTL930X_LAG_TRK_DEV6 GENMASK_MOD(73, 70)
|
||||
#define RTL930X_LAG_TRK_PORT6 GENMASK_MOD(69, 64)
|
||||
|
||||
#define RTL930X_LAG_TRK_DEV5 GENMASK_MOD(61, 58)
|
||||
#define RTL930X_LAG_TRK_PORT5 GENMASK_MOD(57, 52)
|
||||
#define RTL930X_LAG_TRK_DEV4 GENMASK_MOD(51, 48)
|
||||
#define RTL930X_LAG_TRK_PORT4 GENMASK_MOD(47, 42)
|
||||
#define RTL930X_LAG_TRK_DEV3 GENMASK_MOD(41, 38)
|
||||
#define RTL930X_LAG_TRK_PORT3 GENMASK_MOD(37, 32)
|
||||
|
||||
#define RTL930X_LAG_TRK_DEV2 GENMASK_MOD(29, 26)
|
||||
#define RTL930X_LAG_TRK_PORT2 GENMASK_MOD(25, 20)
|
||||
#define RTL930X_LAG_TRK_DEV1 GENMASK_MOD(19, 16)
|
||||
#define RTL930X_LAG_TRK_PORT1 GENMASK_MOD(15, 10)
|
||||
#define RTL930X_LAG_TRK_DEV0 GENMASK_MOD(9, 6)
|
||||
#define RTL930X_LAG_TRK_PORT0 GENMASK_MOD(5, 0)
|
||||
|
||||
/* RTL931X LAG Table offsets */
|
||||
#define RTL931X_LAG_NUM_TX_CANDI GENMASK_MOD(92, 89)
|
||||
#define RTL931X_LAG_L2_HASH_MSK_IDX BIT_MOD(88)
|
||||
#define RTL931X_LAG_IP4_HASH_MSK_IDX BIT_MOD(87)
|
||||
#define RTL931X_LAG_IP6_HASH_MSK_IDX BIT_MOD(86)
|
||||
#define RTL931X_LAG_SEP_FLOOD_EN BIT_MOD(85)
|
||||
#define RTL931X_LAG_SEP_KWN_MC_EN BIT_MOD(84)
|
||||
#define RTL931X_LAG_TRK_DEV7 GENMASK_MOD(83, 80)
|
||||
#define RTL931X_LAG_TRK_PORT7 GENMASK_MOD(79, 74)
|
||||
#define RTL931X_LAG_TRK_DEV6 GENMASK_MOD(73, 70)
|
||||
#define RTL931X_LAG_TRK_PORT6 GENMASK_MOD(69, 64)
|
||||
|
||||
#define RTL931X_LAG_TRK_DEV5 GENMASK_MOD(61, 58)
|
||||
#define RTL931X_LAG_TRK_PORT5 GENMASK_MOD(57, 52)
|
||||
#define RTL931X_LAG_TRK_DEV4 GENMASK_MOD(51, 48)
|
||||
#define RTL931X_LAG_TRK_PORT4 GENMASK_MOD(47, 42)
|
||||
#define RTL931X_LAG_TRK_DEV3 GENMASK_MOD(41, 38)
|
||||
#define RTL931X_LAG_TRK_PORT3 GENMASK_MOD(37, 32)
|
||||
|
||||
#define RTL931X_LAG_TRK_DEV2 GENMASK_MOD(29, 26)
|
||||
#define RTL931X_LAG_TRK_PORT2 GENMASK_MOD(25, 20)
|
||||
#define RTL931X_LAG_TRK_DEV1 GENMASK_MOD(19, 16)
|
||||
#define RTL931X_LAG_TRK_PORT1 GENMASK_MOD(15, 10)
|
||||
#define RTL931X_LAG_TRK_DEV0 GENMASK_MOD(9, 6)
|
||||
#define RTL931X_LAG_TRK_PORT0 GENMASK_MOD(5, 0)
|
||||
|
||||
/* Attack prevention */
|
||||
#define RTL838X_ATK_PRVNT_PORT_EN (0x5B00)
|
||||
@@ -511,6 +598,16 @@
|
||||
#define RTL838X_LED_SW_P_CTRL (0xA01C)
|
||||
#define RTL838X_LED_SW_P_CTRL_PORT(p) (RTL838X_LED_SW_P_CTRL + (((p) << 2)))
|
||||
|
||||
#define RTL93XX_HASH_MASK_INDEX_L2 (0)
|
||||
#define RTL93XX_HASH_MASK_INDEX_L23 (1)
|
||||
|
||||
#define RTL93XX_TRK_CTRL_NON_TMN_TUNNEL_HASH_SEL BIT(0)
|
||||
#define RTL93XX_TRK_CTRL_SEP_PORT_SEL BIT(1)
|
||||
#define RTL93XX_TRK_CTRL_TRK_STAND_ALONE_MODE BIT(2)
|
||||
#define RTL93XX_TRK_CTRL_STK_HASH_CAL BIT(3)
|
||||
#define RTL93XX_TRK_CTRL_LOCAL_FIRST BIT(4)
|
||||
#define RTL93XX_TRK_CTRL_CONGST_AVOID BIT(5)
|
||||
#define RTL93XX_TRK_CTRL_LINK_DOWN_AVOID BIT(6)
|
||||
|
||||
/* special port action controls */
|
||||
/* values:
|
||||
@@ -874,11 +971,39 @@ struct rtldsa_counter_state {
|
||||
struct rtnl_link_stats64 link_stat;
|
||||
};
|
||||
|
||||
struct rtl838x_port {
|
||||
struct rtldsa_93xx_lag_entry {
|
||||
u32 trk_port0:6;
|
||||
u32 trk_dev0:4;
|
||||
u32 trk_port1:6;
|
||||
u32 trk_dev1:4;
|
||||
u32 trk_port2:6;
|
||||
u32 trk_dev2:4;
|
||||
u32 trk_port3:6;
|
||||
u32 trk_dev3:4;
|
||||
u32 trk_port4:6;
|
||||
u32 trk_dev4:4;
|
||||
u32 trk_port5:6;
|
||||
u32 trk_dev5:4;
|
||||
u32 trk_port6:6;
|
||||
u32 trk_dev6:4;
|
||||
u32 trk_port7:6;
|
||||
u32 trk_dev7:4;
|
||||
u32 sep_kwn_mc_en:1;
|
||||
union {
|
||||
// for rtl930x
|
||||
u32 sep_dlf_bcast_en:1;
|
||||
// for rtl931x
|
||||
u32 sep_flood_en:1;
|
||||
} flood_dlf_bcast;
|
||||
u32 ip6_hash_mask_idx:1;
|
||||
u32 ip4_hash_mask_idx:1;
|
||||
u32 l2_hash_mask_idx:1;
|
||||
u32 num_tx_candi:4;
|
||||
};
|
||||
|
||||
struct rtldsa_port {
|
||||
bool enable:1;
|
||||
bool phy_is_integrated:1;
|
||||
bool is10G:1;
|
||||
bool is2G5:1;
|
||||
bool isolated:1;
|
||||
bool rate_police_egress:1;
|
||||
bool rate_police_ingress:1;
|
||||
@@ -886,6 +1011,7 @@ struct rtl838x_port {
|
||||
u16 pvid;
|
||||
bool eee_enabled;
|
||||
enum phy_type phy;
|
||||
struct phylink_pcs *pcs;
|
||||
int led_set;
|
||||
int leds_on_this_port;
|
||||
struct rtldsa_counter_state counters;
|
||||
@@ -1297,6 +1423,8 @@ struct rtldsa_config {
|
||||
int n_counters;
|
||||
int n_pie_blocks;
|
||||
u8 port_ignore;
|
||||
int trk_ctrl;
|
||||
int trk_hash_ctrl;
|
||||
void (*vlan_tables_read)(u32 vlan, struct rtl838x_vlan_info *info);
|
||||
void (*vlan_set_tagged)(u32 vlan, struct rtl838x_vlan_info *info);
|
||||
void (*vlan_set_untagged)(u32 vlan, u64 portmask);
|
||||
@@ -1331,7 +1459,6 @@ struct rtldsa_config {
|
||||
void (*write_l2_entry_using_hash)(u32 hash, u32 pos, struct rtl838x_l2_entry *e);
|
||||
u64 (*read_cam)(int idx, struct rtl838x_l2_entry *e);
|
||||
void (*write_cam)(int idx, struct rtl838x_l2_entry *e);
|
||||
int (*trk_mbr_ctr)(int group);
|
||||
int rma_bpdu_fld_pmask;
|
||||
int spcl_trap_eapol_ctrl;
|
||||
void (*init_eee)(struct rtl838x_switch_priv *priv, bool enable);
|
||||
@@ -1362,10 +1489,26 @@ struct rtldsa_config {
|
||||
void (*get_l3_router_mac)(u32 idx, struct rtl93xx_rt_mac *m);
|
||||
void (*set_l3_router_mac)(u32 idx, struct rtl93xx_rt_mac *m);
|
||||
void (*set_l3_egress_intf)(int idx, struct rtl838x_l3_intf *intf);
|
||||
void (*set_distribution_algorithm)(int group, int algoidx, u32 algomask);
|
||||
void (*set_receive_management_action)(int port, rma_ctrl_t type, action_type_t action);
|
||||
void (*led_init)(struct rtl838x_switch_priv *priv);
|
||||
void (*qos_init)(struct rtl838x_switch_priv *priv);
|
||||
int (*trk_mbr_ctr)(int group);
|
||||
void (*lag_switch_init)(struct rtl838x_switch_priv *priv);
|
||||
void (*prepare_lag_fdb)(struct rtl838x_l2_entry *e, int lag_group);
|
||||
int (*lag_set_port_members)(struct rtl838x_switch_priv *priv, int group, u64 members,
|
||||
struct netdev_lag_upper_info *info);
|
||||
int (*lag_setup_algomask)(struct rtl838x_switch_priv *priv, int group,
|
||||
struct netdev_lag_upper_info *info);
|
||||
int (*lag_set_distribution_algorithm)(struct rtl838x_switch_priv *priv,
|
||||
int group, int algoidx,
|
||||
u32 algomask);
|
||||
void (*lag_set_local_group_id)(int local_group, int global_group, bool valid);
|
||||
void (*lag_write_data)(u32 data[], struct rtldsa_93xx_lag_entry *e);
|
||||
void (*lag_fill_data)(u32 data[], struct rtldsa_93xx_lag_entry *e);
|
||||
void (*lag_set_local_port2group)(int group, int port, bool valid);
|
||||
void (*lag_set_port2group)(int group, int port, bool valid);
|
||||
struct table_reg* (*lag_table)(void);
|
||||
void (*lag_sync_tables)(void);
|
||||
};
|
||||
|
||||
struct rtl838x_switch_priv {
|
||||
@@ -1374,8 +1517,7 @@ struct rtl838x_switch_priv {
|
||||
struct device *dev;
|
||||
u16 id;
|
||||
u16 family_id;
|
||||
struct rtl838x_port ports[57];
|
||||
struct phylink_pcs *pcs[57];
|
||||
struct rtldsa_port ports[57];
|
||||
struct mutex reg_mutex; /* Mutex for individual register manipulations */
|
||||
struct mutex pie_mutex; /* Mutex for Packet Inspection Engine */
|
||||
int link_state_irq;
|
||||
@@ -1440,6 +1582,13 @@ struct rtl838x_switch_priv {
|
||||
|
||||
void rtl838x_dbgfs_init(struct rtl838x_switch_priv *priv);
|
||||
void rtl930x_dbgfs_init(struct rtl838x_switch_priv *priv);
|
||||
void rtldsa_93xx_lag_switch_init(struct rtl838x_switch_priv *priv);
|
||||
int rtldsa_93xx_lag_set_distribution_algorithm(struct rtl838x_switch_priv *priv,
|
||||
int group, int algoidx, u32 algomsk);
|
||||
int rtldsa_93xx_lag_set_port_members(struct rtl838x_switch_priv *priv, int group,
|
||||
u64 members, struct netdev_lag_upper_info *info);
|
||||
|
||||
void rtldsa_93xx_prepare_lag_fdb(struct rtl838x_l2_entry *e, int lag_group);
|
||||
|
||||
void rtldsa_counters_lock_register(struct rtl838x_switch_priv *priv, int port)
|
||||
__acquires(&priv->ports[port].counters.lock);
|
||||
|
||||
@@ -1701,11 +1701,14 @@ static void rtl839x_set_egr_filter(int port, enum egr_filter state)
|
||||
RTL839X_VLAN_PORT_EGR_FLTR + (((port >> 5) << 2)));
|
||||
}
|
||||
|
||||
static void rtl839x_set_distribution_algorithm(int group, int algoidx, u32 algomsk)
|
||||
static int rtldsa_839x_set_distribution_algorithm(struct rtl838x_switch_priv *priv,
|
||||
int group, int algoidx, u32 algomsk)
|
||||
{
|
||||
sw_w32_mask(3 << ((group & 0xf) << 1), algoidx << ((group & 0xf) << 1),
|
||||
RTL839X_TRK_HASH_IDX_CTRL + ((group >> 4) << 2));
|
||||
sw_w32(algomsk, RTL839X_TRK_HASH_CTRL + (algoidx << 2));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtl839x_set_receive_management_action(int port, rma_ctrl_t type, action_type_t action)
|
||||
@@ -1728,6 +1731,20 @@ static void rtl839x_set_receive_management_action(int port, rma_ctrl_t type, act
|
||||
}
|
||||
}
|
||||
|
||||
static int rtldsa_839x_lag_set_port_members(struct rtl838x_switch_priv *priv, int group,
|
||||
u64 members, struct netdev_lag_upper_info *info)
|
||||
{
|
||||
priv->lags_port_members[group] = members;
|
||||
|
||||
priv->r->set_port_reg_be(priv->lags_port_members[group],
|
||||
priv->r->trk_mbr_ctr(group));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtldsa_83xx_lag_setup_algomask(struct rtl838x_switch_priv *priv, int group,
|
||||
struct netdev_lag_upper_info *info);
|
||||
|
||||
const struct rtldsa_config rtldsa_839x_cfg = {
|
||||
.mask_port_reg_be = rtl839x_mask_port_reg_be,
|
||||
.set_port_reg_be = rtl839x_set_port_reg_be,
|
||||
@@ -1813,7 +1830,9 @@ const struct rtldsa_config rtldsa_839x_cfg = {
|
||||
.route_read = rtl839x_route_read,
|
||||
.route_write = rtl839x_route_write,
|
||||
.l3_setup = rtl839x_l3_setup,
|
||||
.set_distribution_algorithm = rtl839x_set_distribution_algorithm,
|
||||
.set_receive_management_action = rtl839x_set_receive_management_action,
|
||||
.qos_init = rtldsa_839x_qos_init,
|
||||
.lag_set_distribution_algorithm = rtldsa_839x_set_distribution_algorithm,
|
||||
.lag_set_port_members = rtldsa_839x_lag_set_port_members,
|
||||
.lag_setup_algomask = rtldsa_83xx_lag_setup_algomask,
|
||||
};
|
||||
|
||||
@@ -127,6 +127,9 @@ inline u16 rtl_table_data(struct table_reg *r, int i);
|
||||
inline u32 rtl_table_data_r(struct table_reg *r, int i);
|
||||
inline void rtl_table_data_w(struct table_reg *r, u32 v, int i);
|
||||
|
||||
int rtldsa_83xx_lag_setup_algomask(struct rtl838x_switch_priv *priv, int group,
|
||||
struct netdev_lag_upper_info *info);
|
||||
|
||||
void rtldsa_838x_qos_init(struct rtl838x_switch_priv *priv);
|
||||
void rtldsa_839x_qos_init(struct rtl838x_switch_priv *priv);
|
||||
|
||||
|
||||
@@ -532,6 +532,118 @@ static void rtldsa_930x_enable_flood(int port, bool enable)
|
||||
RTL930X_L2_LRN_PORT_CONSTRT_CTRL + port * 4);
|
||||
}
|
||||
|
||||
static void rtldsa_930x_lag_set_port2group(int group, int port, bool valid)
|
||||
{
|
||||
struct table_reg *r = rtl_table_get(RTL9300_TBL_0, 8);
|
||||
u32 mask = valid ? RTL930X_SRC_TRK_MAP_TRK_VALID : 0;
|
||||
|
||||
rtl_table_read(r, port);
|
||||
mask |= FIELD_PREP(RTL930X_SRC_TRK_MAP_TRK_ID, group); // Update TRK Field.
|
||||
sw_w32(mask, rtl_table_data(r, 0));
|
||||
rtl_table_write(r, port);
|
||||
rtl_table_release(r);
|
||||
}
|
||||
|
||||
/* Write data from the data buffer into the lag-entry strucure */
|
||||
static void rtldsa_930x_lag_fill_data(u32 data[], struct rtldsa_93xx_lag_entry *e)
|
||||
{
|
||||
/* 95-64 */
|
||||
e->num_tx_candi = FIELD_GET(RTL930X_LAG_NUM_TX_CANDI, data[0]);
|
||||
e->l2_hash_mask_idx = FIELD_GET(RTL930X_LAG_L2_HASH_MSK_IDX, data[0]);
|
||||
e->ip4_hash_mask_idx = FIELD_GET(RTL930X_LAG_IP4_HASH_MSK_IDX, data[0]);
|
||||
e->ip6_hash_mask_idx = FIELD_GET(RTL930X_LAG_IP6_HASH_MSK_IDX, data[0]);
|
||||
e->flood_dlf_bcast.sep_dlf_bcast_en = FIELD_GET(RTL930X_LAG_SEP_DLF_BCAST_EN, data[0]);
|
||||
e->sep_kwn_mc_en = FIELD_GET(RTL930X_LAG_SEP_KWN_MC_EN, data[0]);
|
||||
e->trk_dev7 = FIELD_GET(RTL930X_LAG_TRK_DEV7, data[0]);
|
||||
e->trk_port7 = FIELD_GET(RTL930X_LAG_TRK_PORT7, data[0]);
|
||||
e->trk_dev6 = FIELD_GET(RTL930X_LAG_TRK_DEV6, data[0]);
|
||||
e->trk_port6 = FIELD_GET(RTL930X_LAG_TRK_PORT6, data[0]);
|
||||
|
||||
/* 63-32 */
|
||||
e->trk_dev5 = FIELD_GET(RTL930X_LAG_TRK_DEV5, data[1]);
|
||||
e->trk_port5 = FIELD_GET(RTL930X_LAG_TRK_PORT5, data[1]);
|
||||
e->trk_dev4 = FIELD_GET(RTL930X_LAG_TRK_DEV4, data[1]);
|
||||
e->trk_port4 = FIELD_GET(RTL930X_LAG_TRK_PORT4, data[1]);
|
||||
e->trk_dev3 = FIELD_GET(RTL930X_LAG_TRK_DEV3, data[1]);
|
||||
e->trk_port3 = FIELD_GET(RTL930X_LAG_TRK_PORT3, data[1]);
|
||||
|
||||
/* 31-0 */
|
||||
e->trk_dev2 = FIELD_GET(RTL930X_LAG_TRK_DEV2, data[2]);
|
||||
e->trk_port2 = FIELD_GET(RTL930X_LAG_TRK_PORT2, data[2]);
|
||||
e->trk_dev1 = FIELD_GET(RTL930X_LAG_TRK_DEV1, data[2]);
|
||||
e->trk_port1 = FIELD_GET(RTL930X_LAG_TRK_PORT1, data[2]);
|
||||
e->trk_dev0 = FIELD_GET(RTL930X_LAG_TRK_DEV0, data[2]);
|
||||
e->trk_port0 = FIELD_GET(RTL930X_LAG_TRK_PORT0, data[2]);
|
||||
}
|
||||
|
||||
/* Write lag-entry data into buffer */
|
||||
static void rtldsa_930x_lag_write_data(u32 data[], struct rtldsa_93xx_lag_entry *e)
|
||||
{
|
||||
/* 95-64 */
|
||||
data[0] = FIELD_PREP(RTL930X_LAG_NUM_TX_CANDI, e->num_tx_candi);
|
||||
data[0] |= FIELD_PREP(RTL930X_LAG_L2_HASH_MSK_IDX, e->l2_hash_mask_idx);
|
||||
data[0] |= FIELD_PREP(RTL930X_LAG_IP4_HASH_MSK_IDX, e->ip4_hash_mask_idx);
|
||||
data[0] |= FIELD_PREP(RTL930X_LAG_IP6_HASH_MSK_IDX, e->ip6_hash_mask_idx);
|
||||
data[0] |= FIELD_PREP(RTL930X_LAG_SEP_DLF_BCAST_EN, e->flood_dlf_bcast.sep_dlf_bcast_en);
|
||||
data[0] |= FIELD_PREP(RTL930X_LAG_SEP_KWN_MC_EN, e->sep_kwn_mc_en);
|
||||
data[0] |= FIELD_PREP(RTL930X_LAG_TRK_DEV7, e->trk_dev7);
|
||||
data[0] |= FIELD_PREP(RTL930X_LAG_TRK_PORT7, e->trk_port7);
|
||||
data[0] |= FIELD_PREP(RTL930X_LAG_TRK_DEV6, e->trk_dev6);
|
||||
data[0] |= FIELD_PREP(RTL930X_LAG_TRK_PORT6, e->trk_port6);
|
||||
|
||||
/* 63-32 */
|
||||
data[1] = FIELD_PREP(RTL930X_LAG_TRK_DEV5, e->trk_dev5);
|
||||
data[1] |= FIELD_PREP(RTL930X_LAG_TRK_PORT5, e->trk_port5);
|
||||
data[1] |= FIELD_PREP(RTL930X_LAG_TRK_DEV4, e->trk_dev4);
|
||||
data[1] |= FIELD_PREP(RTL930X_LAG_TRK_PORT4, e->trk_port4);
|
||||
data[1] |= FIELD_PREP(RTL930X_LAG_TRK_DEV3, e->trk_dev3);
|
||||
data[1] |= FIELD_PREP(RTL930X_LAG_TRK_PORT3, e->trk_port3);
|
||||
|
||||
/* 31-0 */
|
||||
data[2] = FIELD_PREP(RTL930X_LAG_TRK_DEV2, e->trk_dev2);
|
||||
data[2] |= FIELD_PREP(RTL930X_LAG_TRK_PORT2, e->trk_port2);
|
||||
data[2] |= FIELD_PREP(RTL930X_LAG_TRK_DEV1, e->trk_dev1);
|
||||
data[2] |= FIELD_PREP(RTL930X_LAG_TRK_PORT1, e->trk_port1);
|
||||
data[2] |= FIELD_PREP(RTL930X_LAG_TRK_DEV0, e->trk_dev0);
|
||||
data[2] |= FIELD_PREP(RTL930X_LAG_TRK_PORT0, e->trk_port0);
|
||||
}
|
||||
|
||||
static void rtldsa_930x_lag_set_local_group_id(int local_group, int global_group, bool valid)
|
||||
{
|
||||
u32 mask = 0;
|
||||
|
||||
mask |= valid ? RTL930X_TRK_ID_CTRL_TRK_VALID : 0;
|
||||
mask |= FIELD_PREP(RTL930X_TRK_ID_CTRL_TRK_ID, global_group);
|
||||
sw_w32(mask, RTL930X_TRK_ID_CTRL + (4 * local_group));
|
||||
}
|
||||
|
||||
static void rtldsa_930x_lag_set_local_port2group(int group, int port, bool valid)
|
||||
{
|
||||
u32 mask = 0;
|
||||
|
||||
mask |= valid ? RTL930X_LOCAL_PORT_TRK_MAP_IS_TRK_MBR : 0;
|
||||
mask |= FIELD_PREP(RTL930X_LOCAL_PORT_TRK_MAP_TRK_ID, group);
|
||||
sw_w32(mask, RTL930X_LOCAL_PORT_TRK_MAP + (4 * port));
|
||||
}
|
||||
|
||||
static void rtldsa_930x_lag_sync_tables(void)
|
||||
{
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
sw_w32(BIT(0), RTL930X_TRK_LOCAL_TBL_REFRESH);
|
||||
|
||||
ret = readx_poll_timeout(sw_r32, RTL930X_TRK_LOCAL_TBL_REFRESH, val,
|
||||
!(val & BIT(0)), 20, 10000);
|
||||
if (ret)
|
||||
pr_err("%s: timeout\n", __func__);
|
||||
}
|
||||
|
||||
static struct table_reg *rtldsa_930x_lag_table(void)
|
||||
{
|
||||
return rtl_table_get(RTL9300_TBL_0, 7);
|
||||
}
|
||||
|
||||
static int rtldsa_930x_stp_get(struct rtl838x_switch_priv *priv, u16 msti, int port, u32 port_state[])
|
||||
{
|
||||
int idx = 1 - ((port + 3) / 16);
|
||||
@@ -2513,46 +2625,6 @@ static void rtl930x_set_egr_filter(int port, enum egr_filter state)
|
||||
RTL930X_VLAN_PORT_EGR_FLTR + (((port / 29) << 2)));
|
||||
}
|
||||
|
||||
static void rtl930x_set_distribution_algorithm(int group, int algoidx, u32 algomsk)
|
||||
{
|
||||
u32 l3shift = 0;
|
||||
u32 newmask = 0;
|
||||
|
||||
/* TODO: for now we set algoidx to 0 */
|
||||
algoidx = 0;
|
||||
if (algomsk & TRUNK_DISTRIBUTION_ALGO_SIP_BIT) {
|
||||
l3shift = 4;
|
||||
newmask |= TRUNK_DISTRIBUTION_ALGO_L3_SIP_BIT;
|
||||
}
|
||||
if (algomsk & TRUNK_DISTRIBUTION_ALGO_DIP_BIT) {
|
||||
l3shift = 4;
|
||||
newmask |= TRUNK_DISTRIBUTION_ALGO_L3_DIP_BIT;
|
||||
}
|
||||
if (algomsk & TRUNK_DISTRIBUTION_ALGO_SRC_L4PORT_BIT) {
|
||||
l3shift = 4;
|
||||
newmask |= TRUNK_DISTRIBUTION_ALGO_L3_SRC_L4PORT_BIT;
|
||||
}
|
||||
if (algomsk & TRUNK_DISTRIBUTION_ALGO_SRC_L4PORT_BIT) {
|
||||
l3shift = 4;
|
||||
newmask |= TRUNK_DISTRIBUTION_ALGO_L3_SRC_L4PORT_BIT;
|
||||
}
|
||||
|
||||
if (l3shift == 4) {
|
||||
if (algomsk & TRUNK_DISTRIBUTION_ALGO_SMAC_BIT)
|
||||
newmask |= TRUNK_DISTRIBUTION_ALGO_L3_SMAC_BIT;
|
||||
|
||||
if (algomsk & TRUNK_DISTRIBUTION_ALGO_DMAC_BIT)
|
||||
newmask |= TRUNK_DISTRIBUTION_ALGO_L3_DMAC_BIT;
|
||||
} else {
|
||||
if (algomsk & TRUNK_DISTRIBUTION_ALGO_SMAC_BIT)
|
||||
newmask |= TRUNK_DISTRIBUTION_ALGO_L2_SMAC_BIT;
|
||||
if (algomsk & TRUNK_DISTRIBUTION_ALGO_DMAC_BIT)
|
||||
newmask |= TRUNK_DISTRIBUTION_ALGO_L2_DMAC_BIT;
|
||||
}
|
||||
|
||||
sw_w32(newmask << l3shift, RTL930X_TRK_HASH_CTRL + (algoidx << 2));
|
||||
}
|
||||
|
||||
static void rtldsa_930x_led_get_forced(const struct device_node *node,
|
||||
const u8 leds_in_set[4],
|
||||
u8 forced_leds_per_port[RTL930X_CPU_PORT])
|
||||
@@ -2637,7 +2709,7 @@ static void rtl930x_led_init(struct rtl838x_switch_priv *priv)
|
||||
sw_w32_mask(0x3 << pos, 0, RTL930X_LED_PORT_FIB_SET_SEL_CTRL(i));
|
||||
sw_w32_mask(0x3 << pos, 0, RTL930X_LED_PORT_COPR_SET_SEL_CTRL(i));
|
||||
|
||||
if (!priv->ports[i].phy && !priv->pcs[i] && !(forced_leds_per_port[i]))
|
||||
if (!priv->ports[i].phy && !priv->ports[i].pcs && !(forced_leds_per_port[i]))
|
||||
continue;
|
||||
|
||||
if (forced_leds_per_port[i] > 0)
|
||||
@@ -2835,10 +2907,22 @@ const struct rtldsa_config rtldsa_930x_cfg = {
|
||||
.set_l3_router_mac = rtl930x_set_l3_router_mac,
|
||||
.set_l3_egress_intf = rtl930x_set_l3_egress_intf,
|
||||
#endif
|
||||
.set_distribution_algorithm = rtl930x_set_distribution_algorithm,
|
||||
.led_init = rtl930x_led_init,
|
||||
.enable_learning = rtldsa_930x_enable_learning,
|
||||
.enable_flood = rtldsa_930x_enable_flood,
|
||||
.set_receive_management_action = rtldsa_930x_set_receive_management_action,
|
||||
.qos_init = rtldsa_930x_qos_init,
|
||||
.trk_ctrl = RTL930X_TRK_CTRL,
|
||||
.trk_hash_ctrl = RTL930X_TRK_HASH_CTRL,
|
||||
.prepare_lag_fdb = rtldsa_93xx_prepare_lag_fdb,
|
||||
.lag_switch_init = rtldsa_93xx_lag_switch_init,
|
||||
.lag_set_port_members = rtldsa_93xx_lag_set_port_members,
|
||||
.lag_set_distribution_algorithm = rtldsa_93xx_lag_set_distribution_algorithm,
|
||||
.lag_set_local_group_id = rtldsa_930x_lag_set_local_group_id,
|
||||
.lag_write_data = rtldsa_930x_lag_write_data,
|
||||
.lag_fill_data = rtldsa_930x_lag_fill_data,
|
||||
.lag_set_local_port2group = rtldsa_930x_lag_set_local_port2group,
|
||||
.lag_set_port2group = rtldsa_930x_lag_set_port2group,
|
||||
.lag_sync_tables = rtldsa_930x_lag_sync_tables,
|
||||
.lag_table = rtldsa_930x_lag_table,
|
||||
};
|
||||
|
||||
@@ -1624,46 +1624,6 @@ static void rtl931x_set_egr_filter(int port, enum egr_filter state)
|
||||
RTL931X_VLAN_PORT_EGR_FLTR + (((port >> 5) << 2)));
|
||||
}
|
||||
|
||||
static void rtl931x_set_distribution_algorithm(int group, int algoidx, u32 algomsk)
|
||||
{
|
||||
u32 l3shift = 0;
|
||||
u32 newmask = 0;
|
||||
|
||||
/* TODO: for now we set algoidx to 0 */
|
||||
algoidx = 0;
|
||||
|
||||
if (algomsk & TRUNK_DISTRIBUTION_ALGO_SIP_BIT) {
|
||||
l3shift = 4;
|
||||
newmask |= TRUNK_DISTRIBUTION_ALGO_L3_SIP_BIT;
|
||||
}
|
||||
if (algomsk & TRUNK_DISTRIBUTION_ALGO_DIP_BIT) {
|
||||
l3shift = 4;
|
||||
newmask |= TRUNK_DISTRIBUTION_ALGO_L3_DIP_BIT;
|
||||
}
|
||||
if (algomsk & TRUNK_DISTRIBUTION_ALGO_SRC_L4PORT_BIT) {
|
||||
l3shift = 4;
|
||||
newmask |= TRUNK_DISTRIBUTION_ALGO_L3_SRC_L4PORT_BIT;
|
||||
}
|
||||
if (algomsk & TRUNK_DISTRIBUTION_ALGO_SRC_L4PORT_BIT) {
|
||||
l3shift = 4;
|
||||
newmask |= TRUNK_DISTRIBUTION_ALGO_L3_SRC_L4PORT_BIT;
|
||||
}
|
||||
|
||||
if (l3shift == 4) {
|
||||
if (algomsk & TRUNK_DISTRIBUTION_ALGO_SMAC_BIT)
|
||||
newmask |= TRUNK_DISTRIBUTION_ALGO_L3_SMAC_BIT;
|
||||
if (algomsk & TRUNK_DISTRIBUTION_ALGO_DMAC_BIT)
|
||||
newmask |= TRUNK_DISTRIBUTION_ALGO_L3_DMAC_BIT;
|
||||
} else {
|
||||
if (algomsk & TRUNK_DISTRIBUTION_ALGO_SMAC_BIT)
|
||||
newmask |= TRUNK_DISTRIBUTION_ALGO_L2_SMAC_BIT;
|
||||
if (algomsk & TRUNK_DISTRIBUTION_ALGO_DMAC_BIT)
|
||||
newmask |= TRUNK_DISTRIBUTION_ALGO_L2_DMAC_BIT;
|
||||
}
|
||||
|
||||
sw_w32(newmask << l3shift, RTL931X_TRK_HASH_CTRL + (algoidx << 2));
|
||||
}
|
||||
|
||||
static void rtldsa_931x_led_get_forced(const struct device_node *node,
|
||||
const u8 leds_in_set[4],
|
||||
u8 forced_leds_per_port[RTL931X_CPU_PORT])
|
||||
@@ -1749,7 +1709,7 @@ static void rtldsa_931x_led_init(struct rtl838x_switch_priv *priv)
|
||||
sw_w32_mask(0x3 << pos, 0, RTL931X_LED_PORT_COPR_SET_SEL_CTRL(i));
|
||||
|
||||
/* Skip port if not present (auto-detect) or not in forced mask */
|
||||
if (!priv->ports[i].phy && !priv->pcs[i] && !(forced_leds_per_port[i]))
|
||||
if (!priv->ports[i].phy && !priv->ports[i].pcs && !(forced_leds_per_port[i]))
|
||||
continue;
|
||||
|
||||
if (forced_leds_per_port[i] > 0)
|
||||
@@ -1785,6 +1745,123 @@ static void rtldsa_931x_led_init(struct rtl838x_switch_priv *priv)
|
||||
dev_dbg(dev, "%08x: %08x\n", 0xbb000600 + i * 4, sw_r32(0x0600 + i * 4));
|
||||
}
|
||||
|
||||
static void rtldsa_931x_lag_set_port2group(int group, int port, bool valid)
|
||||
{
|
||||
u32 trk_id_valid = valid ? RTL931X_SRC_TRK_MAP_TRK_ID_VALID : 0;
|
||||
struct table_reg *r = rtl_table_get(RTL9310_TBL_0, 13);
|
||||
u32 mask = 0;
|
||||
|
||||
rtl_table_read(r, port);
|
||||
|
||||
mask |= trk_id_valid;
|
||||
/* Update TRK Field */
|
||||
mask |= FIELD_PREP(RTL931X_SRC_TRK_MAP_TRK_ID, group);
|
||||
|
||||
sw_w32(mask, rtl_table_data(r, 0));
|
||||
rtl_table_write(r, port);
|
||||
rtl_table_release(r);
|
||||
}
|
||||
|
||||
/* Write data from the data buffer into the lag-entry strucure */
|
||||
static void rtldsa_931x_lag_fill_data(u32 data[], struct rtldsa_93xx_lag_entry *e)
|
||||
{
|
||||
/* 95-64 */
|
||||
e->num_tx_candi = FIELD_GET(RTL931X_LAG_NUM_TX_CANDI, data[0]);
|
||||
e->l2_hash_mask_idx = FIELD_GET(RTL931X_LAG_L2_HASH_MSK_IDX, data[0]);
|
||||
e->ip4_hash_mask_idx = FIELD_GET(RTL931X_LAG_IP4_HASH_MSK_IDX, data[0]);
|
||||
e->ip6_hash_mask_idx = FIELD_GET(RTL931X_LAG_IP6_HASH_MSK_IDX, data[0]);
|
||||
e->flood_dlf_bcast.sep_flood_en = FIELD_GET(RTL931X_LAG_SEP_FLOOD_EN, data[0]);
|
||||
e->sep_kwn_mc_en = FIELD_GET(RTL931X_LAG_SEP_KWN_MC_EN, data[0]);
|
||||
e->trk_dev7 = FIELD_GET(RTL931X_LAG_TRK_DEV7, data[0]);
|
||||
e->trk_port7 = FIELD_GET(RTL931X_LAG_TRK_PORT7, data[0]);
|
||||
e->trk_dev6 = FIELD_GET(RTL931X_LAG_TRK_DEV6, data[0]);
|
||||
e->trk_port6 = FIELD_GET(RTL931X_LAG_TRK_PORT6, data[0]);
|
||||
|
||||
/* 63-32 */
|
||||
e->trk_dev5 = FIELD_GET(RTL931X_LAG_TRK_DEV5, data[1]);
|
||||
e->trk_port5 = FIELD_GET(RTL931X_LAG_TRK_PORT5, data[1]);
|
||||
e->trk_dev4 = FIELD_GET(RTL931X_LAG_TRK_DEV4, data[1]);
|
||||
e->trk_port4 = FIELD_GET(RTL931X_LAG_TRK_PORT4, data[1]);
|
||||
e->trk_dev3 = FIELD_GET(RTL931X_LAG_TRK_DEV3, data[1]);
|
||||
e->trk_port3 = FIELD_GET(RTL931X_LAG_TRK_PORT3, data[1]);
|
||||
|
||||
/* 31-0 */
|
||||
e->trk_dev2 = FIELD_GET(RTL931X_LAG_TRK_DEV2, data[2]);
|
||||
e->trk_port2 = FIELD_GET(RTL931X_LAG_TRK_PORT2, data[2]);
|
||||
e->trk_dev1 = FIELD_GET(RTL931X_LAG_TRK_DEV1, data[2]);
|
||||
e->trk_port1 = FIELD_GET(RTL931X_LAG_TRK_PORT1, data[2]);
|
||||
e->trk_dev0 = FIELD_GET(RTL931X_LAG_TRK_DEV0, data[2]);
|
||||
e->trk_port0 = FIELD_GET(RTL931X_LAG_TRK_PORT0, data[2]);
|
||||
}
|
||||
|
||||
/* Write lag-entry data into buffer */
|
||||
static void rtldsa_931x_lag_write_data(u32 data[], struct rtldsa_93xx_lag_entry *e)
|
||||
{
|
||||
/* 95-64 */
|
||||
data[0] = FIELD_PREP(RTL931X_LAG_NUM_TX_CANDI, e->num_tx_candi);
|
||||
data[0] |= FIELD_PREP(RTL931X_LAG_L2_HASH_MSK_IDX, e->l2_hash_mask_idx);
|
||||
data[0] |= FIELD_PREP(RTL931X_LAG_IP4_HASH_MSK_IDX, e->ip4_hash_mask_idx);
|
||||
data[0] |= FIELD_PREP(RTL931X_LAG_IP6_HASH_MSK_IDX, e->ip6_hash_mask_idx);
|
||||
data[0] |= FIELD_PREP(RTL931X_LAG_SEP_FLOOD_EN, e->flood_dlf_bcast.sep_flood_en);
|
||||
data[0] |= FIELD_PREP(RTL931X_LAG_SEP_KWN_MC_EN, e->sep_kwn_mc_en);
|
||||
data[0] |= FIELD_PREP(RTL931X_LAG_TRK_DEV7, e->trk_dev7);
|
||||
data[0] |= FIELD_PREP(RTL931X_LAG_TRK_PORT7, e->trk_port7);
|
||||
data[0] |= FIELD_PREP(RTL931X_LAG_TRK_DEV6, e->trk_dev6);
|
||||
data[0] |= FIELD_PREP(RTL931X_LAG_TRK_PORT6, e->trk_port6);
|
||||
|
||||
/* 63-32 */
|
||||
data[1] = FIELD_PREP(RTL931X_LAG_TRK_DEV5, e->trk_dev5);
|
||||
data[1] |= FIELD_PREP(RTL931X_LAG_TRK_PORT5, e->trk_port5);
|
||||
data[1] |= FIELD_PREP(RTL931X_LAG_TRK_DEV4, e->trk_dev4);
|
||||
data[1] |= FIELD_PREP(RTL931X_LAG_TRK_PORT4, e->trk_port4);
|
||||
data[1] |= FIELD_PREP(RTL931X_LAG_TRK_DEV3, e->trk_dev3);
|
||||
data[1] |= FIELD_PREP(RTL931X_LAG_TRK_PORT3, e->trk_port3);
|
||||
|
||||
/* 31-0 */
|
||||
data[2] = FIELD_PREP(RTL931X_LAG_TRK_DEV2, e->trk_dev2);
|
||||
data[2] |= FIELD_PREP(RTL931X_LAG_TRK_PORT2, e->trk_port2);
|
||||
data[2] |= FIELD_PREP(RTL931X_LAG_TRK_DEV1, e->trk_dev1);
|
||||
data[2] |= FIELD_PREP(RTL931X_LAG_TRK_PORT1, e->trk_port1);
|
||||
data[2] |= FIELD_PREP(RTL931X_LAG_TRK_DEV0, e->trk_dev0);
|
||||
data[2] |= FIELD_PREP(RTL931X_LAG_TRK_PORT0, e->trk_port0);
|
||||
}
|
||||
|
||||
static void rtldsa_931x_lag_set_local_group_id(int local_group, int global_group, bool valid)
|
||||
{
|
||||
u32 mask = 0;
|
||||
|
||||
mask |= valid ? RTL931X_TRK_ID_CTRL_TRK_VALID : 0;
|
||||
mask |= FIELD_PREP(RLT931X_TRK_ID_CTRL_TRK_ID, global_group);
|
||||
sw_w32(mask, RTL931X_TRK_ID_CTRL + (4 * local_group));
|
||||
}
|
||||
|
||||
static void rtldsa_931x_lag_set_local_port2group(int group, int port, bool valid)
|
||||
{
|
||||
u32 mask = 0;
|
||||
|
||||
mask |= valid ? RTL931X_LOCAL_PORT_TRK_MAP_IS_TRK_MBR : 0;
|
||||
mask |= FIELD_PREP(RTL931X_LOCAL_PORT_TRK_MAP_TRK_ID, group);
|
||||
sw_w32(mask, RTL931X_LOCAL_PORT_TRK_MAP + (4 * port));
|
||||
}
|
||||
|
||||
static void rtldsa_931x_lag_sync_tables(void)
|
||||
{
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
sw_w32(BIT(0), RTL931X_TRK_LOCAL_TBL_REFRESH);
|
||||
|
||||
ret = readx_poll_timeout(sw_r32, RTL931X_TRK_LOCAL_TBL_REFRESH, val,
|
||||
!(val & BIT(0)), 20, 10000);
|
||||
if (ret)
|
||||
pr_err("%s: timeout\n", __func__);
|
||||
}
|
||||
|
||||
static struct table_reg *rtldsa_931x_lag_table(void)
|
||||
{
|
||||
return rtl_table_get(RTL9310_TBL_2, 0);
|
||||
}
|
||||
|
||||
static u64 rtldsa_931x_stat_port_table_read(int port, unsigned int mib_size,
|
||||
unsigned int mib_offset, bool is_pvt)
|
||||
{
|
||||
@@ -1950,7 +2027,6 @@ const struct rtldsa_config rtldsa_931x_cfg = {
|
||||
.rma_bpdu_fld_pmask = RTL931X_RMA_BPDU_FLD_PMSK,
|
||||
.set_vlan_igr_filter = rtl931x_set_igr_filter,
|
||||
.set_vlan_egr_filter = rtl931x_set_egr_filter,
|
||||
.set_distribution_algorithm = rtl931x_set_distribution_algorithm,
|
||||
.l2_hash_key = rtl931x_l2_hash_key,
|
||||
.l2_hash_seed = rtldsa_931x_l2_hash_seed,
|
||||
.read_mcast_pmask = rtl931x_read_mcast_pmask,
|
||||
@@ -1965,4 +2041,17 @@ const struct rtldsa_config rtldsa_931x_cfg = {
|
||||
.enable_flood = rtldsa_931x_enable_flood,
|
||||
.set_receive_management_action = rtldsa_931x_set_receive_management_action,
|
||||
.qos_init = rtldsa_931x_qos_init,
|
||||
.trk_ctrl = RTL931X_TRK_CTRL,
|
||||
.trk_hash_ctrl = RTL931X_TRK_HASH_CTRL,
|
||||
.prepare_lag_fdb = rtldsa_93xx_prepare_lag_fdb,
|
||||
.lag_switch_init = rtldsa_93xx_lag_switch_init,
|
||||
.lag_set_port_members = rtldsa_93xx_lag_set_port_members,
|
||||
.lag_set_distribution_algorithm = rtldsa_93xx_lag_set_distribution_algorithm,
|
||||
.lag_set_local_group_id = rtldsa_931x_lag_set_local_group_id,
|
||||
.lag_write_data = rtldsa_931x_lag_write_data,
|
||||
.lag_fill_data = rtldsa_931x_lag_fill_data,
|
||||
.lag_set_local_port2group = rtldsa_931x_lag_set_local_port2group,
|
||||
.lag_set_port2group = rtldsa_931x_lag_set_port2group,
|
||||
.lag_sync_tables = rtldsa_931x_lag_sync_tables,
|
||||
.lag_table = rtldsa_931x_lag_table,
|
||||
};
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -19501,6 +19501,12 @@ S: Maintained
|
||||
@@ -19507,6 +19507,12 @@ S: Maintained
|
||||
F: Documentation/devicetree/bindings/net/dsa/realtek.yaml
|
||||
F: drivers/net/dsa/realtek/*
|
||||
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
|
||||
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -20158,6 +20158,13 @@ S: Maintained
|
||||
@@ -20164,6 +20164,13 @@ S: Maintained
|
||||
T: git https://github.com/pkshih/rtw.git
|
||||
F: drivers/net/wireless/realtek/rtl8xxxu/
|
||||
|
||||
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
From 0c741b8b6963e584b41c284cd743c545636edb04 Mon Sep 17 00:00:00 2001
|
||||
From: Ahmed Naseef <naseefkm@gmail.com>
|
||||
Date: Sat, 7 Feb 2026 11:02:43 +0400
|
||||
Subject: mtd: nand: realtek-ecc: relax OOB size check to minimum
|
||||
|
||||
The ECC engine strictly validates that flash OOB size equals exactly
|
||||
64 bytes. However, some NAND chips have a larger physical OOB while
|
||||
vendor firmware only uses the first 64 bytes for the ECC layout. For
|
||||
example the Macronix MX35LF1G24AD found in the Netlink HG323DAC has
|
||||
128 byte physical OOB but vendor firmware only uses the first 64
|
||||
bytes (24 bytes free + 40 bytes BCH6 parity), leaving bytes 64-127
|
||||
unused.
|
||||
|
||||
Since the engine only operates on the first 64 bytes of OOB
|
||||
regardless of the physical size, change the check from exact match
|
||||
to minimum size. Flash with OOB >= 64 bytes works correctly with
|
||||
the engine's 64-byte layout.
|
||||
|
||||
Suggested-by: Markus Stockhausen <markus.stockhausen@gmx.de>
|
||||
Signed-off-by: Ahmed Naseef <naseefkm@gmail.com>
|
||||
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
||||
---
|
||||
drivers/mtd/nand/ecc-realtek.c | 18 ++++++++++--------
|
||||
1 file changed, 10 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/nand/ecc-realtek.c
|
||||
+++ b/drivers/mtd/nand/ecc-realtek.c
|
||||
@@ -17,10 +17,12 @@
|
||||
* - BCH12 : Generate 20 ECC bytes from 512 data bytes plus 6 free bytes
|
||||
*
|
||||
* It can run for arbitrary NAND flash chips with different block and OOB sizes. Currently there
|
||||
- * are only two known devices in the wild that have NAND flash and make use of this ECC engine
|
||||
- * (Linksys LGS328C & LGS352C). To keep compatibility with vendor firmware, new modes can only
|
||||
- * be added when new data layouts have been analyzed. For now allow BCH6 on flash with 2048 byte
|
||||
- * blocks and 64 bytes oob.
|
||||
+ * are a few known devices in the wild that make use of this ECC engine
|
||||
+ * (Linksys LGS328C, LGS352C & Netlink HG323DAC). To keep compatibility with vendor firmware,
|
||||
+ * new modes can only be added when new data layouts have been analyzed. For now allow BCH6 on
|
||||
+ * flash with 2048 byte blocks and at least 64 bytes oob. Some vendors make use of
|
||||
+ * 128 bytes OOB NAND chips (e.g. Macronix MX35LF1G24AD) but only use BCH6 and thus the first
|
||||
+ * 64 bytes of the OOB area. In this case the engine leaves any extra bytes unused.
|
||||
*
|
||||
* This driver aligns with kernel ECC naming conventions. Neverthless a short notice on the
|
||||
* Realtek naming conventions for the different structures in the OOB area.
|
||||
@@ -39,7 +41,7 @@
|
||||
*/
|
||||
|
||||
#define RTL_ECC_ALLOWED_PAGE_SIZE 2048
|
||||
-#define RTL_ECC_ALLOWED_OOB_SIZE 64
|
||||
+#define RTL_ECC_ALLOWED_MIN_OOB_SIZE 64
|
||||
#define RTL_ECC_ALLOWED_STRENGTH 6
|
||||
|
||||
#define RTL_ECC_BLOCK_SIZE 512
|
||||
@@ -310,10 +312,10 @@ static int rtl_ecc_check_support(struct
|
||||
struct mtd_info *mtd = nanddev_to_mtd(nand);
|
||||
struct device *dev = nand->ecc.engine->dev;
|
||||
|
||||
- if (mtd->oobsize != RTL_ECC_ALLOWED_OOB_SIZE ||
|
||||
+ if (mtd->oobsize < RTL_ECC_ALLOWED_MIN_OOB_SIZE ||
|
||||
mtd->writesize != RTL_ECC_ALLOWED_PAGE_SIZE) {
|
||||
- dev_err(dev, "only flash geometry data=%d, oob=%d supported\n",
|
||||
- RTL_ECC_ALLOWED_PAGE_SIZE, RTL_ECC_ALLOWED_OOB_SIZE);
|
||||
+ dev_err(dev, "only flash geometry data=%d, oob>=%d supported\n",
|
||||
+ RTL_ECC_ALLOWED_PAGE_SIZE, RTL_ECC_ALLOWED_MIN_OOB_SIZE);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
From linux-i2c Fri Feb 27 11:11:34 2026
|
||||
From: Jan Kantert <jan-kernel () kantert ! net>
|
||||
Date: Fri, 27 Feb 2026 11:11:34 +0000
|
||||
To: linux-i2c
|
||||
Subject: [PATCH] i2c: rtl9300: add support for 50 kHz and 2.5 MHz bus speeds
|
||||
Message-Id: <20260227111134.2163701-1-jan-kernel () kantert ! net>
|
||||
X-MARC-Message: https://marc.info/?l=linux-i2c&m=177219358420283
|
||||
|
||||
Some SFP modules on certain switches (for example the ONTi ONT-S508CL-8S and
|
||||
XikeStor SKS8300-8X) exhibit unreliable I2C communication at the currently
|
||||
supported speeds. Add support for 50 kHz and 2.5 MHz I2C bus modes on the
|
||||
RTL9300 to improve compatibility with these devices.
|
||||
|
||||
Signed-off-by: Jan Kantert <jan-kernel@kantert.net>
|
||||
---
|
||||
drivers/i2c/busses/i2c-rtl9300.c | 16 ++++++++++++++--
|
||||
1 file changed, 14 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/i2c/busses/i2c-rtl9300.c
|
||||
+++ b/drivers/i2c/busses/i2c-rtl9300.c
|
||||
@@ -11,10 +11,16 @@
|
||||
#include <linux/unaligned.h>
|
||||
|
||||
enum rtl9300_bus_freq {
|
||||
- RTL9300_I2C_STD_FREQ,
|
||||
- RTL9300_I2C_FAST_FREQ,
|
||||
+ RTL9300_I2C_STD_FREQ, // 100kHz
|
||||
+ RTL9300_I2C_FAST_FREQ, // 400kHz
|
||||
+ RTL9300_I2C_SUPER_FAST_FREQ, // 2.5MHz
|
||||
+ RTL9300_I2C_SLOW_FREQ, // 50kHz
|
||||
};
|
||||
|
||||
+#define RTL9300_I2C_MAX_SUPER_FAST_FREQ 2500000
|
||||
+#define RTL9300_I2C_MAX_SLOW_FREQ 50000
|
||||
+
|
||||
+
|
||||
struct rtl9300_i2c;
|
||||
|
||||
struct rtl9300_i2c_chan {
|
||||
@@ -434,6 +440,12 @@ static int rtl9300_i2c_probe(struct plat
|
||||
case I2C_MAX_FAST_MODE_FREQ:
|
||||
chan->bus_freq = RTL9300_I2C_FAST_FREQ;
|
||||
break;
|
||||
+ case RTL9300_I2C_MAX_SUPER_FAST_FREQ:
|
||||
+ chan->bus_freq = RTL9300_I2C_SUPER_FAST_FREQ;
|
||||
+ break;
|
||||
+ case RTL9300_I2C_MAX_SLOW_FREQ:
|
||||
+ chan->bus_freq = RTL9300_I2C_SLOW_FREQ;
|
||||
+ break;
|
||||
default:
|
||||
dev_warn(i2c->dev, "SDA%d clock-frequency %d not supported using default\n",
|
||||
sda_num, clock_freq);
|
||||
@@ -10,7 +10,7 @@ Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
|
||||
|
||||
--- a/drivers/net/phy/sfp.c
|
||||
+++ b/drivers/net/phy/sfp.c
|
||||
@@ -718,10 +718,64 @@ static int sfp_i2c_write(struct sfp *sfp
|
||||
@@ -724,10 +724,64 @@ static int sfp_i2c_write(struct sfp *sfp
|
||||
return ret == ARRAY_SIZE(msgs) ? len : 0;
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
|
||||
|
||||
sfp->i2c = i2c;
|
||||
sfp->read = sfp_i2c_read;
|
||||
@@ -753,6 +807,29 @@ static int sfp_i2c_mdiobus_create(struct
|
||||
@@ -759,6 +813,29 @@ static int sfp_i2c_mdiobus_create(struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
|
||||
static void sfp_i2c_mdiobus_destroy(struct sfp *sfp)
|
||||
{
|
||||
mdiobus_unregister(sfp->i2c_mii);
|
||||
@@ -1927,9 +2004,15 @@ static void sfp_sm_fault(struct sfp *sfp
|
||||
@@ -1933,9 +2010,15 @@ static void sfp_sm_fault(struct sfp *sfp
|
||||
|
||||
static int sfp_sm_add_mdio_bus(struct sfp *sfp)
|
||||
{
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
|
||||
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -22072,7 +22072,7 @@ STARFIVE JH71X0 RESET CONTROLLER DRIVERS
|
||||
@@ -22078,7 +22078,7 @@ STARFIVE JH71X0 RESET CONTROLLER DRIVERS
|
||||
M: Emil Renner Berthing <kernel@esmil.dk>
|
||||
M: Hal Feng <hal.feng@starfivetech.com>
|
||||
S: Maintained
|
||||
|
||||
@@ -11,9 +11,9 @@ PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL=$(PROJECT_GIT)/project/firmware-utils.git
|
||||
PKG_SOURCE_DATE:=2025-11-11
|
||||
PKG_SOURCE_VERSION:=c42a3bc53da869d02c8ae4d62b3b08a95ff5833f
|
||||
PKG_MIRROR_HASH:=c9cbe9aafc3476dac9d9bd1b26f932048f895bce775e8220f82fae097463c539
|
||||
PKG_SOURCE_DATE:=2026-03-05
|
||||
PKG_SOURCE_VERSION:=6a87eaf434cb89d4eba0b811a4b5d158fd9c519f
|
||||
PKG_MIRROR_HASH:=b40d6b02dc896359e413dd2ae9d0d616b5c1270dd1eb825b317d27fa531582e2
|
||||
|
||||
include $(INCLUDE_DIR)/host-build.mk
|
||||
include $(INCLUDE_DIR)/cmake.mk
|
||||
|
||||
Reference in New Issue
Block a user