diff --git a/package/boot/uboot-envtools/files/qualcommax_ipq807x b/package/boot/uboot-envtools/files/qualcommax_ipq807x index 49754338a59dc2..840e97fa10cb12 100644 --- a/package/boot/uboot-envtools/files/qualcommax_ipq807x +++ b/package/boot/uboot-envtools/files/qualcommax_ipq807x @@ -7,74 +7,71 @@ touch /etc/config/ubootenv board=$(board_name) +ubootenv_add_mtd() { + local idx="$(find_mtd_index "${1}")" + [ -n "$idx" ] && \ + ubootenv_add_uci_config "/dev/mtd$idx" "${2}" "${3}" "${4}" +} + +ubootenv_add_sys_mtd() { + local idx="$(find_mtd_index "${1}")" + [ -n "$idx" ] && \ + ubootenv_add_uci_sys_config "/dev/mtd$idx" "${2}" "${3}" "${4}" +} + +ubootenv_add_mmc() { + local mmcpart="$(find_mmc_part "${1}")" + [ -n "$mmcpart" ] && \ + ubootenv_add_uci_config "$mmcpart" "${2}" "${3}" "${4}" "${5}" +} + case "$board" in dynalink,dl-wrx36|\ netgear,rax120v2|\ +netgear,sxr80|\ +netgear,sxs80|\ netgear,wax218|\ netgear,wax620|\ -netgear,wax630) - idx="$(find_mtd_index 0:appsblenv)" - [ -n "$idx" ] && \ - ubootenv_add_uci_config "/dev/mtd$idx" "0x0" "0x40000" "0x20000" "2" +netgear,wax630|\ +tplink,eap620hd-v1|\ +tplink,eap660hd-v1) + ubootenv_add_mtd "0:appsblenv" "0x0" "0x40000" "0x20000" ;; compex,wpq873|\ edgecore,eap102|\ zyxel,nbg7815) - idx="$(find_mtd_index 0:appsblenv)" - [ -n "$idx" ] && \ - ubootenv_add_uci_config "/dev/mtd$idx" "0x0" "0x10000" "0x10000" "1" + ubootenv_add_mtd "0:appsblenv" "0x0" "0x10000" "0x10000" ;; edimax,cax1800) - idx="$(find_mtd_index 0:appsblenv)" - [ -n "$idx" ] && \ - ubootenv_add_uci_config "/dev/mtd$idx" "0x0" "0x10000" "0x20000" + ubootenv_add_mtd "0:appsblenv" "0x0" "0x10000" "0x20000" + ;; +linksys,homewrk) + ubootenv_add_mtd "0:appsblenv" "0x0" "0x40000" "0x40000" ;; linksys,mx4200v1|\ linksys,mx4200v2|\ linksys,mx5300|\ linksys,mx8500) - idx="$(find_mtd_index u_env)" - [ -n "$idx" ] && \ - ubootenv_add_uci_config "/dev/mtd$idx" "0x0" "0x40000" "0x20000" "2" + ubootenv_add_mtd "u_env" "0x0" "0x40000" "0x20000" ;; linksys,mx4300) - idx="$(find_mtd_index u_env)" - [ -n "$idx" ] && \ - ubootenv_add_uci_config "/dev/mtd$idx" "0x0" "0x40000" "0x40000" "1" - ;; -netgear,sxr80|\ -netgear,sxs80|\ -tplink,eap620hd-v1|\ -tplink,eap660hd-v1) - idx="$(find_mtd_index 0:appsblenv)" - [ -n "$idx" ] && \ - ubootenv_add_uci_config "/dev/mtd$idx" "0x0" "0x40000" "0x20000" + ubootenv_add_mtd "u_env" "0x0" "0x40000" "0x40000" ;; redmi,ax6|\ xiaomi,ax3600|\ xiaomi,ax9000) - idx="$(find_mtd_index 0:appsblenv)" - [ -n "$idx" ] && \ - ubootenv_add_uci_config "/dev/mtd$idx" "0x0" "0x10000" "0x20000" - idx2="$(find_mtd_index bdata)" - [ -n "$idx2" ] && \ - ubootenv_add_uci_sys_config "/dev/mtd$idx2" "0x0" "0x10000" "0x20000" + ubootenv_add_mtd "0:appsblenv" "0x0" "0x10000" "0x20000" + ubootenv_add_sys_mtd "bdata" "0x0" "0x10000" "0x20000" ;; prpl,haze) - mmcpart="$(find_mmc_part 0:APPSBLENV)" - [ -n "$mmcpart" ] && \ - ubootenv_add_uci_config "$mmcpart" "0x0" "0x40000" "0x400" "0x100" + ubootenv_add_mmc "0:APPSBLENV" "0x0" "0x40000" "0x400" "0x100" ;; asus,rt-ax89x|\ qnap,301w) - idx="$(find_mtd_index 0:appsblenv)" - [ -n "$idx" ] && \ - ubootenv_add_uci_config "/dev/mtd$idx" "0x0" "0x20000" "0x20000" "1" + ubootenv_add_mtd "0:appsblenv" "0x0" "0x20000" "0x20000" ;; spectrum,sax1v1k) - mmcpart="$(find_mmc_part 0:APPSBLENV)" - [ -n "$mmcpart" ] && \ - ubootenv_add_uci_config "$mmcpart" "0x0" "0x40000" "0x40000" "1" + ubootenv_add_mmc "0:APPSBLENV" "0x0" "0x40000" "0x40000" "1" ;; esac diff --git a/package/firmware/ipq-wifi/Makefile b/package/firmware/ipq-wifi/Makefile index 9821e39a85fe9c..da5fd5e23e9fd6 100644 --- a/package/firmware/ipq-wifi/Makefile +++ b/package/firmware/ipq-wifi/Makefile @@ -6,9 +6,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/firmware/qca-wireless.git -PKG_SOURCE_DATE:=2024-12-18 -PKG_SOURCE_VERSION:=4b849214b137b14a903112af3c2016ad9acf48c2 -PKG_MIRROR_HASH:=28162682fe7612460e42398ecc669e245fc0ece873361e3910c2dd8a56111f1c +PKG_SOURCE_DATE:=2025-01-15 +PKG_SOURCE_VERSION:=6e1801a4992fe72a98a2219f2dcd038194785971 +PKG_MIRROR_HASH:=569cf6894e21712ed6a5553b4fad0bbdeed14e0cc4b9292f5f86343f7897fc7e PKG_FLAGS:=nonshared include $(INCLUDE_DIR)/package.mk @@ -37,6 +37,7 @@ ALLWIFIBOARDS:= \ dynalink_dl-wrx36 \ edgecore_eap102 \ edimax_cax1800 \ + linksys_homewrk \ linksys_mr7350 \ linksys_mx4200 \ linksys_mx5300 \ @@ -168,6 +169,7 @@ $(eval $(call generate-ipq-wifi-package,compex_wpq873,Compex WPQ-873)) $(eval $(call generate-ipq-wifi-package,dynalink_dl-wrx36,Dynalink DL-WRX36)) $(eval $(call generate-ipq-wifi-package,edgecore_eap102,Edgecore EAP102)) $(eval $(call generate-ipq-wifi-package,edimax_cax1800,Edimax CAX1800)) +$(eval $(call generate-ipq-wifi-package,linksys_homewrk,Linksys HomeWRK)) $(eval $(call generate-ipq-wifi-package,linksys_mr7350,Linksys MR7350)) $(eval $(call generate-ipq-wifi-package,linksys_mx4200,Linksys MX4200)) $(eval $(call generate-ipq-wifi-package,linksys_mx5300,Linksys MX5300)) diff --git a/package/kernel/linux/modules/netdevices.mk b/package/kernel/linux/modules/netdevices.mk index 2a6ecb7a2bd4b0..24a41c6b3f832e 100644 --- a/package/kernel/linux/modules/netdevices.mk +++ b/package/kernel/linux/modules/netdevices.mk @@ -447,9 +447,10 @@ $(eval $(call KernelPackage,phy-micrel)) define KernelPackage/phy-realtek SUBMENU:=$(NETWORK_DEVICES_MENU) TITLE:=Realtek Ethernet PHY driver - KCONFIG:=CONFIG_REALTEK_PHY - DEPENDS:=+kmod-libphy - FILES:=$(LINUX_DIR)/drivers/net/phy/realtek.ko + KCONFIG:=CONFIG_REALTEK_PHY \ + CONFIG_REALTEK_PHY_HWMON=y + DEPENDS:=+kmod-libphy +kmod-hwmon-core + FILES:=$(LINUX_DIR)/drivers/net/phy/realtek/realtek.ko AUTOLOAD:=$(call AutoLoad,18,realtek,1) endef @@ -959,7 +960,7 @@ $(eval $(call KernelPackage,8139cp)) define KernelPackage/r8169 SUBMENU:=$(NETWORK_DEVICES_MENU) TITLE:=RealTek RTL-8169 PCI Gigabit Ethernet Adapter kernel support - DEPENDS:=@PCI_SUPPORT +kmod-mii +r8169-firmware +kmod-phy-realtek +kmod-mdio-devres +kmod-hwmon-core + DEPENDS:=@PCI_SUPPORT +kmod-mii +r8169-firmware +kmod-phy-realtek +kmod-mdio-devres KCONFIG:= \ CONFIG_R8169 \ CONFIG_R8169_LEDS=y diff --git a/package/kernel/mac80211/patches/build/110-backport-include-fix-linux-acpi_amd_wbrf.h-inclusion.patch b/package/kernel/mac80211/patches/build/110-backport-include-fix-linux-acpi_amd_wbrf.h-inclusion.patch new file mode 100644 index 00000000000000..d8d3783ed607e0 --- /dev/null +++ b/package/kernel/mac80211/patches/build/110-backport-include-fix-linux-acpi_amd_wbrf.h-inclusion.patch @@ -0,0 +1,32 @@ +From: Felix Fietkau +Date: Tue, 14 Jan 2025 11:42:25 +0100 +Subject: [PATCH] backport-include: fix linux/acpi_amd_wbrf.h inclusion + +Fix building for kernel >= 6.8 by adjusting incorrect guard usage, +otherwise an #include_next header is masked and compilation will fail +for net/mac80211/wbrf.c in the mac80211 kernel module. + +Fixes: 52cdcaab ("backport-include: backport linux/acpi_amd_wbrf.h") +Reported-by: Tony Ambardar +Signed-off-by: Felix Fietkau +--- + +--- a/backport-include/linux/acpi_amd_wbrf.h ++++ b/backport-include/linux/acpi_amd_wbrf.h +@@ -4,8 +4,8 @@ + * Copyright (C) 2023 Advanced Micro Devices + */ + +-#ifndef _ACPI_AMD_WBRF_H +-#define _ACPI_AMD_WBRF_H ++#ifndef __BACKPORT_ACPI_AMD_WBRF_H ++#define __BACKPORT_ACPI_AMD_WBRF_H + + #if LINUX_VERSION_IS_GEQ(6,8,0) + #include_next +@@ -83,4 +83,4 @@ int amd_wbrf_unregister_notifier(struct + } + + #endif /* >=6,8,0 */ +-#endif /* _ACPI_AMD_WBRF_H */ ++#endif /* __BACKPORT_ACPI_AMD_WBRF_H */ diff --git a/package/kernel/mt76/Makefile b/package/kernel/mt76/Makefile index 7bc030a9df3ce2..cd168f49bcc0dd 100644 --- a/package/kernel/mt76/Makefile +++ b/package/kernel/mt76/Makefile @@ -8,9 +8,9 @@ PKG_LICENSE_FILES:= PKG_SOURCE_URL:=https://github.com/openwrt/mt76 PKG_SOURCE_PROTO:=git -PKG_SOURCE_DATE:=2025-01-04 -PKG_SOURCE_VERSION:=e354436db4402552bcb0cbe9abab2a46fb1ad31c -PKG_MIRROR_HASH:=7e3894e1f2641e172f87be1ae0cc6adda318d989350ebd53500a7df02f0afd8f +PKG_SOURCE_DATE:=2025-01-14 +PKG_SOURCE_VERSION:=8e4f72b682e9070108536507c5e2720b18c3816d +PKG_MIRROR_HASH:=fa8c5a2ece9e7287605910d9f906b601711c7863613addaadd666f9e3858a9e7 PKG_MAINTAINER:=Felix Fietkau PKG_USE_NINJA:=0 diff --git a/package/network/config/netifd/files/usr/libexec/network/packet-steering.uc b/package/network/config/netifd/files/usr/libexec/network/packet-steering.uc index a578e288791d7d..34df46d18ef5d8 100755 --- a/package/network/config/netifd/files/usr/libexec/network/packet-steering.uc +++ b/package/network/config/netifd/files/usr/libexec/network/packet-steering.uc @@ -65,8 +65,9 @@ function cpu_mask(cpu) return sprintf("%x", mask); } -function set_netdev_cpu(dev, cpu) { - let queues = glob(`/sys/class/net/${dev}/queues/rx-*/rps_cpus`); +function set_netdev_cpu(dev, cpu, rx_queue) { + rx_queue ??= "rx-*"; + let queues = glob(`/sys/class/net/${dev}/queues/${rx_queue}/rps_cpus`); let val = cpu_mask(cpu); if (disable) val = 0; @@ -76,7 +77,7 @@ function set_netdev_cpu(dev, cpu) { if (!do_nothing) writefile(queue, `${val}`); } - queues = glob(`/sys/class/net/${dev}/queues/rx-*/rps_flow_cnt`); + queues = glob(`/sys/class/net/${dev}/queues/${rx_queue}/rps_flow_cnt`); for (let queue in queues) { if (debug || do_nothing) warn(`echo ${local_flows} > ${queue}\n`); @@ -87,7 +88,7 @@ function set_netdev_cpu(dev, cpu) { function task_device_match(name, device) { - let napi_match = match(name, /napi\/([^-+])-\d+/); + let napi_match = match(name, /napi\/([^-]*)-\d+/); if (!napi_match) napi_match = match(name, /mt76-tx (phy\d+)/); if (napi_match && @@ -160,6 +161,9 @@ for (let dev in netdevs) { netdev: [], phy: [], tasks: [], + rx_tasks: [], + rx_queues: map(glob(`/sys/class/net/${dev}/queues/rx-*/rps_cpus`), + (v) => basename(dirname(v))), }; } @@ -187,11 +191,51 @@ for (let path in glob("/proc/*/exe")) { continue; push(dev.tasks, pid); + + let napi_match = match(name, /napi\/([^-]*)-(\d+)/); + if (napi_match && napi_match[2] > 0) + push(dev.rx_tasks, pid); break; } } +function assign_dev_queues_cpu(dev) { + let num = length(dev.rx_queues); + if (num < length(dev.rx_tasks)) + num = length(dev.rx_tasks); + + for (let i = 0; i < num; i++) { + let cpu; + + let task = dev.rx_tasks[i]; + if (num >= length(cpus)) + cpu = i % length(cpus); + else if (task) + cpu = get_next_cpu(napi_weight); + else + cpu = -1; + set_task_cpu(task, cpu); + + let rxq = dev.rx_queues[i]; + if (!rxq) + continue; + + if (num >= length(cpus)) + cpu = (i + 1) % length(cpus); + else if (all_cpus) + cpu = -1; + else + cpu = get_next_cpu(napi_weight, cpu); + for (let netdev in dev.netdev) + set_netdev_cpu(netdev, cpu, rxq); + } +} + function assign_dev_cpu(dev) { + if (length(dev.rx_queues) > 1 && + length(dev.rx_tasks) > 1) + return assign_dev_queues_cpu(dev); + if (length(dev.tasks) > 0) { let cpu = dev.napi_cpu = get_next_cpu(napi_weight); for (let task in dev.tasks) @@ -204,7 +248,6 @@ function assign_dev_cpu(dev) { cpu = -1; else cpu = get_next_cpu(rx_weight, dev.napi_cpu); - dev.rx_cpu = cpu; for (let netdev in dev.netdev) set_netdev_cpu(netdev, cpu); } diff --git a/package/network/config/wifi-scripts/files-ucode/usr/share/ucode/wifi/hostapd.uc b/package/network/config/wifi-scripts/files-ucode/usr/share/ucode/wifi/hostapd.uc index adbfc1b9781436..0e3cfc5b901b85 100644 --- a/package/network/config/wifi-scripts/files-ucode/usr/share/ucode/wifi/hostapd.uc +++ b/package/network/config/wifi-scripts/files-ucode/usr/share/ucode/wifi/hostapd.uc @@ -493,7 +493,7 @@ function generate(config) { if (!phy_features.radar_background || config.band != '5g') delete config.enable_background_radar; else - set_default(config, 'enable_background_radar', phy_features.radar_background); + set_default(config, 'enable_background_radar', false); append_vars(config, [ 'acs_chan_bias', 'acs_exclude_dfs', 'enable_background_radar' ]); diff --git a/package/network/services/lldpd/Makefile b/package/network/services/lldpd/Makefile index f34cd28faac965..3fbd0bf4f93ae8 100644 --- a/package/network/services/lldpd/Makefile +++ b/package/network/services/lldpd/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=lldpd -PKG_VERSION:=1.0.17 -PKG_RELEASE:=5 +PKG_VERSION:=1.0.18 +PKG_RELEASE:=2 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://github.com/lldpd/lldpd/releases/download/$(PKG_VERSION)/ -PKG_HASH:=89ae691a4917ac9e0ec3b8b2c1e634cc402d43b804f98850c73bd1c7df380882 +PKG_HASH:=38cd319aa02ab61d9a2ad130e22f906795ccca9ac73a0a0d9dac19ca99a8a870 PKG_MAINTAINER:=Stijn Tintel PKG_LICENSE:=ISC @@ -90,6 +90,8 @@ endif ifneq ($(CONFIG_LLDPD_WITH_LLDPMED),y) sed -i -e 's/CONFIG_LLDPD_WITH_LLDPMED=y/CONFIG_LLDPD_WITH_LLDPMED=n/g' $(1)/etc/init.d/lldpd sed -i -e '/agentxsocket/d' $(1)/etc/config/lldpd + sed -i -e '/lldp_class/d' $(1)/etc/config/lldpd + sed -i -e '/lldp_location/d' $(1)/etc/config/lldpd endif endef diff --git a/package/network/services/lldpd/files/lldpd.init b/package/network/services/lldpd/files/lldpd.init index 3922b676b52e69..6c1c184bfa10a6 100644 --- a/package/network/services/lldpd/files/lldpd.init +++ b/package/network/services/lldpd/files/lldpd.init @@ -39,7 +39,6 @@ get_config_restart_hash() { config_load 'lldpd' - config_get v 'config' 'lldp_class'; append _string "$v" "," if [ "$CONFIG_LLDPD_WITH_SNMP" = "y" ]; then config_get v 'config' 'agentxsocket'; append _string "$v" "," fi @@ -49,6 +48,7 @@ get_config_restart_hash() { config_get_bool v 'config' 'lldp_no_version'; append _string "$v" "," if [ "$CONFIG_LLDPD_WITH_LLDPMED" = "y" ]; then config_get_bool v 'config' 'lldpmed_no_inventory'; append _string "$v" "," + config_get v 'config' 'lldp_class'; append _string "$v" "," fi config_get_bool v 'config' 'enable_lldp' 1; append _string "$v" "," config_get_bool v 'config' 'force_lldp'; append _string "$v" "," @@ -243,10 +243,10 @@ start_service() { config_get_bool enable_edp 'config' 'enable_edp' 0 config_get_bool force_edp 'config' 'force_edp' 0 fi - config_get lldp_class 'config' 'lldp_class' config_get_bool lldp_no_version 'config' 'lldp_no_version' 0 if [ "$CONFIG_LLDPD_WITH_LLDPMED" = "y" ]; then config_get_bool lldpmed_no_inventory 'config' 'lldpmed_no_inventory' 0 + config_get lldp_class 'config' 'lldp_class' fi config_get_bool readonly_mode 'config' 'readonly_mode' 0 if [ "$CONFIG_LLDPD_WITH_SNMP" = "y" ]; then diff --git a/package/system/uci/Makefile b/package/system/uci/Makefile index 6b902a9c24f9d3..a253b43938f9f8 100644 --- a/package/system/uci/Makefile +++ b/package/system/uci/Makefile @@ -13,9 +13,9 @@ PKG_RELEASE:=1 PKG_SOURCE_URL=$(PROJECT_GIT)/project/uci.git PKG_SOURCE_PROTO:=git -PKG_SOURCE_DATE:=2024-11-26 -PKG_SOURCE_VERSION:=10f7996ec29449915640acca5d65b592365a4b14 -PKG_MIRROR_HASH:=8556add0dd77b85a5702faa94feb811606390c045d7f5004317a4ab3e07f773b +PKG_SOURCE_DATE:=2025-01-17 +PKG_SOURCE_VERSION:=fb3c2343b17b759b175f11aec5b3fbb1cf48bbc3 +PKG_MIRROR_HASH:=c9302f4a1cb400134cb9fc0622fb6a04bbe8c55bcc83ec454caadb1e62f3257e PKG_LICENSE:=LGPL-2.1 PKG_LICENSE_FILES:= @@ -33,7 +33,7 @@ define Package/libuci CATEGORY:=Libraries TITLE:=C library for the Unified Configuration Interface (UCI) DEPENDS:=+libubox - ABI_VERSION:=20130104 + ABI_VERSION:=20250117 endef define Package/uci diff --git a/package/utils/ucode-mod-pkgen/Makefile b/package/utils/ucode-mod-pkgen/Makefile new file mode 100644 index 00000000000000..918aa22a902962 --- /dev/null +++ b/package/utils/ucode-mod-pkgen/Makefile @@ -0,0 +1,44 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=ucode-mod-pkgen +PKG_RELEASE:=1 +PKG_LICENSE:=GPL-2.0-or-later +PKG_MAINTAINER:=Felix Fietkau + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/cmake.mk + +CMAKE_INSTALL := 1 + +define Package/ucode-mod-pkgen + SECTION:=utils + CATEGORY:=Utilities + TITLE:=ucode module for generating public keys/certificates + DEPENDS:=+libucode +libmbedtls +endef + +define Package/ucode-mod-pkgen/description +The pkgen module provides functionality for generating cryptographic keys and +(self-)signed certificates. It supports exporting PEM/DER format files, as +well as PKCS#12 bundle for client cert/key pairs with CA. +endef + +define Package/pkgen + SECTION:=utils + CATEGORY:=Utilities + TITLE:=ucode script for generating public keys/certificates + DEPENDS:=+ucode +ucode-mod-pkgen +ucode-mod-fs +endef + +define Package/ucode-mod-pkgen/install + $(INSTALL_DIR) $(1)/usr/lib/ucode + $(CP) $(PKG_INSTALL_DIR)/usr/lib/ucode/pkgen.so $(1)/usr/lib/ucode/ +endef + +define Package/pkgen/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) ./files/pkgen $(1)/usr/bin +endef + +$(eval $(call BuildPackage,ucode-mod-pkgen)) +$(eval $(call BuildPackage,pkgen)) diff --git a/package/utils/ucode-mod-pkgen/files/pkgen b/package/utils/ucode-mod-pkgen/files/pkgen new file mode 100755 index 00000000000000..e37e5f5329d100 --- /dev/null +++ b/package/utils/ucode-mod-pkgen/files/pkgen @@ -0,0 +1,252 @@ +#!/usr/bin/env ucode +'use strict'; + +import { basename, readfile, writefile, stdin } from "fs"; +let pk = require("pkgen"); +let valid_from = "20240101000000"; +let valid_to = "21001231235959"; +let subject, password, password_stdin; +let keytype = "ec"; +let keylen = 2048; +let keyexp = 65537; +let keycurve = "secp256r1"; +let no_ca; +let legacy; + +const usage_message = `Usage: ${basename(sourcepath())} [] [] + +Commands: + ca : Create a new CA. + (creates ca.pem, ca.key, ca.serial) + + cert : Create a new certificate/key using the CA + from ca.pem. (creates cert.pem and ca.key) + + cert_p12 : Create a new PKCS#12 certificate/key + using the CA from ca.pem. (creates ca.p12) + + selfsigned : Create a self-signed certificate + (creates cert.pem) + +Options: + -C Set EC curve type (default: ${keycurve}) + Possible values: secp521r1, secp384r1, secp256r1, + secp256k1, secp224r1, secp224k1, secp192r1, + secp192k1 + -E Set RSA key exponent (default: ${keyexp}) + -L Set RSA key length (default: ${keylen}) + -N Omit CA certificate for PKCS#12 files + -p Set PKCS#12 password to + -P Read PKCS#12 password from stdin + (default: random password, printed to stdout) + -s Set subject for generated certificate to . + -t rsa|ec Set key type to rsa or ec (default: ec) + -V Set validity for generated certificates. + (default: ${valid_from} ${valid_to}) + -W Use weaker PKCS#12 encryption for + compatibility with Windows and Apple systems + +`; + +function perror(msg) { + let err = pk.errno() == -1 ? "Invalid arguments" : pk.error(); + warn(`${msg}: ${err}\n`); + exit(1); +} + +function usage() { + warn(usage_message); + exit(1); +} + +function check_pem_path(pem_file) { + if (substr(pem_file, -4) != ".pem") { + warn(`Path with .pem extension expected\n`); + exit(1); + } + + return pem_file; +} + + +function gen_key() { + let key = pk.generate_key({ + type: keytype, + curve: keycurve, + size: keylen, + exponent: keyexp, + }); + + if (!key) + perror("Failed to generate CA key"); + + return key; +} + +function gen_cert(key, args) { + let cert = pk.generate_cert({ + subject_name: subject, + subject_key: key, + validity: [ valid_from, valid_to ], + ...args + }); + + if (!cert) + perror("Failed to generate certificate"); + + cert = cert.pem(); + if (!cert) + perror("Failed to complete certificate"); + + return cert; +} + +function gen_client_cert(ca_file, ca_data, key) { + let ca_base = substr(ca_file, 0, -4); + let ca_info = pk.cert_info(ca_data); + if (!length(ca_info)) + perror("Failed to load CA certificate"); + + let ca_key = pk.load_key(readfile(ca_base + ".key")); + if (!ca_key) + perror("Failed to load CA key"); + let ca_serial = +readfile(ca_base + ".serial"); + if (!ca_serial) + perror("Failed to load CA serial"); + + let cert = gen_cert(key, { + serial: ++ca_serial, + issuer_name: ca_info[0].subject, + issuer_key: ca_key, + }); + writefile(ca_base + ".serial", "" + ca_serial); + + return cert; +} + +let cmds = { + ca: function(args) { + let ca_file = check_pem_path(shift(args)); + let ca_base = substr(ca_file, 0, -4); + + let key = gen_key(); + let ca_cert = gen_cert(key, { + ca: true, + serial: 1, + issuer_name: subject, + issuer_key: key, + key_usage: [ "key_cert_sign" ], + }); + + writefile(ca_file, ca_cert); + writefile(ca_base + ".key", key.pem()); + writefile(ca_base + ".serial", "1"); + }, + + cert: function (args) { + let ca_file = check_pem_path(shift(args)); + let crt_file = check_pem_path(shift(args)); + let crt_base = substr(crt_file, 0, -4); + + let key = gen_key(); + let ca_data = readfile(ca_file); + let cert = gen_client_cert(ca_file, ca_data, key); + + writefile(crt_base + ".key", key.pem()); + writefile(crt_file, cert); + }, + + cert_p12: function (args) { + let ca_file = check_pem_path(shift(args)); + let p12_file = shift(args); + if (!p12_file) + usage(); + + let key = gen_key(); + let ca_data = readfile(ca_file); + let cert = gen_client_cert(ca_file, ca_data, key); + + if (password_stdin) + password = rtrim(stdin.read("line")); + else if (!password) + print((password = hexenc(readfile("/dev/urandom", 8))) + "\n"); + + let p12 = pk.generate_pkcs12({ + password, cert, key, legacy, + extra: no_ca ? null : [ ca_data ], + }); + + writefile(p12_file, p12); + }, + + selfsigned: function(args) { + let crt_file = check_pem_path(shift(args)); + let crt_base = substr(crt_file, 0, -4); + + let key = gen_key(); + let cert = gen_cert(key, { + serial: 1, + issuer_name: subject, + issuer_key: key, + }); + + writefile(crt_base + ".key", key.pem()); + writefile(crt_file, cert); + }, +}; + +while (substr(ARGV[0], 0, 1) == "-") { + let opt = substr(shift(ARGV), 1); + switch (opt) { + case 'C': + keycurve = shift(ARGV); + break; + case 'L': + keylen = +shift(ARGV); + break; + case 'N': + no_ca = true; + break; + case 'p': + password = shift(ARGV); + if (password_stdin) + usage(); + break; + case 'P': + password_stdin = true; + if (password) + usage(); + break; + case 's': + subject = shift(ARGV); + break; + case 't': + keytype = shift(ARGV); + if (keytype != "rsa" && keytype != "ec") { + warn(`Unsupported key type ${keytype}\n`); + exit(1); + } + break; + case 'V': + valid_from = shift(ARGV); + valid_to = shift(ARGV); + break; + case 'W': + legacy = true; + break; + default: + usage(); + break; + } +} + +let cmd = shift(ARGV); +if (!cmd || !cmds[cmd]) + usage(); + +if (subject == null) { + warn(`Missing -s option\n`); + exit(1); +} + +cmds[cmd](ARGV); diff --git a/package/utils/ucode-mod-pkgen/src/CMakeLists.txt b/package/utils/ucode-mod-pkgen/src/CMakeLists.txt new file mode 100644 index 00000000000000..879475516054a9 --- /dev/null +++ b/package/utils/ucode-mod-pkgen/src/CMakeLists.txt @@ -0,0 +1,35 @@ +cmake_minimum_required(VERSION 3.13) + +PROJECT(ucode-pkgen C) +ADD_DEFINITIONS(-Os -ggdb -Wall -Werror --std=gnu99 -ffunction-sections -fwrapv -D_GNU_SOURCE) + +IF(CMAKE_C_COMPILER_VERSION VERSION_GREATER 6) + ADD_DEFINITIONS(-Wextra -Werror=implicit-function-declaration) + ADD_DEFINITIONS(-Wformat -Werror=format-security -Werror=format-nonliteral) +ENDIF() +ADD_DEFINITIONS(-Wmissing-declarations -Wno-error=unused-variable -Wno-unused-parameter) + +IF(APPLE) + SET(UCODE_MODULE_LINK_OPTIONS "LINKER:-undefined,dynamic_lookup") +ELSE() + SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "-Wl,--gc-sections") +ENDIF() + +IF(DEBUG) + ADD_DEFINITIONS(-DDEBUG -g3 -O0) +ELSE() + ADD_DEFINITIONS(-DNDEBUG) +ENDIF() + +FIND_LIBRARY(mbedtls NAMES mbedtls) +FIND_LIBRARY(ucode NAMES ucode) +FIND_PATH(mbedtls_include_dir NAMES mbedtls/pk.h) +FIND_PATH(ucode_include_dir NAMES ucode/module.h) +INCLUDE_DIRECTORIES(${mbedtls_include_dir} ${ucode_include_dir}) + +ADD_LIBRARY(pkgen_lib MODULE ucode.c pkcs12.c) +SET_TARGET_PROPERTIES(pkgen_lib PROPERTIES OUTPUT_NAME pkgen PREFIX "") +TARGET_LINK_OPTIONS(pkgen_lib PRIVATE ${UCODE_MODULE_LINK_OPTIONS}) +TARGET_LINK_LIBRARIES(pkgen_lib ${mbedtls}) + +INSTALL(TARGETS pkgen_lib LIBRARY DESTINATION lib/ucode) diff --git a/package/utils/ucode-mod-pkgen/src/pk.h b/package/utils/ucode-mod-pkgen/src/pk.h new file mode 100644 index 00000000000000..9e2b316b6d49a1 --- /dev/null +++ b/package/utils/ucode-mod-pkgen/src/pk.h @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2024 Felix Fietkau + */ +#ifndef __UCODE_PK_H +#define __UCODE_PK_H + +#include +#include + +#include +#include +#include +#include +#include + +#if MBEDTLS_VERSION_MAJOR < 3 +#define MBEDTLS_LEGACY +#endif + +int random_cb(void *ctx, unsigned char *out, size_t len); +uc_value_t *uc_generate_pkcs12(uc_vm_t *vm, size_t nargs); +int64_t get_int_arg(uc_value_t *obj, const char *key, int64_t defval); +extern int mbedtls_errno; +extern char buf[32 * 1024]; + +#define C(ret) \ + ({ \ + int __ret = (ret); \ + mbedtls_errno = __ret < 0 ? __ret : 0; \ + __ret; \ + }) + +#define CHECK(ret) do { \ + if (C(ret) < 0) \ + return NULL; \ +} while (0) +#define CHECK_INT(ret) do { \ + if (C(ret) < 0) \ + return -1; \ +} while (0) + +#define INVALID_ARG() do { C(-1); return NULL; } while (0) + +#endif diff --git a/package/utils/ucode-mod-pkgen/src/pkcs12.c b/package/utils/ucode-mod-pkgen/src/pkcs12.c new file mode 100644 index 00000000000000..7d23b9d35b7583 --- /dev/null +++ b/package/utils/ucode-mod-pkgen/src/pkcs12.c @@ -0,0 +1,612 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2024 Felix Fietkau + */ +#include "pk.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#define OID_TAG(n) MBEDTLS_OID_##n, MBEDTLS_OID_SIZE(MBEDTLS_OID_##n) + +#ifndef MBEDTLS_OID_AES_256_CBC +#define MBEDTLS_OID_AES_256_CBC MBEDTLS_OID_AES "\x2a" +#endif + +#define MBEDTLS_OID_PKCS9_LOCAL_KEY_ID MBEDTLS_OID_PKCS9 "\x15" +#define MBEDTLS_OID_PKCS9_CERT_TYPE MBEDTLS_OID_PKCS9 "\x16" +#define MBEDTLS_OID_PKCS9_CERT_TYPE_X509 MBEDTLS_OID_PKCS9_CERT_TYPE "\x01" + +#define MBEDTLS_OID_PKCS12_KEY_BAG MBEDTLS_OID_PKCS12 "\x0a\x01\x01" +#define MBEDTLS_OID_PKCS12_SHROUDED_KEY_BAG MBEDTLS_OID_PKCS12 "\x0a\x01\x02" +#define MBEDTLS_OID_PKCS12_CERT_BAG MBEDTLS_OID_PKCS12 "\x0a\x01\x03" + +#ifndef MBEDTLS_OID_PKCS7 +#define MBEDTLS_OID_PKCS7 MBEDTLS_OID_PKCS "\x07" +#define MBEDTLS_OID_PKCS7_DATA MBEDTLS_OID_PKCS7 "\x01" +#define MBEDTLS_OID_PKCS7_ENCRYPTED_DATA MBEDTLS_OID_PKCS7 "\x06" +#endif + +#define NUM_ITER 2048 +#define SALT_LEN 16 +#define IV_LEN 16 +#define IV_LEN_LEGACY 8 +#define KEY_LEN 32 +#define CERT_HASH_LEN 20 + +#define CONTEXT_TAG(n) (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | (n)) +#define SEQUENCE_TAG (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) +#define SET_TAG (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET) + +#define CTX_ADD(ctx, n) \ + do { \ + int __n = (n); \ + if ((ctx)->p - (ctx)->start <= __n) \ + return -1; \ + (ctx)->p -= __n; \ + } while (0) + +struct pkcs12_ctx { + uint8_t *p, *start; + + uint8_t cert_hash[20]; + uint8_t *key_cert_hash; + + uint8_t salt[SALT_LEN]; + uint8_t iv[IV_LEN]; + + const char *password; + uint8_t *pwd; + size_t pwd_len; + + bool legacy; +}; + +#ifdef MBEDTLS_LEGACY +static inline int +mbedtls_pkcs5_pbkdf2_hmac_ext(mbedtls_md_type_t md_alg, const unsigned char *password, + size_t plen, const unsigned char *salt, size_t slen, + unsigned int iteration_count, + uint32_t key_length, unsigned char *output) +{ + mbedtls_md_context_t md_ctx; + const mbedtls_md_info_t *md_info; + int ret; + + md_info = mbedtls_md_info_from_type(md_alg); + if (!md_info) + return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE; + + mbedtls_md_init(&md_ctx); + ret = mbedtls_md_setup(&md_ctx, md_info, 1); + if (ret) + goto out; + + ret = mbedtls_pkcs5_pbkdf2_hmac(&md_ctx, password, plen, salt, slen, + iteration_count, key_length, output); + +out: + mbedtls_md_free(&md_ctx); + return ret; +} +#endif + +static void +uc_p12_add_tag(struct pkcs12_ctx *ctx, uint8_t *end, uint8_t tag) +{ + mbedtls_asn1_write_len(&ctx->p, ctx->start, end - ctx->p); + mbedtls_asn1_write_tag(&ctx->p, ctx->start, tag); +} + +static void +uc_p12_add_sequence(struct pkcs12_ctx *ctx, uint8_t *end) +{ + uc_p12_add_tag(ctx, end, SEQUENCE_TAG); +} + +static void +uc_p12_add_algo(struct pkcs12_ctx *ctx, const char *oid, size_t oid_len, size_t par_len) +{ + mbedtls_asn1_write_algorithm_identifier(&ctx->p, ctx->start, oid, oid_len, par_len); +} + +static void +uc_p12_add_attribute(struct pkcs12_ctx *ctx, uint8_t *end, const char *oid, size_t oid_len) +{ + uc_p12_add_tag(ctx, end, SET_TAG); + mbedtls_asn1_write_oid(&ctx->p, ctx->start, oid, oid_len); + uc_p12_add_sequence(ctx, end); +} + +static void +uc_p12_add_localkeyid(struct pkcs12_ctx *ctx, bool key) +{ + uint8_t *end = ctx->p; + + ctx->p -= CERT_HASH_LEN; + if (key) + ctx->key_cert_hash = ctx->p; + else if (ctx->key_cert_hash) + memcpy(ctx->p, ctx->key_cert_hash, CERT_HASH_LEN); + uc_p12_add_tag(ctx, end, MBEDTLS_ASN1_OCTET_STRING); + uc_p12_add_attribute(ctx, end, OID_TAG(PKCS9_LOCAL_KEY_ID)); +} + +static void +uc_p12_add_bag(struct pkcs12_ctx *ctx, uint8_t *data_end, uint8_t *end, const char *oid, size_t oid_len) +{ + uc_p12_add_tag(ctx, data_end, CONTEXT_TAG(0)); + mbedtls_asn1_write_oid(&ctx->p, ctx->start, oid, oid_len); + uc_p12_add_sequence(ctx, end); +} + +static int +uc_p12_enc_setup(struct pkcs12_ctx *ctx, mbedtls_cipher_context_t *cipher) +{ + const mbedtls_cipher_info_t *cipher_info; + uint8_t key[KEY_LEN]; + int ret; + + random_cb(NULL, ctx->iv, IV_LEN); + ret = mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA256, + (void *)ctx->password, strlen(ctx->password), + ctx->salt, SALT_LEN, NUM_ITER, + KEY_LEN, key); + if (ret < 0) + return ret; + + cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_CBC); + ret = mbedtls_cipher_setup(cipher, cipher_info); + if (ret < 0) + return ret; + + return mbedtls_cipher_setkey(cipher, key, 8 * KEY_LEN, MBEDTLS_ENCRYPT); +} + +static int +uc_p12_enc_legacy(struct pkcs12_ctx *ctx, mbedtls_cipher_context_t *cipher) +{ + const mbedtls_cipher_info_t *cipher_info; + uint8_t key[24]; + int ret; + + ret = mbedtls_pkcs12_derivation(key, sizeof(key), ctx->pwd, ctx->pwd_len, + ctx->salt, SALT_LEN, MBEDTLS_MD_SHA1, + MBEDTLS_PKCS12_DERIVE_KEY, NUM_ITER); + if (ret < 0) + return ret; + + ret = mbedtls_pkcs12_derivation(ctx->iv, IV_LEN_LEGACY, ctx->pwd, ctx->pwd_len, + ctx->salt, SALT_LEN, MBEDTLS_MD_SHA1, + MBEDTLS_PKCS12_DERIVE_IV, NUM_ITER); + if (ret < 0) + return ret; + + cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_DES_EDE3_CBC); + ret = mbedtls_cipher_setup(cipher, cipher_info); + if (ret < 0) + return ret; + + return mbedtls_cipher_setkey(cipher, key, 8 * sizeof(key), MBEDTLS_ENCRYPT); +} + +static int +uc_p12_encrypt(struct pkcs12_ctx *ctx, uint8_t *end) +{ + mbedtls_cipher_context_t cipher; + size_t iv_len = ctx->legacy ? IV_LEN_LEGACY : IV_LEN; + size_t out_len = 0; + int ret; + + random_cb(NULL, ctx->salt, SALT_LEN); + + if (ctx->legacy) + ret = uc_p12_enc_legacy(ctx, &cipher); + else + ret = uc_p12_enc_setup(ctx, &cipher); + if (ret < 0) + goto out; + + ret = mbedtls_cipher_set_padding_mode(&cipher, MBEDTLS_PADDING_PKCS7); + if (ret < 0) + goto out; + + ret = mbedtls_cipher_crypt(&cipher, ctx->iv, iv_len, ctx->p, end - ctx->p, + (void *)buf, &out_len); + + if (ret < 0) + goto out; + + CTX_ADD(ctx, out_len - (end - ctx->p)); + memcpy(ctx->p, buf, out_len); + uc_p12_add_tag(ctx, end, MBEDTLS_ASN1_OCTET_STRING); + +out: + mbedtls_cipher_free(&cipher); + + return ret; +} + +static int +uc_p12_add_enc_params(struct pkcs12_ctx *ctx) +{ + uint8_t *par_end = ctx->p; + uint8_t *kdf_end; + + if (ctx->legacy) { + mbedtls_asn1_write_int(&ctx->p, ctx->start, NUM_ITER); + + CTX_ADD(ctx, SALT_LEN); + memcpy(ctx->p, ctx->salt, SALT_LEN); + uc_p12_add_tag(ctx, ctx->p + SALT_LEN, MBEDTLS_ASN1_OCTET_STRING); + + uc_p12_add_sequence(ctx, par_end); + + uc_p12_add_algo(ctx, OID_TAG(PKCS12_PBE_SHA1_DES3_EDE_CBC), par_end - ctx->p); + } else { + CTX_ADD(ctx, IV_LEN); + memcpy(ctx->p, ctx->iv, IV_LEN); + + uc_p12_add_tag(ctx, par_end, MBEDTLS_ASN1_OCTET_STRING); + uc_p12_add_algo(ctx, OID_TAG(AES_256_CBC), par_end - ctx->p); + + kdf_end = ctx->p; + uc_p12_add_algo(ctx, OID_TAG(HMAC_SHA256), 0); + mbedtls_asn1_write_int(&ctx->p, ctx->start, NUM_ITER); + CTX_ADD(ctx, SALT_LEN); + memcpy(ctx->p, ctx->salt, SALT_LEN); + uc_p12_add_tag(ctx, ctx->p + SALT_LEN, MBEDTLS_ASN1_OCTET_STRING); + uc_p12_add_sequence(ctx, kdf_end); + + uc_p12_add_algo(ctx, OID_TAG(PKCS5_PBKDF2), kdf_end - ctx->p); + uc_p12_add_sequence(ctx, par_end); + + uc_p12_add_algo(ctx, OID_TAG(PKCS5_PBES2), par_end - ctx->p); + } + + return 0; +} + +static int +uc_p12_add_cert(struct pkcs12_ctx *ctx, uc_value_t *arg, bool ca) +{ + const char *str = ucv_string_get(arg), *str_end; + uint8_t *bag_end, *end; + size_t len; + int ret; + +#define START_TAG "-----BEGIN CERTIFICATE-----" +#define END_TAG "-----END CERTIFICATE-----" + + if (!str) + return -1; + + str = strstr(str, START_TAG); + if (!str) + return -1; + + str += sizeof(START_TAG); + str_end = strstr(str, END_TAG); + if (!str_end) + return -1; + + if ((size_t)(str_end - str) > sizeof(buf) / 2) + return -1; + + ret = mbedtls_base64_decode((void *)buf, sizeof(buf) / 2, &len, + (const void *)str, str_end - str); + if (ret) + return ret; + + bag_end = ctx->p; + if (!ca && ctx->key_cert_hash) { + mbedtls_sha1((const void *)buf, len, ctx->key_cert_hash); + uc_p12_add_localkeyid(ctx, false); + uc_p12_add_tag(ctx, bag_end, SET_TAG); + } + + end = ctx->p; + CTX_ADD(ctx, len); + memcpy(ctx->p, buf, len); + uc_p12_add_tag(ctx, end, MBEDTLS_ASN1_OCTET_STRING); + + /* CertBag */ + uc_p12_add_tag(ctx, end, CONTEXT_TAG(0)); + mbedtls_asn1_write_oid(&ctx->p, ctx->start, OID_TAG(PKCS9_CERT_TYPE_X509)); + uc_p12_add_sequence(ctx, end); + + uc_p12_add_bag(ctx, end, bag_end, OID_TAG(PKCS12_CERT_BAG)); + + return 0; +} + +static int +uc_p12_add_key(struct pkcs12_ctx *ctx, uc_value_t *arg) +{ + mbedtls_pk_context *pk = ucv_resource_data(arg, "mbedtls.pk"); + uint8_t *bag_end, *end; + uint8_t *param = NULL; + size_t param_len = 0; + const char *oid; + size_t oid_len = 0; + int ret, len; + + if (!pk) + return -1; + + bag_end = ctx->p; + uc_p12_add_localkeyid(ctx, true); + uc_p12_add_tag(ctx, bag_end, SET_TAG); + + end = ctx->p; + len = mbedtls_pk_write_key_der(pk, (void *)ctx->start, end - ctx->start); + if (len < 0) + return len; + + ctx->p -= len; + + /* Convert EC key contents to PKCS#8 style */ + if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_ECKEY) { + mbedtls_ecp_group_id grp_id; + mbedtls_asn1_buf tag_buf; + uint8_t *pkey_start, *pkey_end; + size_t seq_len, pkey_len, param_tag_len; + uint8_t *p = ctx->p; + uint8_t *_end = end; + uint8_t *_start; + int version; + + ret = mbedtls_asn1_get_tag(&p, end, &seq_len, SEQUENCE_TAG); + if (ret < 0) + return ret; + + _start = p; + _end = p + seq_len; + ret = mbedtls_asn1_get_int(&p, _end, &version); + if (ret < 0) + return ret; + + /* private key */ + ret = mbedtls_asn1_get_tag(&p, _end, &pkey_len, MBEDTLS_ASN1_OCTET_STRING); + if (ret < 0) + return ret; + pkey_start = p; + p += pkey_len; + pkey_end = p; + + /* parameters */ + ret = mbedtls_asn1_get_tag(&p, _end, ¶m_len, CONTEXT_TAG(0)); + if (ret < 0) + return ret; + + param = memcpy(buf, p, param_len); + p += param_len; + + /* overwrite parameters */ + param_tag_len = p - pkey_end; + ctx->p += param_tag_len; + _start += param_tag_len; + memmove(ctx->p, ctx->p - param_tag_len, p - ctx->p); + + /* replace sequence tag */ + ctx->p = _start; + uc_p12_add_sequence(ctx, end); + + /* check for Curve25519 or Curve448 */ + tag_buf = (mbedtls_asn1_buf){ + .p = (uint8_t *)buf, + .len = param_len, + }; + tag_buf.tag = *tag_buf.p; + ret = mbedtls_asn1_get_tag(&tag_buf.p, tag_buf.p + param_len, &tag_buf.len, tag_buf.tag); + if (ret < 0) + return ret; + + oid = MBEDTLS_OID_EC_ALG_UNRESTRICTED; + oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_ALG_UNRESTRICTED); + +#ifdef MBEDTLS_LEGACY + (void)pkey_start; + (void)grp_id; +#else + ret = mbedtls_oid_get_ec_grp_algid(&tag_buf, &grp_id); + if (!ret && (grp_id == MBEDTLS_ECP_DP_CURVE25519 || + grp_id == MBEDTLS_ECP_DP_CURVE448)) { + ctx->p = end - pkey_len; + memmove(ctx->p, pkey_start, pkey_len); + uc_p12_add_tag(ctx, end, MBEDTLS_ASN1_OCTET_STRING); + } +#endif + } else { + mbedtls_oid_get_oid_by_pk_alg(mbedtls_pk_get_type(pk), &oid, &oid_len); + } + + uc_p12_add_tag(ctx, end, MBEDTLS_ASN1_OCTET_STRING); + + /* KeyBag */ + if (param_len) { + CTX_ADD(ctx, param_len); + memcpy(ctx->p, param, param_len); + } + uc_p12_add_algo(ctx, oid, oid_len, param_len); + mbedtls_asn1_write_int(&ctx->p, ctx->start, 0); + uc_p12_add_sequence(ctx, end); + + ret = uc_p12_encrypt(ctx, end); + if (ret < 0) + return ret; + + ret = uc_p12_add_enc_params(ctx); + if (ret < 0) + return ret; + + uc_p12_add_sequence(ctx, end); + + uc_p12_add_bag(ctx, end, bag_end, OID_TAG(PKCS12_SHROUDED_KEY_BAG)); + + return 0; +} + +static int +uc_p12_add_authsafe(struct pkcs12_ctx *ctx, uc_value_t *arg) +{ + uc_value_t *extra; + uint8_t *end = ctx->p; + size_t len; + int ret; + + /* authSafe contents */ + extra = ucv_object_get(arg, "extra", NULL); + if (extra) { + size_t len; + + if (ucv_type(extra) != UC_ARRAY) + return -1; + + len = ucv_array_length(extra); + for (size_t i = 0; i < len; i++) { + ret = uc_p12_add_cert(ctx, ucv_array_get(extra, i), true); + if (ret < 0) + return ret; + } + } + + ret = uc_p12_add_key(ctx, ucv_object_get(arg, "key", NULL)); + if (ret < 0) + return ret; + + ret = uc_p12_add_cert(ctx, ucv_object_get(arg, "cert", NULL), false); + if (ret < 0) + return ret; + + /* encrypted */ + uc_p12_add_sequence(ctx, end); + + ret = uc_p12_encrypt(ctx, end); + if (ret < 0) + return ret; + + uc_p12_add_tag(ctx, end, CONTEXT_TAG(0)); + + ret = uc_p12_add_enc_params(ctx); + if (ret < 0) + return ret; + + mbedtls_asn1_write_oid(&ctx->p, ctx->start, OID_TAG(PKCS7_DATA)); + uc_p12_add_sequence(ctx, end); + + mbedtls_asn1_write_int(&ctx->p, ctx->start, 0); + uc_p12_add_sequence(ctx, end); + uc_p12_add_tag(ctx, end, CONTEXT_TAG(0)); + mbedtls_asn1_write_oid(&ctx->p, ctx->start, OID_TAG(PKCS7_ENCRYPTED_DATA)); + uc_p12_add_sequence(ctx, end); + + /* authSafe contents */ + uc_p12_add_sequence(ctx, end); + + /* authSafe header */ + len = end - ctx->p; + uc_p12_add_tag(ctx, end, MBEDTLS_ASN1_OCTET_STRING); + uc_p12_add_tag(ctx, end, CONTEXT_TAG(0)); + mbedtls_asn1_write_oid(&ctx->p, ctx->start, OID_TAG(PKCS7_DATA)); + uc_p12_add_sequence(ctx, end); + + return len; +} + +static void * +uc_p12_add_mac_digest_info(struct pkcs12_ctx *ctx) +{ + uint8_t *end = ctx->p; + size_t len = 20; + + ctx->p -= len; + uc_p12_add_tag(ctx, end, MBEDTLS_ASN1_OCTET_STRING); + uc_p12_add_algo(ctx, OID_TAG(DIGEST_ALG_SHA1), 0); + uc_p12_add_sequence(ctx, end); + + return end - len; +} + +uc_value_t *uc_generate_pkcs12(uc_vm_t *vm, size_t nargs) +{ + uc_value_t *arg = uc_fn_arg(0), *pwd_arg; + mbedtls_md_context_t hmac; + uint8_t *end = (uint8_t *)&buf[sizeof(buf)]; + struct pkcs12_ctx ctx = { + .start = (uint8_t *)&buf[sizeof(buf) / 2], + .p = end, + }; + uint8_t *hash, *data; + uint8_t key[20], *salt; + size_t salt_len = 8; + int data_len; + uc_value_t *ret = NULL; + const char *passwd; + + if (ucv_type(arg) != UC_OBJECT) + INVALID_ARG(); + + ctx.legacy = ucv_is_truish(ucv_object_get(arg, "legacy", NULL)); + + mbedtls_md_init(&hmac); + pwd_arg = ucv_object_get(arg, "password", NULL); + passwd = ucv_string_get(pwd_arg); + if (!passwd) + INVALID_ARG(); + + /* password is expected to be a UTF-16 string */ + ctx.password = passwd; + ctx.pwd_len = 2 * strlen(passwd) + 2; + ctx.pwd = malloc(ctx.pwd_len); + for (size_t i = 0; i < ctx.pwd_len; i += 2) { + ctx.pwd[i] = 0; + ctx.pwd[i + 1] = passwd[i / 2]; + } + + /* MacData */ + mbedtls_asn1_write_int(&ctx.p, ctx.start, NUM_ITER); + + ctx.p -= salt_len; + salt = ctx.p; + random_cb(NULL, salt, salt_len); + uc_p12_add_tag(&ctx, salt + salt_len, MBEDTLS_ASN1_OCTET_STRING); + + hash = uc_p12_add_mac_digest_info(&ctx); + uc_p12_add_sequence(&ctx, end); + + data = ctx.p; + data_len = uc_p12_add_authsafe(&ctx, arg); + if (C(data_len) < 0) + goto out; + data -= data_len; + + mbedtls_asn1_write_int(&ctx.p, ctx.start, 3); + uc_p12_add_sequence(&ctx, end); + + if (C(mbedtls_pkcs12_derivation(key, sizeof(key), ctx.pwd, ctx.pwd_len, + salt, salt_len, MBEDTLS_MD_SHA1, + MBEDTLS_PKCS12_DERIVE_MAC_KEY, NUM_ITER))) + goto out; + + if (C(mbedtls_md_setup(&hmac, mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), 1))) + goto out; + if (C(mbedtls_md_hmac_starts(&hmac, key, sizeof(key)))) + goto out; + if (C(mbedtls_md_hmac_update(&hmac, data, data_len))) + goto out; + if (C(mbedtls_md_hmac_finish(&hmac, hash))) + goto out; + + ret = ucv_string_new_length((char *)ctx.p, end - ctx.p); + +out: + free(ctx.pwd); + mbedtls_md_free(&hmac); + return ret; +} diff --git a/package/utils/ucode-mod-pkgen/src/ucode.c b/package/utils/ucode-mod-pkgen/src/ucode.c new file mode 100644 index 00000000000000..cb5569b977c9bb --- /dev/null +++ b/package/utils/ucode-mod-pkgen/src/ucode.c @@ -0,0 +1,598 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2024 Felix Fietkau + */ +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "pk.h" + +/* mbedtls < 3.x compat */ +#ifdef MBEDTLS_LEGACY +#define mbedtls_pk_parse_key(pk, key, keylen, passwd, passwdlen, random, random_ctx) \ + mbedtls_pk_parse_key(pk, key, keylen, passwd, passwdlen) +#endif + +static uc_resource_type_t *uc_pk_type, *uc_crt_type; +static uc_value_t *registry; +char buf[32 * 1024]; +int mbedtls_errno; + +struct uc_cert_wr { + mbedtls_x509write_cert crt; /* must be first */ + mbedtls_mpi mpi; + unsigned int reg; +}; + +static unsigned int uc_reg_add(uc_value_t *val) +{ + size_t i = 0; + + while (ucv_array_get(registry, i)) + i++; + + ucv_array_set(registry, i, ucv_get(val)); + + return i; +} + +int random_cb(void *ctx, unsigned char *out, size_t len) +{ +#ifdef linux + if (getrandom(out, len, 0) != (ssize_t) len) + return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; +#else + static FILE *f; + + if (!f) + f = fopen("/dev/urandom", "r"); + if (fread(out, len, 1, f) != 1) + return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; +#endif + + return 0; +} + +int64_t get_int_arg(uc_value_t *obj, const char *key, int64_t defval) +{ + uc_value_t *uval = ucv_object_get(obj, key, NULL); + int64_t val; + + if (!uval) + return defval; + + val = ucv_int64_get(uval); + if (errno || val < 0 || val > INT_MAX) + return INT_MIN; + + return val ? val : defval; +} + +static int +gen_rsa_key(mbedtls_pk_context *pk, uc_value_t *arg) +{ + int64_t key_size, exp; + + key_size = get_int_arg(arg, "size", 2048); + exp = get_int_arg(arg, "exponent", 65537); + if (key_size < 0 || exp < 0) + return -1; + + return mbedtls_rsa_gen_key(mbedtls_pk_rsa(*pk), random_cb, NULL, key_size, exp); +} + +static int +gen_ec_key(mbedtls_pk_context *pk, uc_value_t *arg) +{ + mbedtls_ecp_group_id curve; + const char *c_name; + uc_value_t *c_arg; + + c_arg = ucv_object_get(arg, "curve", NULL); + if (c_arg && ucv_type(c_arg) != UC_STRING) + return -1; + + c_name = ucv_string_get(c_arg); + if (!c_name) + curve = MBEDTLS_ECP_DP_SECP256R1; + else { + const mbedtls_ecp_curve_info *curve_info; + curve_info = mbedtls_ecp_curve_info_from_name(c_name); + if (!curve_info) + return MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE; + + curve = curve_info->grp_id; + } + + return mbedtls_ecp_gen_key(curve, mbedtls_pk_ec(*pk), random_cb, NULL); +} + +static void free_pk(void *pk) +{ + if (!pk) + return; + + mbedtls_pk_free(pk); + free(pk); +} + +static void free_crt(void *ptr) +{ + struct uc_cert_wr *crt = ptr; + + if (!crt) + return; + + mbedtls_x509write_crt_free(&crt->crt); + mbedtls_mpi_free(&crt->mpi); + ucv_array_set(registry, crt->reg, NULL); + free(crt); +} + +static uc_value_t * +uc_generate_key(uc_vm_t *vm, size_t nargs) +{ + uc_value_t *cur, *arg = uc_fn_arg(0); + mbedtls_pk_type_t pk_type; + mbedtls_pk_context *pk; + const char *type; + int ret; + + if (ucv_type(arg) != UC_OBJECT) + INVALID_ARG(); + + cur = ucv_object_get(arg, "type", NULL); + type = ucv_string_get(cur); + if (!type) + INVALID_ARG(); + + if (!strcmp(type, "rsa")) + pk_type = MBEDTLS_PK_RSA; + else if (!strcmp(type, "ec")) + pk_type = MBEDTLS_PK_ECKEY; + else + INVALID_ARG(); + + pk = calloc(1, sizeof(*pk)); + mbedtls_pk_init(pk); + mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(pk_type)); + switch (pk_type) { + case MBEDTLS_PK_RSA: + ret = C(gen_rsa_key(pk, arg)); + break; + case MBEDTLS_PK_ECKEY: + ret = C(gen_ec_key(pk, arg)); + break; + default: + ret = -1; + } + + if (ret) { + free_pk(pk); + return NULL; + } + + return uc_resource_new(uc_pk_type, pk); +} + +static uc_value_t * +uc_load_key(uc_vm_t *vm, size_t nargs) +{ + uc_value_t *keystr = uc_fn_arg(0); + uc_value_t *pub = uc_fn_arg(1); + uc_value_t *passwd = uc_fn_arg(2); + mbedtls_pk_context *pk; + int ret; + + if (ucv_type(keystr) != UC_STRING || + (pub && ucv_type(pub) != UC_BOOLEAN) || + (passwd && ucv_type(passwd) != UC_STRING)) + INVALID_ARG(); + + pk = calloc(1, sizeof(*pk)); + mbedtls_pk_init(pk); + if (ucv_is_truish(pub)) + ret = C(mbedtls_pk_parse_public_key(pk, (const uint8_t *)ucv_string_get(keystr), + ucv_string_length(keystr) + 1)); + else + ret = C(mbedtls_pk_parse_key(pk, (const uint8_t *)ucv_string_get(keystr), + ucv_string_length(keystr) + 1, + (const uint8_t *)ucv_string_get(passwd), + ucv_string_length(passwd) + 1, + random_cb, NULL)); + if (ret) { + free_pk(pk); + return NULL; + } + + return uc_resource_new(uc_pk_type, pk); +} + +static void +uc_cert_info_add(uc_value_t *info, const char *name, int len) +{ + uc_value_t *val; + + if (len < 0) + return; + + val = ucv_string_new_length(buf, len); + ucv_object_add(info, name, ucv_get(val)); +} + +static void +uc_cert_info_add_name(uc_value_t *info, const char *name, mbedtls_x509_name *dn) +{ + int len; + + len = mbedtls_x509_dn_gets(buf, sizeof(buf), dn); + uc_cert_info_add(info, name, len); +} + +static void +uc_cert_info_add_time(uc_value_t *info, const char *name, mbedtls_x509_time *t) +{ + int len; + + len = snprintf(buf, sizeof(buf), "%04d%02d%02d%02d%02d%02d", + t->year, t->mon, t->day, t->hour, t->min, t->sec); + uc_cert_info_add(info, name, len); +} + +static uc_value_t * +uc_cert_info(uc_vm_t *vm, size_t nargs) +{ + uc_value_t *arg = uc_fn_arg(0); + mbedtls_x509_crt crt, *cur; + uc_value_t *ret = NULL; + + if (ucv_type(arg) != UC_STRING) + return NULL; + + mbedtls_x509_crt_init(&crt); + if (C(mbedtls_x509_crt_parse(&crt, (const void *)ucv_string_get(arg), ucv_string_length(arg) + 1)) < 0) + goto out; + + ret = ucv_array_new(vm); + for (cur = &crt; cur && cur->version != 0; cur = cur->next) { + uc_value_t *info = ucv_object_new(vm); + int len; + + ucv_array_push(ret, ucv_get(info)); + ucv_object_add(info, "version", ucv_int64_new(cur->version)); + + uc_cert_info_add_name(info, "issuer", &cur->issuer); + uc_cert_info_add_name(info, "subject", &cur->issuer); + uc_cert_info_add_time(info, "valid_from", &cur->valid_from); + uc_cert_info_add_time(info, "valid_to", &cur->valid_to); + + len = mbedtls_x509_serial_gets(buf, sizeof(buf), &cur->serial); + uc_cert_info_add(info, "serial", len); + } + +out: + mbedtls_x509_crt_free(&crt); + return ret; +} + +static uc_value_t * +uc_pk_pem(uc_vm_t *vm, size_t nargs) +{ + mbedtls_pk_context *pk = uc_fn_thisval("mbedtls.pk"); + uc_value_t *pub = uc_fn_arg(0); + + if (!pk) + return NULL; + + if (ucv_is_truish(pub)) + CHECK(mbedtls_pk_write_pubkey_pem(pk, (void *)buf, sizeof(buf))); + else + CHECK(mbedtls_pk_write_key_pem(pk, (void *)buf, sizeof(buf))); + + return ucv_string_new(buf); +} + +static uc_value_t * +uc_pk_der(uc_vm_t *vm, size_t nargs) +{ + mbedtls_pk_context *pk = uc_fn_thisval("mbedtls.pk"); + uc_value_t *pub = uc_fn_arg(0); + int len; + + if (!pk) + return NULL; + + if (ucv_is_truish(pub)) + len = mbedtls_pk_write_pubkey_der(pk, (void *)buf, sizeof(buf)); + else + len = mbedtls_pk_write_key_der(pk, (void *)buf, sizeof(buf)); + if (len < 0) + CHECK(len); + + return ucv_string_new_length(buf + sizeof(buf) - len, len); +} + +static uc_value_t * +uc_crt_pem(uc_vm_t *vm, size_t nargs) +{ + mbedtls_x509write_cert *crt = uc_fn_thisval("mbedtls.crt"); + if (!crt) + return NULL; + + CHECK(mbedtls_x509write_crt_pem(crt, (void *)buf, sizeof(buf), random_cb, NULL)); + + return ucv_string_new(buf); +} + +static uc_value_t * +uc_crt_der(uc_vm_t *vm, size_t nargs) +{ + mbedtls_x509write_cert *crt = uc_fn_thisval("mbedtls.crt"); + int len; + + if (!crt) + return NULL; + + len = mbedtls_x509write_crt_der(crt, (void *)buf, sizeof(buf), random_cb, NULL); + if (len < 0) + CHECK(len); + + return ucv_string_new_length(buf, len); +} + +static int +uc_cert_set_validity(mbedtls_x509write_cert *crt, uc_value_t *arg) +{ + uc_value_t *from = ucv_array_get(arg, 0); + uc_value_t *to = ucv_array_get(arg, 1); + + if (ucv_type(from) != UC_STRING || ucv_type(to) != UC_STRING) + return -1; + + return mbedtls_x509write_crt_set_validity(crt, ucv_string_get(from), ucv_string_get(to)); +} + +static int +uc_cert_init(mbedtls_x509write_cert *crt, mbedtls_mpi *mpi, uc_value_t *reg, uc_value_t *arg) +{ + uc_value_t *cur; + int64_t serial; + int path_len; + int version; + bool ca; + + mbedtls_mpi_init(mpi); + mbedtls_x509write_crt_init(crt); + mbedtls_x509write_crt_set_md_alg(crt, MBEDTLS_MD_SHA256); + + ca = ucv_is_truish(ucv_object_get(arg, "ca", NULL)); + path_len = get_int_arg(arg, "max_pathlen", ca ? -1 : 0); + if (path_len < -1) + return -1; + + version = get_int_arg(arg, "version", 3); + if (version < 0 || version > 3) + return -1; + + serial = get_int_arg(arg, "serial", 1); + if (serial < 0) + return -1; + + mbedtls_mpi_lset(mpi, serial); + mbedtls_x509write_crt_set_serial(crt, mpi); + mbedtls_x509write_crt_set_version(crt, version - 1); + CHECK_INT(mbedtls_x509write_crt_set_basic_constraints(crt, ca, path_len)); + + cur = ucv_object_get(arg, "subject_name", NULL); + if (ucv_type(cur) == UC_STRING) + CHECK_INT(mbedtls_x509write_crt_set_subject_name(crt, ucv_string_get(cur))); + else + return -1; + cur = ucv_object_get(arg, "subject_key", NULL); + if (cur) { + mbedtls_pk_context *key = ucv_resource_data(cur, "mbedtls.pk"); + if (!key) + return -1; + + ucv_array_set(reg, 0, ucv_get(cur)); + mbedtls_x509write_crt_set_subject_key(crt, key); + mbedtls_x509write_crt_set_subject_key_identifier(crt); + } else + return -1; + + cur = ucv_object_get(arg, "issuer_name", NULL); + if (ucv_type(cur) == UC_STRING) + CHECK_INT(mbedtls_x509write_crt_set_issuer_name(crt, ucv_string_get(cur))); + else + return -1; + cur = ucv_object_get(arg, "issuer_key", NULL); + if (cur) { + mbedtls_pk_context *key = ucv_resource_data(cur, "mbedtls.pk"); + if (!key) + return -1; + + ucv_array_set(reg, 1, ucv_get(cur)); + mbedtls_x509write_crt_set_issuer_key(crt, key); + mbedtls_x509write_crt_set_authority_key_identifier(crt); + } else + return -1; + + cur = ucv_object_get(arg, "validity", NULL); + if (ucv_type(cur) != UC_ARRAY || ucv_array_length(cur) != 2) + return -1; + if (uc_cert_set_validity(crt, cur)) + return -1; + + cur = ucv_object_get(arg, "key_usage", NULL); + if (ucv_type(cur) == UC_ARRAY) { + static const struct { + const char *name; + uint8_t val; + } key_flags[] = { + { "digital_signature", MBEDTLS_X509_KU_DIGITAL_SIGNATURE }, + { "non_repudiation", MBEDTLS_X509_KU_NON_REPUDIATION }, + { "key_encipherment", MBEDTLS_X509_KU_KEY_ENCIPHERMENT }, + { "data_encipherment", MBEDTLS_X509_KU_DATA_ENCIPHERMENT }, + { "key_agreement", MBEDTLS_X509_KU_KEY_AGREEMENT }, + { "key_cert_sign", MBEDTLS_X509_KU_KEY_CERT_SIGN }, + { "crl_sign", MBEDTLS_X509_KU_CRL_SIGN }, + }; + uint8_t key_usage = 0; + size_t len = ucv_array_length(cur); + + for (size_t i = 0; i < len; i++) { + uc_value_t *val = ucv_array_get(cur, i); + const char *str; + size_t k; + + str = ucv_string_get(val); + if (!str) + return -1; + + for (k = 0; k < ARRAY_SIZE(key_flags); k++) + if (!strcmp(str, key_flags[k].name)) + break; + if (k == ARRAY_SIZE(key_flags)) + return -1; + + key_usage |= key_flags[k].val; + } + CHECK_INT(mbedtls_x509write_crt_set_key_usage(crt, key_usage)); + } else if (cur) + return -1; + +#ifndef MBEDTLS_LEGACY + cur = ucv_object_get(arg, "ext_key_usage", NULL); + if (ucv_type(cur) == UC_ARRAY && ucv_array_length(cur)) { + static const struct { + const char *name; + struct mbedtls_asn1_buf val; + } key_flags[] = { +#define __oid(name, val) \ + { \ + name, \ + { \ + .tag = MBEDTLS_ASN1_OID, \ + .len = sizeof(MBEDTLS_OID_##val), \ + .p = (uint8_t *)MBEDTLS_OID_##val, \ + } \ + } + __oid("server_auth", SERVER_AUTH), + __oid("client_auth", CLIENT_AUTH), + __oid("code_signing", CODE_SIGNING), + __oid("email_protection", EMAIL_PROTECTION), + __oid("time_stamping", TIME_STAMPING), + __oid("ocsp_signing", OCSP_SIGNING), + __oid("any", ANY_EXTENDED_KEY_USAGE) + }; + struct mbedtls_asn1_sequence *elem; + size_t len = ucv_array_length(cur); + + elem = calloc(len, sizeof(*elem)); + for (size_t i = 0; i < len; i++) { + uc_value_t *val = ucv_array_get(cur, i); + const char *str; + size_t k; + + str = ucv_string_get(val); + if (!str) + return -1; + + for (k = 0; k < ARRAY_SIZE(key_flags); k++) + if (!strcmp(str, key_flags[k].name)) + break; + + if (k == ARRAY_SIZE(key_flags)) { + free(elem); + return -1; + } + elem[i].buf = key_flags[k].val; + if (i + 1 < len) + elem[i].next = &elem[i + 1]; + } + + CHECK_INT(mbedtls_x509write_crt_set_ext_key_usage(crt, elem)); + } else if (cur) + return -1; +#endif + + return 0; +} + +static uc_value_t * +uc_generate_cert(uc_vm_t *vm, size_t nargs) +{ + struct uc_cert_wr *crt; + uc_value_t *arg = uc_fn_arg(0); + uc_value_t *reg; + + if (ucv_type(arg) != UC_OBJECT) + return NULL; + + reg = ucv_array_new(vm); + crt = calloc(1, sizeof(*crt)); + if (C(uc_cert_init(&crt->crt, &crt->mpi, reg, arg))) { + free(crt); + return NULL; + } + + crt->reg = uc_reg_add(reg); + + return uc_resource_new(uc_crt_type, crt); +} + +static uc_value_t * +uc_mbedtls_error(uc_vm_t *vm, size_t nargs) +{ + mbedtls_strerror(mbedtls_errno, buf, sizeof(buf)); + + return ucv_string_new(buf); +} + +static uc_value_t * +uc_mbedtls_errno(uc_vm_t *vm, size_t nargs) +{ + return ucv_int64_new(mbedtls_errno); +} + + +static const uc_function_list_t pk_fns[] = { + { "pem", uc_pk_pem }, + { "der", uc_pk_der }, +}; + +static const uc_function_list_t crt_fns[] = { + { "pem", uc_crt_pem }, + { "der", uc_crt_der }, +}; + +static const uc_function_list_t global_fns[] = { + { "load_key", uc_load_key }, + { "cert_info", uc_cert_info }, + { "generate_key", uc_generate_key }, + { "generate_cert", uc_generate_cert }, + { "generate_pkcs12", uc_generate_pkcs12 }, + { "errno", uc_mbedtls_errno }, + { "error", uc_mbedtls_error }, +}; + +void uc_module_init(uc_vm_t *vm, uc_value_t *scope) +{ + uc_pk_type = uc_type_declare(vm, "mbedtls.pk", pk_fns, free_pk); + uc_crt_type = uc_type_declare(vm, "mbedtls.crt", crt_fns, free_crt); + uc_function_list_register(scope, global_fns); + + registry = ucv_array_new(vm); + uc_vm_registry_set(vm, "pkgen.registry", registry); +} diff --git a/rules.mk b/rules.mk index 16d6020e1a0efe..dbc448e1a432c9 100644 --- a/rules.mk +++ b/rules.mk @@ -96,7 +96,7 @@ TARGET_SUFFIX=$(call qstrip,$(CONFIG_TARGET_SUFFIX)) BUILD_SUFFIX:=$(call qstrip,$(CONFIG_BUILD_SUFFIX)) SUBDIR:=$(patsubst $(TOPDIR)/%,%,${CURDIR}) BUILD_SUBDIR:=$(patsubst $(TOPDIR)/%,%,${CURDIR}) -NPROC:=$(shell sysctl -n hw.ncpu 2>/dev/null || nproc) +NPROC=$(shell sysctl -n hw.ncpu 2>/dev/null || nproc) export SHELL:=/usr/bin/env bash IS_PACKAGE_BUILD := $(if $(filter package/%,$(BUILD_SUBDIR)),1) diff --git a/target/linux/armsr/README b/target/linux/armsr/README index b4b9012826a2ca..04f01f8e305228 100644 --- a/target/linux/armsr/README +++ b/target/linux/armsr/README @@ -49,7 +49,7 @@ With a EDKII or U-Boot binary for the QEMU ARM virtual machines, you can use the images in EFI mode: 32-bit: -gunzip -c bin/targets/armsr/armv7/openwrt-armsr-armv7-generic-ext4-combined.img.gz > openwrt-arm-32.img +gunzip -c bin/targets/armsr/armv7/openwrt-armsr-armv7-generic-ext4-combined-efi.img.gz > openwrt-arm-32.img qemu-system-arm -nographic \ -cpu cortex-a15 -machine virt \ -bios bin/targets/armsr/armv7/u-boot-qemu_armv7/u-boot.bin \ @@ -60,7 +60,7 @@ qemu-system-arm -nographic \ -netdev user,id=testwan -net nic,netdev=testwan 64-bit: -gunzip -c bin/targets/armsr/armv8/openwrt-armsr-armv8-generic-ext4-combined.img.gz > openwrt-arm-64.img +gunzip -c bin/targets/armsr/armv8/openwrt-armsr-armv8-generic-ext4-combined-efi.img.gz > openwrt-arm-64.img qemu-system-aarch64 -nographic \ -cpu cortex-a53 -machine virt \ -bios bin/targets/armsr/armv8/u-boot-qemu_armv8/u-boot.bin \ diff --git a/target/linux/armsr/image/Makefile b/target/linux/armsr/image/Makefile index 09c37beeec43ec..b34c1f16e79844 100644 --- a/target/linux/armsr/image/Makefile +++ b/target/linux/armsr/image/Makefile @@ -74,18 +74,18 @@ DEVICE_VARS += GRUB2_VARIANT UBOOT define Device/efi-default IMAGE/rootfs.img := append-rootfs | pad-to $(ROOTFS_PARTSIZE) IMAGE/rootfs.img.gz := append-rootfs | pad-to $(ROOTFS_PARTSIZE) | gzip - IMAGE/combined.img := grub-config efi | combined efi | grub-install efi | append-metadata - IMAGE/combined.img.gz := grub-config efi | combined efi | grub-install efi | gzip | append-metadata - IMAGE/combined.vmdk := grub-config efi | combined efi | grub-install efi | qemu-image vmdk + IMAGE/combined-efi.img := grub-config efi | combined efi | grub-install efi | append-metadata + IMAGE/combined-efi.img.gz := grub-config efi | combined efi | grub-install efi | gzip | append-metadata + IMAGE/combined-efi.vmdk := grub-config efi | combined efi | grub-install efi | qemu-image vmdk ifeq ($(CONFIG_TARGET_IMAGES_GZIP),y) IMAGES-y := rootfs.img.gz - IMAGES-y += combined.img.gz + IMAGES-y += combined-efi.img.gz else IMAGES-y := rootfs.img - IMAGES-y += combined.img + IMAGES-y += combined-efi.img endif ifeq ($(CONFIG_VMDK_IMAGES),y) - IMAGES-y += combined.vmdk + IMAGES-y += combined-efi.vmdk endif KERNEL := kernel-bin KERNEL_INSTALL := 1 diff --git a/target/linux/d1/base-files/etc/board.d/02_network b/target/linux/d1/base-files/etc/board.d/02_network index df48b431af5e2c..dc61e4bde51460 100644 --- a/target/linux/d1/base-files/etc/board.d/02_network +++ b/target/linux/d1/base-files/etc/board.d/02_network @@ -8,6 +8,10 @@ board_config_update case "$(board_name)" in +sipeed,lichee-rv-dock |\ +widora,mangopi-mq-pro) + ucidef_set_interface_lan "wlan0" + ;; *) ucidef_set_interface_lan 'eth0' ;; diff --git a/target/linux/d1/image/Makefile b/target/linux/d1/image/Makefile index 8dca2fb1cb0ee0..ea41e65c760e09 100644 --- a/target/linux/d1/image/Makefile +++ b/target/linux/d1/image/Makefile @@ -65,7 +65,7 @@ define Device/sipeed_lichee-rv-dock DEVICE_MODEL := LicheePi RV (dock) DEVICE_DTS := allwinner/sun20i-d1-lichee-rv-dock SUPPORTED_DEVICES += lichee_rv_dock - DEVICE_PACKAGES += kmod-rtl8723bs + DEVICE_PACKAGES += kmod-rtw88-8723ds wpad-basic-mbedtls UBOOT := lichee_rv_dock endef TARGET_DEVICES += sipeed_lichee-rv-dock @@ -76,7 +76,7 @@ define Device/widora_mangopi-mq-pro DEVICE_MODEL := MQ Pro DEVICE_DTS := allwinner/sun20i-d1-mangopi-mq-pro SUPPORTED_DEVICES += mangopi_mq_pro - DEVICE_PACKAGES += kmod-rtl8723bs + DEVICE_PACKAGES += kmod-rtw88-8723ds wpad-basic-mbedtls UBOOT := mangopi_mq_pro endef TARGET_DEVICES += widora_mangopi-mq-pro diff --git a/target/linux/generic/backport-6.6/780-24-v6.13-r8169-add-support-for-the-temperature-sensor-being-a.patch b/target/linux/generic/backport-6.6/780-24-v6.13-r8169-add-support-for-the-temperature-sensor-being-a.patch deleted file mode 100644 index 2403da5d55519f..00000000000000 --- a/target/linux/generic/backport-6.6/780-24-v6.13-r8169-add-support-for-the-temperature-sensor-being-a.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 1ffcc8d41306fd2e5f140b276820714a26a11cc4 Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Mon, 7 Oct 2024 20:34:12 +0200 -Subject: [PATCH] r8169: add support for the temperature sensor being available - from RTL8125B - -This adds support for the temperature sensor being available from -RTL8125B. Register information was taken from r8125 vendor driver. - -Signed-off-by: Heiner Kallweit -Reviewed-by: Simon Horman -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/realtek/r8169_main.c | 44 +++++++++++++++++++++++ - 1 file changed, 44 insertions(+) - ---- a/drivers/net/ethernet/realtek/r8169_main.c -+++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -16,6 +16,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -5373,6 +5374,43 @@ static bool rtl_aspm_is_safe(struct rtl8 - return false; - } - -+static umode_t r8169_hwmon_is_visible(const void *drvdata, -+ enum hwmon_sensor_types type, -+ u32 attr, int channel) -+{ -+ return 0444; -+} -+ -+static int r8169_hwmon_read(struct device *dev, enum hwmon_sensor_types type, -+ u32 attr, int channel, long *val) -+{ -+ struct rtl8169_private *tp = dev_get_drvdata(dev); -+ int val_raw; -+ -+ val_raw = phy_read_paged(tp->phydev, 0xbd8, 0x12) & 0x3ff; -+ if (val_raw >= 512) -+ val_raw -= 1024; -+ -+ *val = 1000 * val_raw / 2; -+ -+ return 0; -+} -+ -+static const struct hwmon_ops r8169_hwmon_ops = { -+ .is_visible = r8169_hwmon_is_visible, -+ .read = r8169_hwmon_read, -+}; -+ -+static const struct hwmon_channel_info * const r8169_hwmon_info[] = { -+ HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT), -+ NULL -+}; -+ -+static const struct hwmon_chip_info r8169_hwmon_chip_info = { -+ .ops = &r8169_hwmon_ops, -+ .info = r8169_hwmon_info, -+}; -+ - static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) - { - struct rtl8169_private *tp; -@@ -5547,6 +5585,12 @@ static int rtl_init_one(struct pci_dev * - if (rc) - return rc; - -+ /* The temperature sensor is available from RTl8125B */ -+ if (IS_REACHABLE(CONFIG_HWMON) && tp->mac_version >= RTL_GIGA_MAC_VER_63) -+ /* ignore errors */ -+ devm_hwmon_device_register_with_info(&pdev->dev, "nic_temp", tp, -+ &r8169_hwmon_chip_info, -+ NULL); - rc = register_netdev(dev); - if (rc) - return rc; diff --git a/target/linux/generic/backport-6.6/780-25-v6.13-r8169-remove-original-workaround-for-RTL8125-broken-.patch b/target/linux/generic/backport-6.6/780-25-v6.13-r8169-remove-original-workaround-for-RTL8125-broken-.patch index 8c6e6d8dc41bb8..dbf66bb81e8a2c 100644 --- a/target/linux/generic/backport-6.6/780-25-v6.13-r8169-remove-original-workaround-for-RTL8125-broken-.patch +++ b/target/linux/generic/backport-6.6/780-25-v6.13-r8169-remove-original-workaround-for-RTL8125-broken-.patch @@ -19,7 +19,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -4779,11 +4779,7 @@ static void r8169_phylink_handler(struct +@@ -4778,11 +4778,7 @@ static void r8169_phylink_handler(struct if (netif_carrier_ok(ndev)) { rtl_link_chg_patch(tp); pm_request_resume(d); diff --git a/target/linux/generic/backport-6.6/780-26-v6.13-r8169-enable-SG-TSO-on-selected-chip-versions-per-de.patch b/target/linux/generic/backport-6.6/780-26-v6.13-r8169-enable-SG-TSO-on-selected-chip-versions-per-de.patch index dc05299628eda5..4b00eba62239e7 100644 --- a/target/linux/generic/backport-6.6/780-26-v6.13-r8169-enable-SG-TSO-on-selected-chip-versions-per-de.patch +++ b/target/linux/generic/backport-6.6/780-26-v6.13-r8169-enable-SG-TSO-on-selected-chip-versions-per-de.patch @@ -20,7 +20,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -5529,11 +5529,6 @@ static int rtl_init_one(struct pci_dev * +@@ -5491,11 +5491,6 @@ static int rtl_init_one(struct pci_dev * dev->features |= dev->hw_features; @@ -32,7 +32,7 @@ Signed-off-by: David S. Miller if (rtl_chip_supports_csum_v2(tp)) { dev->hw_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6; netif_set_tso_max_size(dev, RTL_GSO_MAX_SIZE_V2); -@@ -5544,6 +5539,17 @@ static int rtl_init_one(struct pci_dev * +@@ -5506,6 +5501,17 @@ static int rtl_init_one(struct pci_dev * netif_set_tso_max_segs(dev, RTL_GSO_MAX_SEGS_V1); } diff --git a/target/linux/generic/backport-6.6/780-27-v6.13-r8169-implement-additional-ethtool-stats-ops.patch b/target/linux/generic/backport-6.6/780-27-v6.13-r8169-implement-additional-ethtool-stats-ops.patch index faab0df7f400e2..29c8527b1cb95d 100644 --- a/target/linux/generic/backport-6.6/780-27-v6.13-r8169-implement-additional-ethtool-stats-ops.patch +++ b/target/linux/generic/backport-6.6/780-27-v6.13-r8169-implement-additional-ethtool-stats-ops.patch @@ -16,7 +16,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -2162,6 +2162,19 @@ static void rtl8169_get_ringparam(struct +@@ -2161,6 +2161,19 @@ static void rtl8169_get_ringparam(struct data->tx_pending = NUM_TX_DESC; } @@ -36,7 +36,7 @@ Signed-off-by: Jakub Kicinski static void rtl8169_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *data) { -@@ -2188,6 +2201,69 @@ static int rtl8169_set_pauseparam(struct +@@ -2187,6 +2200,69 @@ static int rtl8169_set_pauseparam(struct return 0; } @@ -106,7 +106,7 @@ Signed-off-by: Jakub Kicinski static const struct ethtool_ops rtl8169_ethtool_ops = { .supported_coalesce_params = ETHTOOL_COALESCE_USECS | ETHTOOL_COALESCE_MAX_FRAMES, -@@ -2209,8 +2285,11 @@ static const struct ethtool_ops rtl8169_ +@@ -2208,8 +2284,11 @@ static const struct ethtool_ops rtl8169_ .get_link_ksettings = phy_ethtool_get_link_ksettings, .set_link_ksettings = phy_ethtool_set_link_ksettings, .get_ringparam = rtl8169_get_ringparam, @@ -118,7 +118,7 @@ Signed-off-by: Jakub Kicinski }; static enum mac_version rtl8169_get_mac_version(u16 xid, bool gmii) -@@ -3895,6 +3974,9 @@ static void rtl_hw_start_8125(struct rtl +@@ -3894,6 +3973,9 @@ static void rtl_hw_start_8125(struct rtl break; } diff --git a/target/linux/generic/backport-6.6/780-28-v6.13-r8169-don-t-take-RTNL-lock-in-rtl_task.patch b/target/linux/generic/backport-6.6/780-28-v6.13-r8169-don-t-take-RTNL-lock-in-rtl_task.patch index 38b5035441f039..3e495e19defbdd 100644 --- a/target/linux/generic/backport-6.6/780-28-v6.13-r8169-don-t-take-RTNL-lock-in-rtl_task.patch +++ b/target/linux/generic/backport-6.6/780-28-v6.13-r8169-don-t-take-RTNL-lock-in-rtl_task.patch @@ -18,7 +18,7 @@ Signed-off-by: Andrew Lunn --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -4802,10 +4802,8 @@ static void rtl_task(struct work_struct +@@ -4801,10 +4801,8 @@ static void rtl_task(struct work_struct container_of(work, struct rtl8169_private, wk.work); int ret; @@ -30,7 +30,7 @@ Signed-off-by: Andrew Lunn if (test_and_clear_bit(RTL_FLAG_TASK_TX_TIMEOUT, tp->wk.flags)) { /* if chip isn't accessible, reset bus to revive it */ -@@ -4814,7 +4812,7 @@ static void rtl_task(struct work_struct +@@ -4813,7 +4811,7 @@ static void rtl_task(struct work_struct if (ret < 0) { netdev_err(tp->dev, "Can't reset secondary PCI bus, detach NIC\n"); netif_device_detach(tp->dev); @@ -39,7 +39,7 @@ Signed-off-by: Andrew Lunn } } -@@ -4833,8 +4831,6 @@ reset: +@@ -4832,8 +4830,6 @@ reset: } else if (test_and_clear_bit(RTL_FLAG_TASK_RESET_NO_QUEUE_WAKE, tp->wk.flags)) { rtl_reset_work(tp); } diff --git a/target/linux/generic/backport-6.6/780-31-v6.13-r8169-remove-rtl_dash_loop_wait_high-low.patch b/target/linux/generic/backport-6.6/780-31-v6.13-r8169-remove-rtl_dash_loop_wait_high-low.patch index 4792e371b6316b..0c0e80c92dc197 100644 --- a/target/linux/generic/backport-6.6/780-31-v6.13-r8169-remove-rtl_dash_loop_wait_high-low.patch +++ b/target/linux/generic/backport-6.6/780-31-v6.13-r8169-remove-rtl_dash_loop_wait_high-low.patch @@ -15,7 +15,7 @@ Signed-off-by: Andrew Lunn --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -1347,40 +1347,19 @@ static void rtl8168ep_stop_cmac(struct r +@@ -1346,40 +1346,19 @@ static void rtl8168ep_stop_cmac(struct r RTL_W8(tp, IBCR0, RTL_R8(tp, IBCR0) & ~0x01); } @@ -60,7 +60,7 @@ Signed-off-by: Andrew Lunn } static void rtl8168_driver_start(struct rtl8169_private *tp) -@@ -1394,7 +1373,8 @@ static void rtl8168_driver_start(struct +@@ -1393,7 +1372,8 @@ static void rtl8168_driver_start(struct static void rtl8168dp_driver_stop(struct rtl8169_private *tp) { r8168dp_oob_notify(tp, OOB_CMD_DRIVER_STOP); @@ -70,7 +70,7 @@ Signed-off-by: Andrew Lunn } static void rtl8168ep_driver_stop(struct rtl8169_private *tp) -@@ -1402,7 +1382,8 @@ static void rtl8168ep_driver_stop(struct +@@ -1401,7 +1381,8 @@ static void rtl8168ep_driver_stop(struct rtl8168ep_stop_cmac(tp); r8168ep_ocp_write(tp, 0x01, 0x180, OOB_CMD_DRIVER_STOP); r8168ep_ocp_write(tp, 0x01, 0x30, r8168ep_ocp_read(tp, 0x30) | 0x01); diff --git a/target/linux/generic/backport-6.6/780-33-v6.13-r8169-add-support-for-RTL8125D.patch b/target/linux/generic/backport-6.6/780-33-v6.13-r8169-add-support-for-RTL8125D.patch index 81058e5e9f7641..687ed445dafb0e 100644 --- a/target/linux/generic/backport-6.6/780-33-v6.13-r8169-add-support-for-RTL8125D.patch +++ b/target/linux/generic/backport-6.6/780-33-v6.13-r8169-add-support-for-RTL8125D.patch @@ -29,7 +29,7 @@ Signed-off-by: Jakub Kicinski RTL_GIGA_MAC_NONE --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -56,6 +56,7 @@ +@@ -55,6 +55,7 @@ #define FIRMWARE_8107E_2 "rtl_nic/rtl8107e-2.fw" #define FIRMWARE_8125A_3 "rtl_nic/rtl8125a-3.fw" #define FIRMWARE_8125B_2 "rtl_nic/rtl8125b-2.fw" @@ -37,7 +37,7 @@ Signed-off-by: Jakub Kicinski #define FIRMWARE_8126A_2 "rtl_nic/rtl8126a-2.fw" #define FIRMWARE_8126A_3 "rtl_nic/rtl8126a-3.fw" -@@ -139,6 +140,7 @@ static const struct { +@@ -138,6 +139,7 @@ static const struct { [RTL_GIGA_MAC_VER_61] = {"RTL8125A", FIRMWARE_8125A_3}, /* reserve 62 for CFG_METHOD_4 in the vendor driver */ [RTL_GIGA_MAC_VER_63] = {"RTL8125B", FIRMWARE_8125B_2}, @@ -45,7 +45,7 @@ Signed-off-by: Jakub Kicinski [RTL_GIGA_MAC_VER_65] = {"RTL8126A", FIRMWARE_8126A_2}, [RTL_GIGA_MAC_VER_66] = {"RTL8126A", FIRMWARE_8126A_3}, }; -@@ -708,6 +710,7 @@ MODULE_FIRMWARE(FIRMWARE_8168FP_3); +@@ -707,6 +709,7 @@ MODULE_FIRMWARE(FIRMWARE_8168FP_3); MODULE_FIRMWARE(FIRMWARE_8107E_2); MODULE_FIRMWARE(FIRMWARE_8125A_3); MODULE_FIRMWARE(FIRMWARE_8125B_2); @@ -53,7 +53,7 @@ Signed-off-by: Jakub Kicinski MODULE_FIRMWARE(FIRMWARE_8126A_2); MODULE_FIRMWARE(FIRMWARE_8126A_3); -@@ -2080,10 +2083,7 @@ static void rtl_set_eee_txidle_timer(str +@@ -2079,10 +2082,7 @@ static void rtl_set_eee_txidle_timer(str tp->tx_lpi_timer = timer_val; r8168_mac_ocp_write(tp, 0xe048, timer_val); break; @@ -65,7 +65,7 @@ Signed-off-by: Jakub Kicinski tp->tx_lpi_timer = timer_val; RTL_W16(tp, EEE_TXIDLE_TIMER_8125, timer_val); break; -@@ -2295,6 +2295,9 @@ static enum mac_version rtl8169_get_mac_ +@@ -2294,6 +2294,9 @@ static enum mac_version rtl8169_get_mac_ { 0x7cf, 0x64a, RTL_GIGA_MAC_VER_66 }, { 0x7cf, 0x649, RTL_GIGA_MAC_VER_65 }, @@ -75,7 +75,7 @@ Signed-off-by: Jakub Kicinski /* 8125B family. */ { 0x7cf, 0x641, RTL_GIGA_MAC_VER_63 }, -@@ -2562,9 +2565,7 @@ static void rtl_init_rxcfg(struct rtl816 +@@ -2561,9 +2564,7 @@ static void rtl_init_rxcfg(struct rtl816 case RTL_GIGA_MAC_VER_61: RTL_W32(tp, RxConfig, RX_FETCH_DFLT_8125 | RX_DMA_BURST); break; @@ -86,7 +86,7 @@ Signed-off-by: Jakub Kicinski RTL_W32(tp, RxConfig, RX_FETCH_DFLT_8125 | RX_DMA_BURST | RX_PAUSE_SLOT_ON); break; -@@ -3876,6 +3877,12 @@ static void rtl_hw_start_8125b(struct rt +@@ -3875,6 +3876,12 @@ static void rtl_hw_start_8125b(struct rt rtl_hw_start_8125_common(tp); } @@ -99,7 +99,7 @@ Signed-off-by: Jakub Kicinski static void rtl_hw_start_8126a(struct rtl8169_private *tp) { rtl_set_def_aspm_entry_latency(tp); -@@ -3924,6 +3931,7 @@ static void rtl_hw_config(struct rtl8169 +@@ -3923,6 +3930,7 @@ static void rtl_hw_config(struct rtl8169 [RTL_GIGA_MAC_VER_53] = rtl_hw_start_8117, [RTL_GIGA_MAC_VER_61] = rtl_hw_start_8125a_2, [RTL_GIGA_MAC_VER_63] = rtl_hw_start_8125b, @@ -107,7 +107,7 @@ Signed-off-by: Jakub Kicinski [RTL_GIGA_MAC_VER_65] = rtl_hw_start_8126a, [RTL_GIGA_MAC_VER_66] = rtl_hw_start_8126a, }; -@@ -3941,6 +3949,7 @@ static void rtl_hw_start_8125(struct rtl +@@ -3940,6 +3948,7 @@ static void rtl_hw_start_8125(struct rtl /* disable interrupt coalescing */ switch (tp->mac_version) { case RTL_GIGA_MAC_VER_61: diff --git a/target/linux/generic/backport-6.6/780-34-v6.13-r8169-fix-inconsistent-indenting-in-rtl8169_get_eth_.patch b/target/linux/generic/backport-6.6/780-34-v6.13-r8169-fix-inconsistent-indenting-in-rtl8169_get_eth_.patch index 721e51ebf056e9..2f65f066af1287 100644 --- a/target/linux/generic/backport-6.6/780-34-v6.13-r8169-fix-inconsistent-indenting-in-rtl8169_get_eth_.patch +++ b/target/linux/generic/backport-6.6/780-34-v6.13-r8169-fix-inconsistent-indenting-in-rtl8169_get_eth_.patch @@ -19,7 +19,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -2227,7 +2227,7 @@ static void rtl8169_get_eth_mac_stats(st +@@ -2226,7 +2226,7 @@ static void rtl8169_get_eth_mac_stats(st le64_to_cpu(tp->counters->tx_broadcast64); mac_stats->MulticastFramesReceivedOK = le64_to_cpu(tp->counters->rx_multicast64); diff --git a/target/linux/generic/backport-6.6/780-38-v6.13-r8169-improve-initialization-of-RSS-registers-on-RTL.patch b/target/linux/generic/backport-6.6/780-38-v6.13-r8169-improve-initialization-of-RSS-registers-on-RTL.patch index 8cb79c82cf3a37..c2f6d755a5cb21 100644 --- a/target/linux/generic/backport-6.6/780-38-v6.13-r8169-improve-initialization-of-RSS-registers-on-RTL.patch +++ b/target/linux/generic/backport-6.6/780-38-v6.13-r8169-improve-initialization-of-RSS-registers-on-RTL.patch @@ -16,7 +16,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -347,6 +347,8 @@ enum rtl8125_registers { +@@ -346,6 +346,8 @@ enum rtl8125_registers { TxPoll_8125 = 0x90, LEDSEL3 = 0x96, MAC0_BKP = 0x19e0, @@ -25,7 +25,7 @@ Signed-off-by: Jakub Kicinski EEE_TXIDLE_TIMER_8125 = 0x6048, }; -@@ -3770,8 +3772,8 @@ static void rtl_hw_start_8125_common(str +@@ -3769,8 +3771,8 @@ static void rtl_hw_start_8125_common(str rtl_pcie_state_l2l3_disable(tp); RTL_W16(tp, 0x382, 0x221b); diff --git a/target/linux/generic/backport-6.6/780-39-v6.13-r8169-remove-leftover-locks-after-reverted-change.patch b/target/linux/generic/backport-6.6/780-39-v6.13-r8169-remove-leftover-locks-after-reverted-change.patch index 20c42955e36d46..c3e93989016214 100644 --- a/target/linux/generic/backport-6.6/780-39-v6.13-r8169-remove-leftover-locks-after-reverted-change.patch +++ b/target/linux/generic/backport-6.6/780-39-v6.13-r8169-remove-leftover-locks-after-reverted-change.patch @@ -15,7 +15,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -663,13 +663,9 @@ struct rtl8169_private { +@@ -662,13 +662,9 @@ struct rtl8169_private { struct work_struct work; } wk; @@ -29,7 +29,7 @@ Signed-off-by: Jakub Kicinski unsigned supports_gmii:1; unsigned aspm_manageable:1; unsigned dash_enabled:1; -@@ -723,22 +719,12 @@ static inline struct device *tp_to_dev(s +@@ -722,22 +718,12 @@ static inline struct device *tp_to_dev(s static void rtl_lock_config_regs(struct rtl8169_private *tp) { @@ -54,7 +54,7 @@ Signed-off-by: Jakub Kicinski } static void rtl_pci_commit(struct rtl8169_private *tp) -@@ -749,24 +735,18 @@ static void rtl_pci_commit(struct rtl816 +@@ -748,24 +734,18 @@ static void rtl_pci_commit(struct rtl816 static void rtl_mod_config2(struct rtl8169_private *tp, u8 clear, u8 set) { @@ -79,7 +79,7 @@ Signed-off-by: Jakub Kicinski } static bool rtl_is_8125(struct rtl8169_private *tp) -@@ -1572,7 +1552,6 @@ static void __rtl8169_set_wol(struct rtl +@@ -1571,7 +1551,6 @@ static void __rtl8169_set_wol(struct rtl { WAKE_MAGIC, Config3, MagicPacket } }; unsigned int i, tmp = ARRAY_SIZE(cfg); @@ -87,7 +87,7 @@ Signed-off-by: Jakub Kicinski u8 options; rtl_unlock_config_regs(tp); -@@ -1591,14 +1570,12 @@ static void __rtl8169_set_wol(struct rtl +@@ -1590,14 +1569,12 @@ static void __rtl8169_set_wol(struct rtl r8168_mac_ocp_modify(tp, 0xc0b6, BIT(0), 0); } @@ -102,7 +102,7 @@ Signed-off-by: Jakub Kicinski switch (tp->mac_version) { case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06: -@@ -5498,8 +5475,6 @@ static int rtl_init_one(struct pci_dev * +@@ -5460,8 +5437,6 @@ static int rtl_init_one(struct pci_dev * tp->supports_gmii = ent->driver_data == RTL_CFG_NO_GBIT ? 0 : 1; tp->ocp_base = OCP_STD_PHY_BASE; diff --git a/target/linux/generic/backport-6.6/780-40-v6.13-r8169-improve-__rtl8169_set_wol.patch b/target/linux/generic/backport-6.6/780-40-v6.13-r8169-improve-__rtl8169_set_wol.patch index 8c88c078f29f57..e468d637c93815 100644 --- a/target/linux/generic/backport-6.6/780-40-v6.13-r8169-improve-__rtl8169_set_wol.patch +++ b/target/linux/generic/backport-6.6/780-40-v6.13-r8169-improve-__rtl8169_set_wol.patch @@ -16,7 +16,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -749,6 +749,20 @@ static void rtl_mod_config5(struct rtl81 +@@ -748,6 +748,20 @@ static void rtl_mod_config5(struct rtl81 RTL_W8(tp, Config5, (val & ~clear) | set); } @@ -37,7 +37,7 @@ Signed-off-by: Jakub Kicinski static bool rtl_is_8125(struct rtl8169_private *tp) { return tp->mac_version >= RTL_GIGA_MAC_VER_61; -@@ -1539,58 +1553,37 @@ static void rtl8169_get_wol(struct net_d +@@ -1538,58 +1552,37 @@ static void rtl8169_get_wol(struct net_d static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts) { diff --git a/target/linux/generic/backport-6.6/780-41-v6.13-r8169-improve-rtl_set_d3_pll_down.patch b/target/linux/generic/backport-6.6/780-41-v6.13-r8169-improve-rtl_set_d3_pll_down.patch index e7626173102023..aeafebb2140500 100644 --- a/target/linux/generic/backport-6.6/780-41-v6.13-r8169-improve-rtl_set_d3_pll_down.patch +++ b/target/linux/generic/backport-6.6/780-41-v6.13-r8169-improve-rtl_set_d3_pll_down.patch @@ -17,7 +17,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -1432,19 +1432,11 @@ static enum rtl_dash_type rtl_get_dash_t +@@ -1431,19 +1431,11 @@ static enum rtl_dash_type rtl_get_dash_t static void rtl_set_d3_pll_down(struct rtl8169_private *tp, bool enable) { diff --git a/target/linux/generic/backport-6.6/780-42-v6.13-r8169-align-WAKE_PHY-handling-with-r8125-r8126-vendo.patch b/target/linux/generic/backport-6.6/780-42-v6.13-r8169-align-WAKE_PHY-handling-with-r8125-r8126-vendo.patch index de86c2f6cd064e..26c362dd6ca260 100644 --- a/target/linux/generic/backport-6.6/780-42-v6.13-r8169-align-WAKE_PHY-handling-with-r8125-r8126-vendo.patch +++ b/target/linux/generic/backport-6.6/780-42-v6.13-r8169-align-WAKE_PHY-handling-with-r8125-r8126-vendo.patch @@ -17,7 +17,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -1563,6 +1563,9 @@ static void __rtl8169_set_wol(struct rtl +@@ -1562,6 +1562,9 @@ static void __rtl8169_set_wol(struct rtl } r8169_mod_reg8_cond(tp, Config3, LinkUp, wolopts & WAKE_PHY); diff --git a/target/linux/generic/backport-6.6/780-43-v6.13-r8169-use-helper-r8169_mod_reg8_cond-to-simplify-rtl.patch b/target/linux/generic/backport-6.6/780-43-v6.13-r8169-use-helper-r8169_mod_reg8_cond-to-simplify-rtl.patch index 5bcf06098a88ee..bdeb46eeb85146 100644 --- a/target/linux/generic/backport-6.6/780-43-v6.13-r8169-use-helper-r8169_mod_reg8_cond-to-simplify-rtl.patch +++ b/target/linux/generic/backport-6.6/780-43-v6.13-r8169-use-helper-r8169_mod_reg8_cond-to-simplify-rtl.patch @@ -17,7 +17,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c -@@ -2547,86 +2547,31 @@ static void rtl8169_init_ring_indexes(st +@@ -2546,86 +2546,31 @@ static void rtl8169_init_ring_indexes(st tp->dirty_tx = tp->cur_tx = tp->cur_rx = 0; } diff --git a/target/linux/generic/backport-6.6/781-20-v6.14-net-phy-realtek-add-support-for-reading-MDIO_MMD_VEN.patch b/target/linux/generic/backport-6.6/781-20-v6.14-net-phy-realtek-add-support-for-reading-MDIO_MMD_VEN.patch new file mode 100644 index 00000000000000..2add672f441a9d --- /dev/null +++ b/target/linux/generic/backport-6.6/781-20-v6.14-net-phy-realtek-add-support-for-reading-MDIO_MMD_VEN.patch @@ -0,0 +1,47 @@ +From 3d483a10327f38595f714f9f9e9dde43a622cb0f Mon Sep 17 00:00:00 2001 +From: Heiner Kallweit +Date: Sat, 11 Jan 2025 21:49:31 +0100 +Subject: [PATCH] net: phy: realtek: add support for reading MDIO_MMD_VEND2 + regs on RTL8125/RTL8126 + +RTL8125/RTL8126 don't support MMD access to the internal PHY, but +provide a mechanism to access at least all MDIO_MMD_VEND2 registers. +By exposing this mechanism standard MMD access functions can be used +to access the MDIO_MMD_VEND2 registers. + +Signed-off-by: Heiner Kallweit +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/e821b302-5fe6-49ab-aabd-05da500581c0@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/realtek.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -736,7 +736,11 @@ static int rtlgen_read_mmd(struct phy_de + { + int ret; + +- if (devnum == MDIO_MMD_PCS && regnum == MDIO_PCS_EEE_ABLE) { ++ if (devnum == MDIO_MMD_VEND2) { ++ rtl821x_write_page(phydev, regnum >> 4); ++ ret = __phy_read(phydev, 0x10 + ((regnum & 0xf) >> 1)); ++ rtl821x_write_page(phydev, 0); ++ } else if (devnum == MDIO_MMD_PCS && regnum == MDIO_PCS_EEE_ABLE) { + rtl821x_write_page(phydev, 0xa5c); + ret = __phy_read(phydev, 0x12); + rtl821x_write_page(phydev, 0); +@@ -760,7 +764,11 @@ static int rtlgen_write_mmd(struct phy_d + { + int ret; + +- if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) { ++ if (devnum == MDIO_MMD_VEND2) { ++ rtl821x_write_page(phydev, regnum >> 4); ++ ret = __phy_write(phydev, 0x10 + ((regnum & 0xf) >> 1), val); ++ rtl821x_write_page(phydev, 0); ++ } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) { + rtl821x_write_page(phydev, 0xa5d); + ret = __phy_write(phydev, 0x10, val); + rtl821x_write_page(phydev, 0); diff --git a/target/linux/generic/backport-6.6/781-21-v6.14-net-phy-move-realtek-PHY-driver-to-its-own-subdirect.patch b/target/linux/generic/backport-6.6/781-21-v6.14-net-phy-move-realtek-PHY-driver-to-its-own-subdirect.patch new file mode 100644 index 00000000000000..b410ab8a32bcc0 --- /dev/null +++ b/target/linux/generic/backport-6.6/781-21-v6.14-net-phy-move-realtek-PHY-driver-to-its-own-subdirect.patch @@ -0,0 +1,3249 @@ +From 1416a9b2ba710d31954131c06d46f298e340aa2c Mon Sep 17 00:00:00 2001 +From: Heiner Kallweit +Date: Sat, 11 Jan 2025 21:50:19 +0100 +Subject: [PATCH] net: phy: move realtek PHY driver to its own subdirectory + +In preparation of adding a source file with hwmon support, move the +Realtek PHY driver to its own subdirectory and rename realtek.c to +realtek_main.c. + +Signed-off-by: Heiner Kallweit +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/c566551b-c915-4e34-9b33-129a6ddd6e4c@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/Kconfig | 5 +---- + drivers/net/phy/Makefile | 2 +- + drivers/net/phy/realtek/Kconfig | 5 +++++ + drivers/net/phy/realtek/Makefile | 3 +++ + drivers/net/phy/{realtek.c => realtek/realtek_main.c} | 0 + 5 files changed, 10 insertions(+), 5 deletions(-) + create mode 100644 drivers/net/phy/realtek/Kconfig + create mode 100644 drivers/net/phy/realtek/Makefile + rename drivers/net/phy/{realtek.c => realtek/realtek_main.c} (100%) + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -325,10 +325,7 @@ config QSEMI_PHY + help + Currently supports the qs6612 + +-config REALTEK_PHY +- tristate "Realtek PHYs" +- help +- Supports the Realtek 821x PHY. ++source "drivers/net/phy/realtek/Kconfig" + + config RENESAS_PHY + tristate "Renesas PHYs" +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -83,7 +83,7 @@ obj-$(CONFIG_NXP_CBTX_PHY) += nxp-cbtx.o + obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o + obj-y += qcom/ + obj-$(CONFIG_QSEMI_PHY) += qsemi.o +-obj-$(CONFIG_REALTEK_PHY) += realtek.o ++obj-$(CONFIG_REALTEK_PHY) += realtek/ + obj-$(CONFIG_RENESAS_PHY) += uPD60620.o + obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o + obj-$(CONFIG_SMSC_PHY) += smsc.o +--- /dev/null ++++ b/drivers/net/phy/realtek/Kconfig +@@ -0,0 +1,5 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++config REALTEK_PHY ++ tristate "Realtek PHYs" ++ help ++ Currently supports RTL821x/RTL822x and fast ethernet PHYs +--- /dev/null ++++ b/drivers/net/phy/realtek/Makefile +@@ -0,0 +1,3 @@ ++# SPDX-License-Identifier: GPL-2.0 ++realtek-y += realtek_main.o ++obj-$(CONFIG_REALTEK_PHY) += realtek.o +--- a/drivers/net/phy/realtek.c ++++ /dev/null +@@ -1,1590 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0+ +-/* drivers/net/phy/realtek.c +- * +- * Driver for Realtek PHYs +- * +- * Author: Johnson Leung +- * +- * Copyright (c) 2004 Freescale Semiconductor, Inc. +- */ +-#include +-#include +-#include +-#include +-#include +-#include +- +-#define RTL821x_PHYSR 0x11 +-#define RTL821x_PHYSR_DUPLEX BIT(13) +-#define RTL821x_PHYSR_SPEED GENMASK(15, 14) +- +-#define RTL821x_INER 0x12 +-#define RTL8211B_INER_INIT 0x6400 +-#define RTL8211E_INER_LINK_STATUS BIT(10) +-#define RTL8211F_INER_LINK_STATUS BIT(4) +- +-#define RTL821x_INSR 0x13 +- +-#define RTL821x_EXT_PAGE_SELECT 0x1e +-#define RTL821x_PAGE_SELECT 0x1f +- +-#define RTL8211F_PHYCR1 0x18 +-#define RTL8211F_PHYCR2 0x19 +-#define RTL8211F_INSR 0x1d +- +-#define RTL8211F_LEDCR 0x10 +-#define RTL8211F_LEDCR_MODE BIT(15) +-#define RTL8211F_LEDCR_ACT_TXRX BIT(4) +-#define RTL8211F_LEDCR_LINK_1000 BIT(3) +-#define RTL8211F_LEDCR_LINK_100 BIT(1) +-#define RTL8211F_LEDCR_LINK_10 BIT(0) +-#define RTL8211F_LEDCR_MASK GENMASK(4, 0) +-#define RTL8211F_LEDCR_SHIFT 5 +- +-#define RTL8211F_TX_DELAY BIT(8) +-#define RTL8211F_RX_DELAY BIT(3) +- +-#define RTL8211F_ALDPS_PLL_OFF BIT(1) +-#define RTL8211F_ALDPS_ENABLE BIT(2) +-#define RTL8211F_ALDPS_XTAL_OFF BIT(12) +- +-#define RTL8211E_CTRL_DELAY BIT(13) +-#define RTL8211E_TX_DELAY BIT(12) +-#define RTL8211E_RX_DELAY BIT(11) +- +-#define RTL8211F_CLKOUT_EN BIT(0) +- +-#define RTL8201F_ISR 0x1e +-#define RTL8201F_ISR_ANERR BIT(15) +-#define RTL8201F_ISR_DUPLEX BIT(13) +-#define RTL8201F_ISR_LINK BIT(11) +-#define RTL8201F_ISR_MASK (RTL8201F_ISR_ANERR | \ +- RTL8201F_ISR_DUPLEX | \ +- RTL8201F_ISR_LINK) +-#define RTL8201F_IER 0x13 +- +-#define RTL822X_VND1_SERDES_OPTION 0x697a +-#define RTL822X_VND1_SERDES_OPTION_MODE_MASK GENMASK(5, 0) +-#define RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX_SGMII 0 +-#define RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX 2 +- +-#define RTL822X_VND1_SERDES_CTRL3 0x7580 +-#define RTL822X_VND1_SERDES_CTRL3_MODE_MASK GENMASK(5, 0) +-#define RTL822X_VND1_SERDES_CTRL3_MODE_SGMII 0x02 +-#define RTL822X_VND1_SERDES_CTRL3_MODE_2500BASEX 0x16 +- +-/* RTL822X_VND2_XXXXX registers are only accessible when phydev->is_c45 +- * is set, they cannot be accessed by C45-over-C22. +- */ +-#define RTL822X_VND2_GBCR 0xa412 +- +-#define RTL822X_VND2_GANLPAR 0xa414 +- +-#define RTL8366RB_POWER_SAVE 0x15 +-#define RTL8366RB_POWER_SAVE_ON BIT(12) +- +-#define RTL9000A_GINMR 0x14 +-#define RTL9000A_GINMR_LINK_STATUS BIT(4) +- +-#define RTL_VND2_PHYSR 0xa434 +-#define RTL_VND2_PHYSR_DUPLEX BIT(3) +-#define RTL_VND2_PHYSR_SPEEDL GENMASK(5, 4) +-#define RTL_VND2_PHYSR_SPEEDH GENMASK(10, 9) +-#define RTL_VND2_PHYSR_MASTER BIT(11) +-#define RTL_VND2_PHYSR_SPEED_MASK (RTL_VND2_PHYSR_SPEEDL | RTL_VND2_PHYSR_SPEEDH) +- +-#define RTL_GENERIC_PHYID 0x001cc800 +-#define RTL_8211FVD_PHYID 0x001cc878 +-#define RTL_8221B 0x001cc840 +-#define RTL_8221B_VB_CG 0x001cc849 +-#define RTL_8221B_VN_CG 0x001cc84a +-#define RTL_8251B 0x001cc862 +- +-#define RTL8211F_LED_COUNT 3 +- +-MODULE_DESCRIPTION("Realtek PHY driver"); +-MODULE_AUTHOR("Johnson Leung"); +-MODULE_LICENSE("GPL"); +- +-struct rtl821x_priv { +- u16 phycr1; +- u16 phycr2; +- bool has_phycr2; +- struct clk *clk; +-}; +- +-static int rtl821x_read_page(struct phy_device *phydev) +-{ +- return __phy_read(phydev, RTL821x_PAGE_SELECT); +-} +- +-static int rtl821x_write_page(struct phy_device *phydev, int page) +-{ +- return __phy_write(phydev, RTL821x_PAGE_SELECT, page); +-} +- +-static int rtl821x_probe(struct phy_device *phydev) +-{ +- struct device *dev = &phydev->mdio.dev; +- struct rtl821x_priv *priv; +- u32 phy_id = phydev->drv->phy_id; +- int ret; +- +- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); +- if (!priv) +- return -ENOMEM; +- +- priv->clk = devm_clk_get_optional_enabled(dev, NULL); +- if (IS_ERR(priv->clk)) +- return dev_err_probe(dev, PTR_ERR(priv->clk), +- "failed to get phy clock\n"); +- +- ret = phy_read_paged(phydev, 0xa43, RTL8211F_PHYCR1); +- if (ret < 0) +- return ret; +- +- priv->phycr1 = ret & (RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF); +- if (of_property_read_bool(dev->of_node, "realtek,aldps-enable")) +- priv->phycr1 |= RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF; +- +- priv->has_phycr2 = !(phy_id == RTL_8211FVD_PHYID); +- if (priv->has_phycr2) { +- ret = phy_read_paged(phydev, 0xa43, RTL8211F_PHYCR2); +- if (ret < 0) +- return ret; +- +- priv->phycr2 = ret & RTL8211F_CLKOUT_EN; +- if (of_property_read_bool(dev->of_node, "realtek,clkout-disable")) +- priv->phycr2 &= ~RTL8211F_CLKOUT_EN; +- } +- +- phydev->priv = priv; +- +- return 0; +-} +- +-static int rtl8201_ack_interrupt(struct phy_device *phydev) +-{ +- int err; +- +- err = phy_read(phydev, RTL8201F_ISR); +- +- return (err < 0) ? err : 0; +-} +- +-static int rtl821x_ack_interrupt(struct phy_device *phydev) +-{ +- int err; +- +- err = phy_read(phydev, RTL821x_INSR); +- +- return (err < 0) ? err : 0; +-} +- +-static int rtl8211f_ack_interrupt(struct phy_device *phydev) +-{ +- int err; +- +- err = phy_read_paged(phydev, 0xa43, RTL8211F_INSR); +- +- return (err < 0) ? err : 0; +-} +- +-static int rtl8201_config_intr(struct phy_device *phydev) +-{ +- u16 val; +- int err; +- +- if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { +- err = rtl8201_ack_interrupt(phydev); +- if (err) +- return err; +- +- val = BIT(13) | BIT(12) | BIT(11); +- err = phy_write_paged(phydev, 0x7, RTL8201F_IER, val); +- } else { +- val = 0; +- err = phy_write_paged(phydev, 0x7, RTL8201F_IER, val); +- if (err) +- return err; +- +- err = rtl8201_ack_interrupt(phydev); +- } +- +- return err; +-} +- +-static int rtl8211b_config_intr(struct phy_device *phydev) +-{ +- int err; +- +- if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { +- err = rtl821x_ack_interrupt(phydev); +- if (err) +- return err; +- +- err = phy_write(phydev, RTL821x_INER, +- RTL8211B_INER_INIT); +- } else { +- err = phy_write(phydev, RTL821x_INER, 0); +- if (err) +- return err; +- +- err = rtl821x_ack_interrupt(phydev); +- } +- +- return err; +-} +- +-static int rtl8211e_config_intr(struct phy_device *phydev) +-{ +- int err; +- +- if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { +- err = rtl821x_ack_interrupt(phydev); +- if (err) +- return err; +- +- err = phy_write(phydev, RTL821x_INER, +- RTL8211E_INER_LINK_STATUS); +- } else { +- err = phy_write(phydev, RTL821x_INER, 0); +- if (err) +- return err; +- +- err = rtl821x_ack_interrupt(phydev); +- } +- +- return err; +-} +- +-static int rtl8211f_config_intr(struct phy_device *phydev) +-{ +- u16 val; +- int err; +- +- if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { +- err = rtl8211f_ack_interrupt(phydev); +- if (err) +- return err; +- +- val = RTL8211F_INER_LINK_STATUS; +- err = phy_write_paged(phydev, 0xa42, RTL821x_INER, val); +- } else { +- val = 0; +- err = phy_write_paged(phydev, 0xa42, RTL821x_INER, val); +- if (err) +- return err; +- +- err = rtl8211f_ack_interrupt(phydev); +- } +- +- return err; +-} +- +-static irqreturn_t rtl8201_handle_interrupt(struct phy_device *phydev) +-{ +- int irq_status; +- +- irq_status = phy_read(phydev, RTL8201F_ISR); +- if (irq_status < 0) { +- phy_error(phydev); +- return IRQ_NONE; +- } +- +- if (!(irq_status & RTL8201F_ISR_MASK)) +- return IRQ_NONE; +- +- phy_trigger_machine(phydev); +- +- return IRQ_HANDLED; +-} +- +-static irqreturn_t rtl821x_handle_interrupt(struct phy_device *phydev) +-{ +- int irq_status, irq_enabled; +- +- irq_status = phy_read(phydev, RTL821x_INSR); +- if (irq_status < 0) { +- phy_error(phydev); +- return IRQ_NONE; +- } +- +- irq_enabled = phy_read(phydev, RTL821x_INER); +- if (irq_enabled < 0) { +- phy_error(phydev); +- return IRQ_NONE; +- } +- +- if (!(irq_status & irq_enabled)) +- return IRQ_NONE; +- +- phy_trigger_machine(phydev); +- +- return IRQ_HANDLED; +-} +- +-static irqreturn_t rtl8211f_handle_interrupt(struct phy_device *phydev) +-{ +- int irq_status; +- +- irq_status = phy_read_paged(phydev, 0xa43, RTL8211F_INSR); +- if (irq_status < 0) { +- phy_error(phydev); +- return IRQ_NONE; +- } +- +- if (!(irq_status & RTL8211F_INER_LINK_STATUS)) +- return IRQ_NONE; +- +- phy_trigger_machine(phydev); +- +- return IRQ_HANDLED; +-} +- +-static int rtl8211_config_aneg(struct phy_device *phydev) +-{ +- int ret; +- +- ret = genphy_config_aneg(phydev); +- if (ret < 0) +- return ret; +- +- /* Quirk was copied from vendor driver. Unfortunately it includes no +- * description of the magic numbers. +- */ +- if (phydev->speed == SPEED_100 && phydev->autoneg == AUTONEG_DISABLE) { +- phy_write(phydev, 0x17, 0x2138); +- phy_write(phydev, 0x0e, 0x0260); +- } else { +- phy_write(phydev, 0x17, 0x2108); +- phy_write(phydev, 0x0e, 0x0000); +- } +- +- return 0; +-} +- +-static int rtl8211c_config_init(struct phy_device *phydev) +-{ +- /* RTL8211C has an issue when operating in Gigabit slave mode */ +- return phy_set_bits(phydev, MII_CTRL1000, +- CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER); +-} +- +-static int rtl8211f_config_init(struct phy_device *phydev) +-{ +- struct rtl821x_priv *priv = phydev->priv; +- struct device *dev = &phydev->mdio.dev; +- u16 val_txdly, val_rxdly; +- int ret; +- +- ret = phy_modify_paged_changed(phydev, 0xa43, RTL8211F_PHYCR1, +- RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF, +- priv->phycr1); +- if (ret < 0) { +- dev_err(dev, "aldps mode configuration failed: %pe\n", +- ERR_PTR(ret)); +- return ret; +- } +- +- switch (phydev->interface) { +- case PHY_INTERFACE_MODE_RGMII: +- val_txdly = 0; +- val_rxdly = 0; +- break; +- +- case PHY_INTERFACE_MODE_RGMII_RXID: +- val_txdly = 0; +- val_rxdly = RTL8211F_RX_DELAY; +- break; +- +- case PHY_INTERFACE_MODE_RGMII_TXID: +- val_txdly = RTL8211F_TX_DELAY; +- val_rxdly = 0; +- break; +- +- case PHY_INTERFACE_MODE_RGMII_ID: +- val_txdly = RTL8211F_TX_DELAY; +- val_rxdly = RTL8211F_RX_DELAY; +- break; +- +- default: /* the rest of the modes imply leaving delay as is. */ +- return 0; +- } +- +- ret = phy_modify_paged_changed(phydev, 0xd08, 0x11, RTL8211F_TX_DELAY, +- val_txdly); +- if (ret < 0) { +- dev_err(dev, "Failed to update the TX delay register\n"); +- return ret; +- } else if (ret) { +- dev_dbg(dev, +- "%s 2ns TX delay (and changing the value from pin-strapping RXD1 or the bootloader)\n", +- val_txdly ? "Enabling" : "Disabling"); +- } else { +- dev_dbg(dev, +- "2ns TX delay was already %s (by pin-strapping RXD1 or bootloader configuration)\n", +- val_txdly ? "enabled" : "disabled"); +- } +- +- ret = phy_modify_paged_changed(phydev, 0xd08, 0x15, RTL8211F_RX_DELAY, +- val_rxdly); +- if (ret < 0) { +- dev_err(dev, "Failed to update the RX delay register\n"); +- return ret; +- } else if (ret) { +- dev_dbg(dev, +- "%s 2ns RX delay (and changing the value from pin-strapping RXD0 or the bootloader)\n", +- val_rxdly ? "Enabling" : "Disabling"); +- } else { +- dev_dbg(dev, +- "2ns RX delay was already %s (by pin-strapping RXD0 or bootloader configuration)\n", +- val_rxdly ? "enabled" : "disabled"); +- } +- +- if (priv->has_phycr2) { +- ret = phy_modify_paged(phydev, 0xa43, RTL8211F_PHYCR2, +- RTL8211F_CLKOUT_EN, priv->phycr2); +- if (ret < 0) { +- dev_err(dev, "clkout configuration failed: %pe\n", +- ERR_PTR(ret)); +- return ret; +- } +- +- return genphy_soft_reset(phydev); +- } +- +- return 0; +-} +- +-static int rtl821x_suspend(struct phy_device *phydev) +-{ +- struct rtl821x_priv *priv = phydev->priv; +- int ret = 0; +- +- if (!phydev->wol_enabled) { +- ret = genphy_suspend(phydev); +- +- if (ret) +- return ret; +- +- clk_disable_unprepare(priv->clk); +- } +- +- return ret; +-} +- +-static int rtl821x_resume(struct phy_device *phydev) +-{ +- struct rtl821x_priv *priv = phydev->priv; +- int ret; +- +- if (!phydev->wol_enabled) +- clk_prepare_enable(priv->clk); +- +- ret = genphy_resume(phydev); +- if (ret < 0) +- return ret; +- +- msleep(20); +- +- return 0; +-} +- +-static int rtl8211f_led_hw_is_supported(struct phy_device *phydev, u8 index, +- unsigned long rules) +-{ +- const unsigned long mask = BIT(TRIGGER_NETDEV_LINK_10) | +- BIT(TRIGGER_NETDEV_LINK_100) | +- BIT(TRIGGER_NETDEV_LINK_1000) | +- BIT(TRIGGER_NETDEV_RX) | +- BIT(TRIGGER_NETDEV_TX); +- +- /* The RTL8211F PHY supports these LED settings on up to three LEDs: +- * - Link: Configurable subset of 10/100/1000 link rates +- * - Active: Blink on activity, RX or TX is not differentiated +- * The Active option has two modes, A and B: +- * - A: Link and Active indication at configurable, but matching, +- * subset of 10/100/1000 link rates +- * - B: Link indication at configurable subset of 10/100/1000 link +- * rates and Active indication always at all three 10+100+1000 +- * link rates. +- * This code currently uses mode B only. +- */ +- +- if (index >= RTL8211F_LED_COUNT) +- return -EINVAL; +- +- /* Filter out any other unsupported triggers. */ +- if (rules & ~mask) +- return -EOPNOTSUPP; +- +- /* RX and TX are not differentiated, either both are set or not set. */ +- if (!(rules & BIT(TRIGGER_NETDEV_RX)) ^ !(rules & BIT(TRIGGER_NETDEV_TX))) +- return -EOPNOTSUPP; +- +- return 0; +-} +- +-static int rtl8211f_led_hw_control_get(struct phy_device *phydev, u8 index, +- unsigned long *rules) +-{ +- int val; +- +- if (index >= RTL8211F_LED_COUNT) +- return -EINVAL; +- +- val = phy_read_paged(phydev, 0xd04, RTL8211F_LEDCR); +- if (val < 0) +- return val; +- +- val >>= RTL8211F_LEDCR_SHIFT * index; +- val &= RTL8211F_LEDCR_MASK; +- +- if (val & RTL8211F_LEDCR_LINK_10) +- set_bit(TRIGGER_NETDEV_LINK_10, rules); +- +- if (val & RTL8211F_LEDCR_LINK_100) +- set_bit(TRIGGER_NETDEV_LINK_100, rules); +- +- if (val & RTL8211F_LEDCR_LINK_1000) +- set_bit(TRIGGER_NETDEV_LINK_1000, rules); +- +- if (val & RTL8211F_LEDCR_ACT_TXRX) { +- set_bit(TRIGGER_NETDEV_RX, rules); +- set_bit(TRIGGER_NETDEV_TX, rules); +- } +- +- return 0; +-} +- +-static int rtl8211f_led_hw_control_set(struct phy_device *phydev, u8 index, +- unsigned long rules) +-{ +- const u16 mask = RTL8211F_LEDCR_MASK << (RTL8211F_LEDCR_SHIFT * index); +- u16 reg = 0; +- +- if (index >= RTL8211F_LED_COUNT) +- return -EINVAL; +- +- if (test_bit(TRIGGER_NETDEV_LINK_10, &rules)) +- reg |= RTL8211F_LEDCR_LINK_10; +- +- if (test_bit(TRIGGER_NETDEV_LINK_100, &rules)) +- reg |= RTL8211F_LEDCR_LINK_100; +- +- if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) +- reg |= RTL8211F_LEDCR_LINK_1000; +- +- if (test_bit(TRIGGER_NETDEV_RX, &rules) || +- test_bit(TRIGGER_NETDEV_TX, &rules)) { +- reg |= RTL8211F_LEDCR_ACT_TXRX; +- } +- +- reg <<= RTL8211F_LEDCR_SHIFT * index; +- reg |= RTL8211F_LEDCR_MODE; /* Mode B */ +- +- return phy_modify_paged(phydev, 0xd04, RTL8211F_LEDCR, mask, reg); +-} +- +-static int rtl8211e_config_init(struct phy_device *phydev) +-{ +- int ret = 0, oldpage; +- u16 val; +- +- /* enable TX/RX delay for rgmii-* modes, and disable them for rgmii. */ +- switch (phydev->interface) { +- case PHY_INTERFACE_MODE_RGMII: +- val = RTL8211E_CTRL_DELAY | 0; +- break; +- case PHY_INTERFACE_MODE_RGMII_ID: +- val = RTL8211E_CTRL_DELAY | RTL8211E_TX_DELAY | RTL8211E_RX_DELAY; +- break; +- case PHY_INTERFACE_MODE_RGMII_RXID: +- val = RTL8211E_CTRL_DELAY | RTL8211E_RX_DELAY; +- break; +- case PHY_INTERFACE_MODE_RGMII_TXID: +- val = RTL8211E_CTRL_DELAY | RTL8211E_TX_DELAY; +- break; +- default: /* the rest of the modes imply leaving delays as is. */ +- return 0; +- } +- +- /* According to a sample driver there is a 0x1c config register on the +- * 0xa4 extension page (0x7) layout. It can be used to disable/enable +- * the RX/TX delays otherwise controlled by RXDLY/TXDLY pins. +- * The configuration register definition: +- * 14 = reserved +- * 13 = Force Tx RX Delay controlled by bit12 bit11, +- * 12 = RX Delay, 11 = TX Delay +- * 10:0 = Test && debug settings reserved by realtek +- */ +- oldpage = phy_select_page(phydev, 0x7); +- if (oldpage < 0) +- goto err_restore_page; +- +- ret = __phy_write(phydev, RTL821x_EXT_PAGE_SELECT, 0xa4); +- if (ret) +- goto err_restore_page; +- +- ret = __phy_modify(phydev, 0x1c, RTL8211E_CTRL_DELAY +- | RTL8211E_TX_DELAY | RTL8211E_RX_DELAY, +- val); +- +-err_restore_page: +- return phy_restore_page(phydev, oldpage, ret); +-} +- +-static int rtl8211b_suspend(struct phy_device *phydev) +-{ +- phy_write(phydev, MII_MMD_DATA, BIT(9)); +- +- return genphy_suspend(phydev); +-} +- +-static int rtl8211b_resume(struct phy_device *phydev) +-{ +- phy_write(phydev, MII_MMD_DATA, 0); +- +- return genphy_resume(phydev); +-} +- +-static int rtl8366rb_config_init(struct phy_device *phydev) +-{ +- int ret; +- +- ret = phy_set_bits(phydev, RTL8366RB_POWER_SAVE, +- RTL8366RB_POWER_SAVE_ON); +- if (ret) { +- dev_err(&phydev->mdio.dev, +- "error enabling power management\n"); +- } +- +- return ret; +-} +- +-/* get actual speed to cover the downshift case */ +-static void rtlgen_decode_physr(struct phy_device *phydev, int val) +-{ +- /* bit 3 +- * 0: Half Duplex +- * 1: Full Duplex +- */ +- if (val & RTL_VND2_PHYSR_DUPLEX) +- phydev->duplex = DUPLEX_FULL; +- else +- phydev->duplex = DUPLEX_HALF; +- +- switch (val & RTL_VND2_PHYSR_SPEED_MASK) { +- case 0x0000: +- phydev->speed = SPEED_10; +- break; +- case 0x0010: +- phydev->speed = SPEED_100; +- break; +- case 0x0020: +- phydev->speed = SPEED_1000; +- break; +- case 0x0200: +- phydev->speed = SPEED_10000; +- break; +- case 0x0210: +- phydev->speed = SPEED_2500; +- break; +- case 0x0220: +- phydev->speed = SPEED_5000; +- break; +- default: +- break; +- } +- +- /* bit 11 +- * 0: Slave Mode +- * 1: Master Mode +- */ +- if (phydev->speed >= 1000) { +- if (val & RTL_VND2_PHYSR_MASTER) +- phydev->master_slave_state = MASTER_SLAVE_STATE_MASTER; +- else +- phydev->master_slave_state = MASTER_SLAVE_STATE_SLAVE; +- } else { +- phydev->master_slave_state = MASTER_SLAVE_STATE_UNSUPPORTED; +- } +-} +- +-static int rtlgen_read_status(struct phy_device *phydev) +-{ +- int ret, val; +- +- ret = genphy_read_status(phydev); +- if (ret < 0) +- return ret; +- +- if (!phydev->link) +- return 0; +- +- val = phy_read_paged(phydev, 0xa43, 0x12); +- if (val < 0) +- return val; +- +- rtlgen_decode_physr(phydev, val); +- +- return 0; +-} +- +-static int rtlgen_read_mmd(struct phy_device *phydev, int devnum, u16 regnum) +-{ +- int ret; +- +- if (devnum == MDIO_MMD_VEND2) { +- rtl821x_write_page(phydev, regnum >> 4); +- ret = __phy_read(phydev, 0x10 + ((regnum & 0xf) >> 1)); +- rtl821x_write_page(phydev, 0); +- } else if (devnum == MDIO_MMD_PCS && regnum == MDIO_PCS_EEE_ABLE) { +- rtl821x_write_page(phydev, 0xa5c); +- ret = __phy_read(phydev, 0x12); +- rtl821x_write_page(phydev, 0); +- } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) { +- rtl821x_write_page(phydev, 0xa5d); +- ret = __phy_read(phydev, 0x10); +- rtl821x_write_page(phydev, 0); +- } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_LPABLE) { +- rtl821x_write_page(phydev, 0xa5d); +- ret = __phy_read(phydev, 0x11); +- rtl821x_write_page(phydev, 0); +- } else { +- ret = -EOPNOTSUPP; +- } +- +- return ret; +-} +- +-static int rtlgen_write_mmd(struct phy_device *phydev, int devnum, u16 regnum, +- u16 val) +-{ +- int ret; +- +- if (devnum == MDIO_MMD_VEND2) { +- rtl821x_write_page(phydev, regnum >> 4); +- ret = __phy_write(phydev, 0x10 + ((regnum & 0xf) >> 1), val); +- rtl821x_write_page(phydev, 0); +- } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) { +- rtl821x_write_page(phydev, 0xa5d); +- ret = __phy_write(phydev, 0x10, val); +- rtl821x_write_page(phydev, 0); +- } else { +- ret = -EOPNOTSUPP; +- } +- +- return ret; +-} +- +-static int rtl822x_read_mmd(struct phy_device *phydev, int devnum, u16 regnum) +-{ +- int ret = rtlgen_read_mmd(phydev, devnum, regnum); +- +- if (ret != -EOPNOTSUPP) +- return ret; +- +- if (devnum == MDIO_MMD_PCS && regnum == MDIO_PCS_EEE_ABLE2) { +- rtl821x_write_page(phydev, 0xa6e); +- ret = __phy_read(phydev, 0x16); +- rtl821x_write_page(phydev, 0); +- } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV2) { +- rtl821x_write_page(phydev, 0xa6d); +- ret = __phy_read(phydev, 0x12); +- rtl821x_write_page(phydev, 0); +- } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_LPABLE2) { +- rtl821x_write_page(phydev, 0xa6d); +- ret = __phy_read(phydev, 0x10); +- rtl821x_write_page(phydev, 0); +- } +- +- return ret; +-} +- +-static int rtl822x_write_mmd(struct phy_device *phydev, int devnum, u16 regnum, +- u16 val) +-{ +- int ret = rtlgen_write_mmd(phydev, devnum, regnum, val); +- +- if (ret != -EOPNOTSUPP) +- return ret; +- +- if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV2) { +- rtl821x_write_page(phydev, 0xa6d); +- ret = __phy_write(phydev, 0x12, val); +- rtl821x_write_page(phydev, 0); +- } +- +- return ret; +-} +- +-static int rtl822xb_config_init(struct phy_device *phydev) +-{ +- bool has_2500, has_sgmii; +- u16 mode; +- int ret; +- +- has_2500 = test_bit(PHY_INTERFACE_MODE_2500BASEX, +- phydev->host_interfaces) || +- phydev->interface == PHY_INTERFACE_MODE_2500BASEX; +- +- has_sgmii = test_bit(PHY_INTERFACE_MODE_SGMII, +- phydev->host_interfaces) || +- phydev->interface == PHY_INTERFACE_MODE_SGMII; +- +- /* fill in possible interfaces */ +- __assign_bit(PHY_INTERFACE_MODE_2500BASEX, phydev->possible_interfaces, +- has_2500); +- __assign_bit(PHY_INTERFACE_MODE_SGMII, phydev->possible_interfaces, +- has_sgmii); +- +- if (!has_2500 && !has_sgmii) +- return 0; +- +- /* determine SerDes option mode */ +- if (has_2500 && !has_sgmii) { +- mode = RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX; +- phydev->rate_matching = RATE_MATCH_PAUSE; +- } else { +- mode = RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX_SGMII; +- phydev->rate_matching = RATE_MATCH_NONE; +- } +- +- /* the following sequence with magic numbers sets up the SerDes +- * option mode +- */ +- ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x75f3, 0); +- if (ret < 0) +- return ret; +- +- ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND1, +- RTL822X_VND1_SERDES_OPTION, +- RTL822X_VND1_SERDES_OPTION_MODE_MASK, +- mode); +- if (ret < 0) +- return ret; +- +- ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6a04, 0x0503); +- if (ret < 0) +- return ret; +- +- ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f10, 0xd455); +- if (ret < 0) +- return ret; +- +- return phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f11, 0x8020); +-} +- +-static int rtl822xb_get_rate_matching(struct phy_device *phydev, +- phy_interface_t iface) +-{ +- int val; +- +- /* Only rate matching at 2500base-x */ +- if (iface != PHY_INTERFACE_MODE_2500BASEX) +- return RATE_MATCH_NONE; +- +- val = phy_read_mmd(phydev, MDIO_MMD_VEND1, RTL822X_VND1_SERDES_OPTION); +- if (val < 0) +- return val; +- +- if ((val & RTL822X_VND1_SERDES_OPTION_MODE_MASK) == +- RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX) +- return RATE_MATCH_PAUSE; +- +- /* RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX_SGMII */ +- return RATE_MATCH_NONE; +-} +- +-static int rtl822x_get_features(struct phy_device *phydev) +-{ +- int val; +- +- val = phy_read_paged(phydev, 0xa61, 0x13); +- if (val < 0) +- return val; +- +- linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, +- phydev->supported, val & MDIO_PMA_SPEED_2_5G); +- linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, +- phydev->supported, val & MDIO_PMA_SPEED_5G); +- linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, +- phydev->supported, val & MDIO_SPEED_10G); +- +- return genphy_read_abilities(phydev); +-} +- +-static int rtl822x_config_aneg(struct phy_device *phydev) +-{ +- int ret = 0; +- +- if (phydev->autoneg == AUTONEG_ENABLE) { +- u16 adv = linkmode_adv_to_mii_10gbt_adv_t(phydev->advertising); +- +- ret = phy_modify_paged_changed(phydev, 0xa5d, 0x12, +- MDIO_AN_10GBT_CTRL_ADV2_5G | +- MDIO_AN_10GBT_CTRL_ADV5G, +- adv); +- if (ret < 0) +- return ret; +- } +- +- return __genphy_config_aneg(phydev, ret); +-} +- +-static void rtl822xb_update_interface(struct phy_device *phydev) +-{ +- int val; +- +- if (!phydev->link) +- return; +- +- /* Change interface according to serdes mode */ +- val = phy_read_mmd(phydev, MDIO_MMD_VEND1, RTL822X_VND1_SERDES_CTRL3); +- if (val < 0) +- return; +- +- switch (val & RTL822X_VND1_SERDES_CTRL3_MODE_MASK) { +- case RTL822X_VND1_SERDES_CTRL3_MODE_2500BASEX: +- phydev->interface = PHY_INTERFACE_MODE_2500BASEX; +- break; +- case RTL822X_VND1_SERDES_CTRL3_MODE_SGMII: +- phydev->interface = PHY_INTERFACE_MODE_SGMII; +- break; +- } +-} +- +-static int rtl822x_read_status(struct phy_device *phydev) +-{ +- int lpadv, ret; +- +- ret = rtlgen_read_status(phydev); +- if (ret < 0) +- return ret; +- +- if (phydev->autoneg == AUTONEG_DISABLE || +- !phydev->autoneg_complete) { +- mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, 0); +- return 0; +- } +- +- lpadv = phy_read_paged(phydev, 0xa5d, 0x13); +- if (lpadv < 0) +- return lpadv; +- +- mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, lpadv); +- +- return 0; +-} +- +-static int rtl822xb_read_status(struct phy_device *phydev) +-{ +- int ret; +- +- ret = rtl822x_read_status(phydev); +- if (ret < 0) +- return ret; +- +- rtl822xb_update_interface(phydev); +- +- return 0; +-} +- +-static int rtl822x_c45_get_features(struct phy_device *phydev) +-{ +- linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT, +- phydev->supported); +- +- return genphy_c45_pma_read_abilities(phydev); +-} +- +-static int rtl822x_c45_config_aneg(struct phy_device *phydev) +-{ +- bool changed = false; +- int ret, val; +- +- if (phydev->autoneg == AUTONEG_DISABLE) +- return genphy_c45_pma_setup_forced(phydev); +- +- ret = genphy_c45_an_config_aneg(phydev); +- if (ret < 0) +- return ret; +- if (ret > 0) +- changed = true; +- +- val = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising); +- +- /* Vendor register as C45 has no standardized support for 1000BaseT */ +- ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, RTL822X_VND2_GBCR, +- ADVERTISE_1000FULL, val); +- if (ret < 0) +- return ret; +- if (ret > 0) +- changed = true; +- +- return genphy_c45_check_and_restart_aneg(phydev, changed); +-} +- +-static int rtl822x_c45_read_status(struct phy_device *phydev) +-{ +- int ret, val; +- +- ret = genphy_c45_read_status(phydev); +- if (ret < 0) +- return ret; +- +- if (phydev->autoneg == AUTONEG_DISABLE || +- !genphy_c45_aneg_done(phydev)) +- mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, 0); +- +- /* Vendor register as C45 has no standardized support for 1000BaseT */ +- if (phydev->autoneg == AUTONEG_ENABLE) { +- val = phy_read_mmd(phydev, MDIO_MMD_VEND2, +- RTL822X_VND2_GANLPAR); +- if (val < 0) +- return val; +- +- mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, val); +- } +- +- if (!phydev->link) +- return 0; +- +- /* Read actual speed from vendor register. */ +- val = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL_VND2_PHYSR); +- if (val < 0) +- return val; +- +- rtlgen_decode_physr(phydev, val); +- +- return 0; +-} +- +-static int rtl822xb_c45_read_status(struct phy_device *phydev) +-{ +- int ret; +- +- ret = rtl822x_c45_read_status(phydev); +- if (ret < 0) +- return ret; +- +- rtl822xb_update_interface(phydev); +- +- return 0; +-} +- +-static bool rtlgen_supports_2_5gbps(struct phy_device *phydev) +-{ +- int val; +- +- phy_write(phydev, RTL821x_PAGE_SELECT, 0xa61); +- val = phy_read(phydev, 0x13); +- phy_write(phydev, RTL821x_PAGE_SELECT, 0); +- +- return val >= 0 && val & MDIO_PMA_SPEED_2_5G; +-} +- +-/* On internal PHY's MMD reads over C22 always return 0. +- * Check a MMD register which is known to be non-zero. +- */ +-static bool rtlgen_supports_mmd(struct phy_device *phydev) +-{ +- int val; +- +- phy_lock_mdio_bus(phydev); +- __phy_write(phydev, MII_MMD_CTRL, MDIO_MMD_PCS); +- __phy_write(phydev, MII_MMD_DATA, MDIO_PCS_EEE_ABLE); +- __phy_write(phydev, MII_MMD_CTRL, MDIO_MMD_PCS | MII_MMD_CTRL_NOINCR); +- val = __phy_read(phydev, MII_MMD_DATA); +- phy_unlock_mdio_bus(phydev); +- +- return val > 0; +-} +- +-static int rtlgen_match_phy_device(struct phy_device *phydev) +-{ +- return phydev->phy_id == RTL_GENERIC_PHYID && +- !rtlgen_supports_2_5gbps(phydev); +-} +- +-static int rtl8226_match_phy_device(struct phy_device *phydev) +-{ +- return phydev->phy_id == RTL_GENERIC_PHYID && +- rtlgen_supports_2_5gbps(phydev) && +- rtlgen_supports_mmd(phydev); +-} +- +-static int rtlgen_is_c45_match(struct phy_device *phydev, unsigned int id, +- bool is_c45) +-{ +- if (phydev->is_c45) +- return is_c45 && (id == phydev->c45_ids.device_ids[1]); +- else +- return !is_c45 && (id == phydev->phy_id); +-} +- +-static int rtl8221b_match_phy_device(struct phy_device *phydev) +-{ +- return phydev->phy_id == RTL_8221B && rtlgen_supports_mmd(phydev); +-} +- +-static int rtl8221b_vb_cg_c22_match_phy_device(struct phy_device *phydev) +-{ +- return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, false); +-} +- +-static int rtl8221b_vb_cg_c45_match_phy_device(struct phy_device *phydev) +-{ +- return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, true); +-} +- +-static int rtl8221b_vn_cg_c22_match_phy_device(struct phy_device *phydev) +-{ +- return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, false); +-} +- +-static int rtl8221b_vn_cg_c45_match_phy_device(struct phy_device *phydev) +-{ +- return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, true); +-} +- +-static int rtl_internal_nbaset_match_phy_device(struct phy_device *phydev) +-{ +- if (phydev->is_c45) +- return false; +- +- switch (phydev->phy_id) { +- case RTL_GENERIC_PHYID: +- case RTL_8221B: +- case RTL_8251B: +- case 0x001cc841: +- break; +- default: +- return false; +- } +- +- return rtlgen_supports_2_5gbps(phydev) && !rtlgen_supports_mmd(phydev); +-} +- +-static int rtl8251b_c45_match_phy_device(struct phy_device *phydev) +-{ +- return rtlgen_is_c45_match(phydev, RTL_8251B, true); +-} +- +-static int rtlgen_resume(struct phy_device *phydev) +-{ +- int ret = genphy_resume(phydev); +- +- /* Internal PHY's from RTL8168h up may not be instantly ready */ +- msleep(20); +- +- return ret; +-} +- +-static int rtlgen_c45_resume(struct phy_device *phydev) +-{ +- int ret = genphy_c45_pma_resume(phydev); +- +- msleep(20); +- +- return ret; +-} +- +-static int rtl9000a_config_init(struct phy_device *phydev) +-{ +- phydev->autoneg = AUTONEG_DISABLE; +- phydev->speed = SPEED_100; +- phydev->duplex = DUPLEX_FULL; +- +- return 0; +-} +- +-static int rtl9000a_config_aneg(struct phy_device *phydev) +-{ +- int ret; +- u16 ctl = 0; +- +- switch (phydev->master_slave_set) { +- case MASTER_SLAVE_CFG_MASTER_FORCE: +- ctl |= CTL1000_AS_MASTER; +- break; +- case MASTER_SLAVE_CFG_SLAVE_FORCE: +- break; +- case MASTER_SLAVE_CFG_UNKNOWN: +- case MASTER_SLAVE_CFG_UNSUPPORTED: +- return 0; +- default: +- phydev_warn(phydev, "Unsupported Master/Slave mode\n"); +- return -EOPNOTSUPP; +- } +- +- ret = phy_modify_changed(phydev, MII_CTRL1000, CTL1000_AS_MASTER, ctl); +- if (ret == 1) +- ret = genphy_soft_reset(phydev); +- +- return ret; +-} +- +-static int rtl9000a_read_status(struct phy_device *phydev) +-{ +- int ret; +- +- phydev->master_slave_get = MASTER_SLAVE_CFG_UNKNOWN; +- phydev->master_slave_state = MASTER_SLAVE_STATE_UNKNOWN; +- +- ret = genphy_update_link(phydev); +- if (ret) +- return ret; +- +- ret = phy_read(phydev, MII_CTRL1000); +- if (ret < 0) +- return ret; +- if (ret & CTL1000_AS_MASTER) +- phydev->master_slave_get = MASTER_SLAVE_CFG_MASTER_FORCE; +- else +- phydev->master_slave_get = MASTER_SLAVE_CFG_SLAVE_FORCE; +- +- ret = phy_read(phydev, MII_STAT1000); +- if (ret < 0) +- return ret; +- if (ret & LPA_1000MSRES) +- phydev->master_slave_state = MASTER_SLAVE_STATE_MASTER; +- else +- phydev->master_slave_state = MASTER_SLAVE_STATE_SLAVE; +- +- return 0; +-} +- +-static int rtl9000a_ack_interrupt(struct phy_device *phydev) +-{ +- int err; +- +- err = phy_read(phydev, RTL8211F_INSR); +- +- return (err < 0) ? err : 0; +-} +- +-static int rtl9000a_config_intr(struct phy_device *phydev) +-{ +- u16 val; +- int err; +- +- if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { +- err = rtl9000a_ack_interrupt(phydev); +- if (err) +- return err; +- +- val = (u16)~RTL9000A_GINMR_LINK_STATUS; +- err = phy_write_paged(phydev, 0xa42, RTL9000A_GINMR, val); +- } else { +- val = ~0; +- err = phy_write_paged(phydev, 0xa42, RTL9000A_GINMR, val); +- if (err) +- return err; +- +- err = rtl9000a_ack_interrupt(phydev); +- } +- +- return phy_write_paged(phydev, 0xa42, RTL9000A_GINMR, val); +-} +- +-static irqreturn_t rtl9000a_handle_interrupt(struct phy_device *phydev) +-{ +- int irq_status; +- +- irq_status = phy_read(phydev, RTL8211F_INSR); +- if (irq_status < 0) { +- phy_error(phydev); +- return IRQ_NONE; +- } +- +- if (!(irq_status & RTL8211F_INER_LINK_STATUS)) +- return IRQ_NONE; +- +- phy_trigger_machine(phydev); +- +- return IRQ_HANDLED; +-} +- +-static struct phy_driver realtek_drvs[] = { +- { +- PHY_ID_MATCH_EXACT(0x00008201), +- .name = "RTL8201CP Ethernet", +- .read_page = rtl821x_read_page, +- .write_page = rtl821x_write_page, +- }, { +- PHY_ID_MATCH_EXACT(0x001cc816), +- .name = "RTL8201F Fast Ethernet", +- .config_intr = &rtl8201_config_intr, +- .handle_interrupt = rtl8201_handle_interrupt, +- .suspend = genphy_suspend, +- .resume = genphy_resume, +- .read_page = rtl821x_read_page, +- .write_page = rtl821x_write_page, +- }, { +- PHY_ID_MATCH_MODEL(0x001cc880), +- .name = "RTL8208 Fast Ethernet", +- .read_mmd = genphy_read_mmd_unsupported, +- .write_mmd = genphy_write_mmd_unsupported, +- .suspend = genphy_suspend, +- .resume = genphy_resume, +- .read_page = rtl821x_read_page, +- .write_page = rtl821x_write_page, +- }, { +- PHY_ID_MATCH_EXACT(0x001cc910), +- .name = "RTL8211 Gigabit Ethernet", +- .config_aneg = rtl8211_config_aneg, +- .read_mmd = &genphy_read_mmd_unsupported, +- .write_mmd = &genphy_write_mmd_unsupported, +- .read_page = rtl821x_read_page, +- .write_page = rtl821x_write_page, +- }, { +- PHY_ID_MATCH_EXACT(0x001cc912), +- .name = "RTL8211B Gigabit Ethernet", +- .config_intr = &rtl8211b_config_intr, +- .handle_interrupt = rtl821x_handle_interrupt, +- .read_mmd = &genphy_read_mmd_unsupported, +- .write_mmd = &genphy_write_mmd_unsupported, +- .suspend = rtl8211b_suspend, +- .resume = rtl8211b_resume, +- .read_page = rtl821x_read_page, +- .write_page = rtl821x_write_page, +- }, { +- PHY_ID_MATCH_EXACT(0x001cc913), +- .name = "RTL8211C Gigabit Ethernet", +- .config_init = rtl8211c_config_init, +- .read_mmd = &genphy_read_mmd_unsupported, +- .write_mmd = &genphy_write_mmd_unsupported, +- .read_page = rtl821x_read_page, +- .write_page = rtl821x_write_page, +- }, { +- PHY_ID_MATCH_EXACT(0x001cc914), +- .name = "RTL8211DN Gigabit Ethernet", +- .config_intr = rtl8211e_config_intr, +- .handle_interrupt = rtl821x_handle_interrupt, +- .suspend = genphy_suspend, +- .resume = genphy_resume, +- .read_page = rtl821x_read_page, +- .write_page = rtl821x_write_page, +- }, { +- PHY_ID_MATCH_EXACT(0x001cc915), +- .name = "RTL8211E Gigabit Ethernet", +- .config_init = &rtl8211e_config_init, +- .config_intr = &rtl8211e_config_intr, +- .handle_interrupt = rtl821x_handle_interrupt, +- .suspend = genphy_suspend, +- .resume = genphy_resume, +- .read_page = rtl821x_read_page, +- .write_page = rtl821x_write_page, +- }, { +- PHY_ID_MATCH_EXACT(0x001cc916), +- .name = "RTL8211F Gigabit Ethernet", +- .probe = rtl821x_probe, +- .config_init = &rtl8211f_config_init, +- .read_status = rtlgen_read_status, +- .config_intr = &rtl8211f_config_intr, +- .handle_interrupt = rtl8211f_handle_interrupt, +- .suspend = rtl821x_suspend, +- .resume = rtl821x_resume, +- .read_page = rtl821x_read_page, +- .write_page = rtl821x_write_page, +- .flags = PHY_ALWAYS_CALL_SUSPEND, +- .led_hw_is_supported = rtl8211f_led_hw_is_supported, +- .led_hw_control_get = rtl8211f_led_hw_control_get, +- .led_hw_control_set = rtl8211f_led_hw_control_set, +- }, { +- PHY_ID_MATCH_EXACT(RTL_8211FVD_PHYID), +- .name = "RTL8211F-VD Gigabit Ethernet", +- .probe = rtl821x_probe, +- .config_init = &rtl8211f_config_init, +- .read_status = rtlgen_read_status, +- .config_intr = &rtl8211f_config_intr, +- .handle_interrupt = rtl8211f_handle_interrupt, +- .suspend = rtl821x_suspend, +- .resume = rtl821x_resume, +- .read_page = rtl821x_read_page, +- .write_page = rtl821x_write_page, +- .flags = PHY_ALWAYS_CALL_SUSPEND, +- }, { +- .name = "Generic FE-GE Realtek PHY", +- .match_phy_device = rtlgen_match_phy_device, +- .read_status = rtlgen_read_status, +- .suspend = genphy_suspend, +- .resume = rtlgen_resume, +- .read_page = rtl821x_read_page, +- .write_page = rtl821x_write_page, +- .read_mmd = rtlgen_read_mmd, +- .write_mmd = rtlgen_write_mmd, +- }, { +- .name = "RTL8226 2.5Gbps PHY", +- .match_phy_device = rtl8226_match_phy_device, +- .get_features = rtl822x_get_features, +- .config_aneg = rtl822x_config_aneg, +- .read_status = rtl822x_read_status, +- .suspend = genphy_suspend, +- .resume = rtlgen_resume, +- .read_page = rtl821x_read_page, +- .write_page = rtl821x_write_page, +- }, { +- .match_phy_device = rtl8221b_match_phy_device, +- .name = "RTL8226B_RTL8221B 2.5Gbps PHY", +- .get_features = rtl822x_get_features, +- .config_aneg = rtl822x_config_aneg, +- .config_init = rtl822xb_config_init, +- .get_rate_matching = rtl822xb_get_rate_matching, +- .read_status = rtl822xb_read_status, +- .suspend = genphy_suspend, +- .resume = rtlgen_resume, +- .read_page = rtl821x_read_page, +- .write_page = rtl821x_write_page, +- }, { +- PHY_ID_MATCH_EXACT(0x001cc838), +- .name = "RTL8226-CG 2.5Gbps PHY", +- .get_features = rtl822x_get_features, +- .config_aneg = rtl822x_config_aneg, +- .read_status = rtl822x_read_status, +- .suspend = genphy_suspend, +- .resume = rtlgen_resume, +- .read_page = rtl821x_read_page, +- .write_page = rtl821x_write_page, +- }, { +- PHY_ID_MATCH_EXACT(0x001cc848), +- .name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY", +- .get_features = rtl822x_get_features, +- .config_aneg = rtl822x_config_aneg, +- .config_init = rtl822xb_config_init, +- .get_rate_matching = rtl822xb_get_rate_matching, +- .read_status = rtl822xb_read_status, +- .suspend = genphy_suspend, +- .resume = rtlgen_resume, +- .read_page = rtl821x_read_page, +- .write_page = rtl821x_write_page, +- }, { +- .match_phy_device = rtl8221b_vb_cg_c22_match_phy_device, +- .name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)", +- .get_features = rtl822x_get_features, +- .config_aneg = rtl822x_config_aneg, +- .config_init = rtl822xb_config_init, +- .get_rate_matching = rtl822xb_get_rate_matching, +- .read_status = rtl822xb_read_status, +- .suspend = genphy_suspend, +- .resume = rtlgen_resume, +- .read_page = rtl821x_read_page, +- .write_page = rtl821x_write_page, +- }, { +- .match_phy_device = rtl8221b_vb_cg_c45_match_phy_device, +- .name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)", +- .config_init = rtl822xb_config_init, +- .get_rate_matching = rtl822xb_get_rate_matching, +- .get_features = rtl822x_c45_get_features, +- .config_aneg = rtl822x_c45_config_aneg, +- .read_status = rtl822xb_c45_read_status, +- .suspend = genphy_c45_pma_suspend, +- .resume = rtlgen_c45_resume, +- }, { +- .match_phy_device = rtl8221b_vn_cg_c22_match_phy_device, +- .name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)", +- .get_features = rtl822x_get_features, +- .config_aneg = rtl822x_config_aneg, +- .config_init = rtl822xb_config_init, +- .get_rate_matching = rtl822xb_get_rate_matching, +- .read_status = rtl822xb_read_status, +- .suspend = genphy_suspend, +- .resume = rtlgen_resume, +- .read_page = rtl821x_read_page, +- .write_page = rtl821x_write_page, +- }, { +- .match_phy_device = rtl8221b_vn_cg_c45_match_phy_device, +- .name = "RTL8221B-VN-CG 2.5Gbps PHY (C45)", +- .config_init = rtl822xb_config_init, +- .get_rate_matching = rtl822xb_get_rate_matching, +- .get_features = rtl822x_c45_get_features, +- .config_aneg = rtl822x_c45_config_aneg, +- .read_status = rtl822xb_c45_read_status, +- .suspend = genphy_c45_pma_suspend, +- .resume = rtlgen_c45_resume, +- }, { +- .match_phy_device = rtl8251b_c45_match_phy_device, +- .name = "RTL8251B 5Gbps PHY", +- .get_features = rtl822x_get_features, +- .config_aneg = rtl822x_config_aneg, +- .read_status = rtl822x_read_status, +- .suspend = genphy_suspend, +- .resume = rtlgen_resume, +- .read_page = rtl821x_read_page, +- .write_page = rtl821x_write_page, +- }, { +- .match_phy_device = rtl_internal_nbaset_match_phy_device, +- .name = "Realtek Internal NBASE-T PHY", +- .flags = PHY_IS_INTERNAL, +- .get_features = rtl822x_get_features, +- .config_aneg = rtl822x_config_aneg, +- .read_status = rtl822x_read_status, +- .suspend = genphy_suspend, +- .resume = rtlgen_resume, +- .read_page = rtl821x_read_page, +- .write_page = rtl821x_write_page, +- .read_mmd = rtl822x_read_mmd, +- .write_mmd = rtl822x_write_mmd, +- }, { +- PHY_ID_MATCH_EXACT(0x001ccad0), +- .name = "RTL8224 2.5Gbps PHY", +- .get_features = rtl822x_c45_get_features, +- .config_aneg = rtl822x_c45_config_aneg, +- .read_status = rtl822x_c45_read_status, +- .suspend = genphy_c45_pma_suspend, +- .resume = rtlgen_c45_resume, +- }, { +- PHY_ID_MATCH_EXACT(0x001cc961), +- .name = "RTL8366RB Gigabit Ethernet", +- .config_init = &rtl8366rb_config_init, +- /* These interrupts are handled by the irq controller +- * embedded inside the RTL8366RB, they get unmasked when the +- * irq is requested and ACKed by reading the status register, +- * which is done by the irqchip code. +- */ +- .config_intr = genphy_no_config_intr, +- .handle_interrupt = genphy_handle_interrupt_no_ack, +- .suspend = genphy_suspend, +- .resume = genphy_resume, +- }, { +- PHY_ID_MATCH_EXACT(0x001ccb00), +- .name = "RTL9000AA_RTL9000AN Ethernet", +- .features = PHY_BASIC_T1_FEATURES, +- .config_init = rtl9000a_config_init, +- .config_aneg = rtl9000a_config_aneg, +- .read_status = rtl9000a_read_status, +- .config_intr = rtl9000a_config_intr, +- .handle_interrupt = rtl9000a_handle_interrupt, +- .suspend = genphy_suspend, +- .resume = genphy_resume, +- .read_page = rtl821x_read_page, +- .write_page = rtl821x_write_page, +- }, { +- PHY_ID_MATCH_EXACT(0x001cc942), +- .name = "RTL8365MB-VC Gigabit Ethernet", +- /* Interrupt handling analogous to RTL8366RB */ +- .config_intr = genphy_no_config_intr, +- .handle_interrupt = genphy_handle_interrupt_no_ack, +- .suspend = genphy_suspend, +- .resume = genphy_resume, +- }, { +- PHY_ID_MATCH_EXACT(0x001cc960), +- .name = "RTL8366S Gigabit Ethernet", +- .suspend = genphy_suspend, +- .resume = genphy_resume, +- .read_mmd = genphy_read_mmd_unsupported, +- .write_mmd = genphy_write_mmd_unsupported, +- }, +-}; +- +-module_phy_driver(realtek_drvs); +- +-static const struct mdio_device_id __maybe_unused realtek_tbl[] = { +- { PHY_ID_MATCH_VENDOR(0x001cc800) }, +- { } +-}; +- +-MODULE_DEVICE_TABLE(mdio, realtek_tbl); +--- /dev/null ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -0,0 +1,1590 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* drivers/net/phy/realtek.c ++ * ++ * Driver for Realtek PHYs ++ * ++ * Author: Johnson Leung ++ * ++ * Copyright (c) 2004 Freescale Semiconductor, Inc. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define RTL821x_PHYSR 0x11 ++#define RTL821x_PHYSR_DUPLEX BIT(13) ++#define RTL821x_PHYSR_SPEED GENMASK(15, 14) ++ ++#define RTL821x_INER 0x12 ++#define RTL8211B_INER_INIT 0x6400 ++#define RTL8211E_INER_LINK_STATUS BIT(10) ++#define RTL8211F_INER_LINK_STATUS BIT(4) ++ ++#define RTL821x_INSR 0x13 ++ ++#define RTL821x_EXT_PAGE_SELECT 0x1e ++#define RTL821x_PAGE_SELECT 0x1f ++ ++#define RTL8211F_PHYCR1 0x18 ++#define RTL8211F_PHYCR2 0x19 ++#define RTL8211F_INSR 0x1d ++ ++#define RTL8211F_LEDCR 0x10 ++#define RTL8211F_LEDCR_MODE BIT(15) ++#define RTL8211F_LEDCR_ACT_TXRX BIT(4) ++#define RTL8211F_LEDCR_LINK_1000 BIT(3) ++#define RTL8211F_LEDCR_LINK_100 BIT(1) ++#define RTL8211F_LEDCR_LINK_10 BIT(0) ++#define RTL8211F_LEDCR_MASK GENMASK(4, 0) ++#define RTL8211F_LEDCR_SHIFT 5 ++ ++#define RTL8211F_TX_DELAY BIT(8) ++#define RTL8211F_RX_DELAY BIT(3) ++ ++#define RTL8211F_ALDPS_PLL_OFF BIT(1) ++#define RTL8211F_ALDPS_ENABLE BIT(2) ++#define RTL8211F_ALDPS_XTAL_OFF BIT(12) ++ ++#define RTL8211E_CTRL_DELAY BIT(13) ++#define RTL8211E_TX_DELAY BIT(12) ++#define RTL8211E_RX_DELAY BIT(11) ++ ++#define RTL8211F_CLKOUT_EN BIT(0) ++ ++#define RTL8201F_ISR 0x1e ++#define RTL8201F_ISR_ANERR BIT(15) ++#define RTL8201F_ISR_DUPLEX BIT(13) ++#define RTL8201F_ISR_LINK BIT(11) ++#define RTL8201F_ISR_MASK (RTL8201F_ISR_ANERR | \ ++ RTL8201F_ISR_DUPLEX | \ ++ RTL8201F_ISR_LINK) ++#define RTL8201F_IER 0x13 ++ ++#define RTL822X_VND1_SERDES_OPTION 0x697a ++#define RTL822X_VND1_SERDES_OPTION_MODE_MASK GENMASK(5, 0) ++#define RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX_SGMII 0 ++#define RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX 2 ++ ++#define RTL822X_VND1_SERDES_CTRL3 0x7580 ++#define RTL822X_VND1_SERDES_CTRL3_MODE_MASK GENMASK(5, 0) ++#define RTL822X_VND1_SERDES_CTRL3_MODE_SGMII 0x02 ++#define RTL822X_VND1_SERDES_CTRL3_MODE_2500BASEX 0x16 ++ ++/* RTL822X_VND2_XXXXX registers are only accessible when phydev->is_c45 ++ * is set, they cannot be accessed by C45-over-C22. ++ */ ++#define RTL822X_VND2_GBCR 0xa412 ++ ++#define RTL822X_VND2_GANLPAR 0xa414 ++ ++#define RTL8366RB_POWER_SAVE 0x15 ++#define RTL8366RB_POWER_SAVE_ON BIT(12) ++ ++#define RTL9000A_GINMR 0x14 ++#define RTL9000A_GINMR_LINK_STATUS BIT(4) ++ ++#define RTL_VND2_PHYSR 0xa434 ++#define RTL_VND2_PHYSR_DUPLEX BIT(3) ++#define RTL_VND2_PHYSR_SPEEDL GENMASK(5, 4) ++#define RTL_VND2_PHYSR_SPEEDH GENMASK(10, 9) ++#define RTL_VND2_PHYSR_MASTER BIT(11) ++#define RTL_VND2_PHYSR_SPEED_MASK (RTL_VND2_PHYSR_SPEEDL | RTL_VND2_PHYSR_SPEEDH) ++ ++#define RTL_GENERIC_PHYID 0x001cc800 ++#define RTL_8211FVD_PHYID 0x001cc878 ++#define RTL_8221B 0x001cc840 ++#define RTL_8221B_VB_CG 0x001cc849 ++#define RTL_8221B_VN_CG 0x001cc84a ++#define RTL_8251B 0x001cc862 ++ ++#define RTL8211F_LED_COUNT 3 ++ ++MODULE_DESCRIPTION("Realtek PHY driver"); ++MODULE_AUTHOR("Johnson Leung"); ++MODULE_LICENSE("GPL"); ++ ++struct rtl821x_priv { ++ u16 phycr1; ++ u16 phycr2; ++ bool has_phycr2; ++ struct clk *clk; ++}; ++ ++static int rtl821x_read_page(struct phy_device *phydev) ++{ ++ return __phy_read(phydev, RTL821x_PAGE_SELECT); ++} ++ ++static int rtl821x_write_page(struct phy_device *phydev, int page) ++{ ++ return __phy_write(phydev, RTL821x_PAGE_SELECT, page); ++} ++ ++static int rtl821x_probe(struct phy_device *phydev) ++{ ++ struct device *dev = &phydev->mdio.dev; ++ struct rtl821x_priv *priv; ++ u32 phy_id = phydev->drv->phy_id; ++ int ret; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->clk = devm_clk_get_optional_enabled(dev, NULL); ++ if (IS_ERR(priv->clk)) ++ return dev_err_probe(dev, PTR_ERR(priv->clk), ++ "failed to get phy clock\n"); ++ ++ ret = phy_read_paged(phydev, 0xa43, RTL8211F_PHYCR1); ++ if (ret < 0) ++ return ret; ++ ++ priv->phycr1 = ret & (RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF); ++ if (of_property_read_bool(dev->of_node, "realtek,aldps-enable")) ++ priv->phycr1 |= RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF; ++ ++ priv->has_phycr2 = !(phy_id == RTL_8211FVD_PHYID); ++ if (priv->has_phycr2) { ++ ret = phy_read_paged(phydev, 0xa43, RTL8211F_PHYCR2); ++ if (ret < 0) ++ return ret; ++ ++ priv->phycr2 = ret & RTL8211F_CLKOUT_EN; ++ if (of_property_read_bool(dev->of_node, "realtek,clkout-disable")) ++ priv->phycr2 &= ~RTL8211F_CLKOUT_EN; ++ } ++ ++ phydev->priv = priv; ++ ++ return 0; ++} ++ ++static int rtl8201_ack_interrupt(struct phy_device *phydev) ++{ ++ int err; ++ ++ err = phy_read(phydev, RTL8201F_ISR); ++ ++ return (err < 0) ? err : 0; ++} ++ ++static int rtl821x_ack_interrupt(struct phy_device *phydev) ++{ ++ int err; ++ ++ err = phy_read(phydev, RTL821x_INSR); ++ ++ return (err < 0) ? err : 0; ++} ++ ++static int rtl8211f_ack_interrupt(struct phy_device *phydev) ++{ ++ int err; ++ ++ err = phy_read_paged(phydev, 0xa43, RTL8211F_INSR); ++ ++ return (err < 0) ? err : 0; ++} ++ ++static int rtl8201_config_intr(struct phy_device *phydev) ++{ ++ u16 val; ++ int err; ++ ++ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { ++ err = rtl8201_ack_interrupt(phydev); ++ if (err) ++ return err; ++ ++ val = BIT(13) | BIT(12) | BIT(11); ++ err = phy_write_paged(phydev, 0x7, RTL8201F_IER, val); ++ } else { ++ val = 0; ++ err = phy_write_paged(phydev, 0x7, RTL8201F_IER, val); ++ if (err) ++ return err; ++ ++ err = rtl8201_ack_interrupt(phydev); ++ } ++ ++ return err; ++} ++ ++static int rtl8211b_config_intr(struct phy_device *phydev) ++{ ++ int err; ++ ++ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { ++ err = rtl821x_ack_interrupt(phydev); ++ if (err) ++ return err; ++ ++ err = phy_write(phydev, RTL821x_INER, ++ RTL8211B_INER_INIT); ++ } else { ++ err = phy_write(phydev, RTL821x_INER, 0); ++ if (err) ++ return err; ++ ++ err = rtl821x_ack_interrupt(phydev); ++ } ++ ++ return err; ++} ++ ++static int rtl8211e_config_intr(struct phy_device *phydev) ++{ ++ int err; ++ ++ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { ++ err = rtl821x_ack_interrupt(phydev); ++ if (err) ++ return err; ++ ++ err = phy_write(phydev, RTL821x_INER, ++ RTL8211E_INER_LINK_STATUS); ++ } else { ++ err = phy_write(phydev, RTL821x_INER, 0); ++ if (err) ++ return err; ++ ++ err = rtl821x_ack_interrupt(phydev); ++ } ++ ++ return err; ++} ++ ++static int rtl8211f_config_intr(struct phy_device *phydev) ++{ ++ u16 val; ++ int err; ++ ++ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { ++ err = rtl8211f_ack_interrupt(phydev); ++ if (err) ++ return err; ++ ++ val = RTL8211F_INER_LINK_STATUS; ++ err = phy_write_paged(phydev, 0xa42, RTL821x_INER, val); ++ } else { ++ val = 0; ++ err = phy_write_paged(phydev, 0xa42, RTL821x_INER, val); ++ if (err) ++ return err; ++ ++ err = rtl8211f_ack_interrupt(phydev); ++ } ++ ++ return err; ++} ++ ++static irqreturn_t rtl8201_handle_interrupt(struct phy_device *phydev) ++{ ++ int irq_status; ++ ++ irq_status = phy_read(phydev, RTL8201F_ISR); ++ if (irq_status < 0) { ++ phy_error(phydev); ++ return IRQ_NONE; ++ } ++ ++ if (!(irq_status & RTL8201F_ISR_MASK)) ++ return IRQ_NONE; ++ ++ phy_trigger_machine(phydev); ++ ++ return IRQ_HANDLED; ++} ++ ++static irqreturn_t rtl821x_handle_interrupt(struct phy_device *phydev) ++{ ++ int irq_status, irq_enabled; ++ ++ irq_status = phy_read(phydev, RTL821x_INSR); ++ if (irq_status < 0) { ++ phy_error(phydev); ++ return IRQ_NONE; ++ } ++ ++ irq_enabled = phy_read(phydev, RTL821x_INER); ++ if (irq_enabled < 0) { ++ phy_error(phydev); ++ return IRQ_NONE; ++ } ++ ++ if (!(irq_status & irq_enabled)) ++ return IRQ_NONE; ++ ++ phy_trigger_machine(phydev); ++ ++ return IRQ_HANDLED; ++} ++ ++static irqreturn_t rtl8211f_handle_interrupt(struct phy_device *phydev) ++{ ++ int irq_status; ++ ++ irq_status = phy_read_paged(phydev, 0xa43, RTL8211F_INSR); ++ if (irq_status < 0) { ++ phy_error(phydev); ++ return IRQ_NONE; ++ } ++ ++ if (!(irq_status & RTL8211F_INER_LINK_STATUS)) ++ return IRQ_NONE; ++ ++ phy_trigger_machine(phydev); ++ ++ return IRQ_HANDLED; ++} ++ ++static int rtl8211_config_aneg(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = genphy_config_aneg(phydev); ++ if (ret < 0) ++ return ret; ++ ++ /* Quirk was copied from vendor driver. Unfortunately it includes no ++ * description of the magic numbers. ++ */ ++ if (phydev->speed == SPEED_100 && phydev->autoneg == AUTONEG_DISABLE) { ++ phy_write(phydev, 0x17, 0x2138); ++ phy_write(phydev, 0x0e, 0x0260); ++ } else { ++ phy_write(phydev, 0x17, 0x2108); ++ phy_write(phydev, 0x0e, 0x0000); ++ } ++ ++ return 0; ++} ++ ++static int rtl8211c_config_init(struct phy_device *phydev) ++{ ++ /* RTL8211C has an issue when operating in Gigabit slave mode */ ++ return phy_set_bits(phydev, MII_CTRL1000, ++ CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER); ++} ++ ++static int rtl8211f_config_init(struct phy_device *phydev) ++{ ++ struct rtl821x_priv *priv = phydev->priv; ++ struct device *dev = &phydev->mdio.dev; ++ u16 val_txdly, val_rxdly; ++ int ret; ++ ++ ret = phy_modify_paged_changed(phydev, 0xa43, RTL8211F_PHYCR1, ++ RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF, ++ priv->phycr1); ++ if (ret < 0) { ++ dev_err(dev, "aldps mode configuration failed: %pe\n", ++ ERR_PTR(ret)); ++ return ret; ++ } ++ ++ switch (phydev->interface) { ++ case PHY_INTERFACE_MODE_RGMII: ++ val_txdly = 0; ++ val_rxdly = 0; ++ break; ++ ++ case PHY_INTERFACE_MODE_RGMII_RXID: ++ val_txdly = 0; ++ val_rxdly = RTL8211F_RX_DELAY; ++ break; ++ ++ case PHY_INTERFACE_MODE_RGMII_TXID: ++ val_txdly = RTL8211F_TX_DELAY; ++ val_rxdly = 0; ++ break; ++ ++ case PHY_INTERFACE_MODE_RGMII_ID: ++ val_txdly = RTL8211F_TX_DELAY; ++ val_rxdly = RTL8211F_RX_DELAY; ++ break; ++ ++ default: /* the rest of the modes imply leaving delay as is. */ ++ return 0; ++ } ++ ++ ret = phy_modify_paged_changed(phydev, 0xd08, 0x11, RTL8211F_TX_DELAY, ++ val_txdly); ++ if (ret < 0) { ++ dev_err(dev, "Failed to update the TX delay register\n"); ++ return ret; ++ } else if (ret) { ++ dev_dbg(dev, ++ "%s 2ns TX delay (and changing the value from pin-strapping RXD1 or the bootloader)\n", ++ val_txdly ? "Enabling" : "Disabling"); ++ } else { ++ dev_dbg(dev, ++ "2ns TX delay was already %s (by pin-strapping RXD1 or bootloader configuration)\n", ++ val_txdly ? "enabled" : "disabled"); ++ } ++ ++ ret = phy_modify_paged_changed(phydev, 0xd08, 0x15, RTL8211F_RX_DELAY, ++ val_rxdly); ++ if (ret < 0) { ++ dev_err(dev, "Failed to update the RX delay register\n"); ++ return ret; ++ } else if (ret) { ++ dev_dbg(dev, ++ "%s 2ns RX delay (and changing the value from pin-strapping RXD0 or the bootloader)\n", ++ val_rxdly ? "Enabling" : "Disabling"); ++ } else { ++ dev_dbg(dev, ++ "2ns RX delay was already %s (by pin-strapping RXD0 or bootloader configuration)\n", ++ val_rxdly ? "enabled" : "disabled"); ++ } ++ ++ if (priv->has_phycr2) { ++ ret = phy_modify_paged(phydev, 0xa43, RTL8211F_PHYCR2, ++ RTL8211F_CLKOUT_EN, priv->phycr2); ++ if (ret < 0) { ++ dev_err(dev, "clkout configuration failed: %pe\n", ++ ERR_PTR(ret)); ++ return ret; ++ } ++ ++ return genphy_soft_reset(phydev); ++ } ++ ++ return 0; ++} ++ ++static int rtl821x_suspend(struct phy_device *phydev) ++{ ++ struct rtl821x_priv *priv = phydev->priv; ++ int ret = 0; ++ ++ if (!phydev->wol_enabled) { ++ ret = genphy_suspend(phydev); ++ ++ if (ret) ++ return ret; ++ ++ clk_disable_unprepare(priv->clk); ++ } ++ ++ return ret; ++} ++ ++static int rtl821x_resume(struct phy_device *phydev) ++{ ++ struct rtl821x_priv *priv = phydev->priv; ++ int ret; ++ ++ if (!phydev->wol_enabled) ++ clk_prepare_enable(priv->clk); ++ ++ ret = genphy_resume(phydev); ++ if (ret < 0) ++ return ret; ++ ++ msleep(20); ++ ++ return 0; ++} ++ ++static int rtl8211f_led_hw_is_supported(struct phy_device *phydev, u8 index, ++ unsigned long rules) ++{ ++ const unsigned long mask = BIT(TRIGGER_NETDEV_LINK_10) | ++ BIT(TRIGGER_NETDEV_LINK_100) | ++ BIT(TRIGGER_NETDEV_LINK_1000) | ++ BIT(TRIGGER_NETDEV_RX) | ++ BIT(TRIGGER_NETDEV_TX); ++ ++ /* The RTL8211F PHY supports these LED settings on up to three LEDs: ++ * - Link: Configurable subset of 10/100/1000 link rates ++ * - Active: Blink on activity, RX or TX is not differentiated ++ * The Active option has two modes, A and B: ++ * - A: Link and Active indication at configurable, but matching, ++ * subset of 10/100/1000 link rates ++ * - B: Link indication at configurable subset of 10/100/1000 link ++ * rates and Active indication always at all three 10+100+1000 ++ * link rates. ++ * This code currently uses mode B only. ++ */ ++ ++ if (index >= RTL8211F_LED_COUNT) ++ return -EINVAL; ++ ++ /* Filter out any other unsupported triggers. */ ++ if (rules & ~mask) ++ return -EOPNOTSUPP; ++ ++ /* RX and TX are not differentiated, either both are set or not set. */ ++ if (!(rules & BIT(TRIGGER_NETDEV_RX)) ^ !(rules & BIT(TRIGGER_NETDEV_TX))) ++ return -EOPNOTSUPP; ++ ++ return 0; ++} ++ ++static int rtl8211f_led_hw_control_get(struct phy_device *phydev, u8 index, ++ unsigned long *rules) ++{ ++ int val; ++ ++ if (index >= RTL8211F_LED_COUNT) ++ return -EINVAL; ++ ++ val = phy_read_paged(phydev, 0xd04, RTL8211F_LEDCR); ++ if (val < 0) ++ return val; ++ ++ val >>= RTL8211F_LEDCR_SHIFT * index; ++ val &= RTL8211F_LEDCR_MASK; ++ ++ if (val & RTL8211F_LEDCR_LINK_10) ++ set_bit(TRIGGER_NETDEV_LINK_10, rules); ++ ++ if (val & RTL8211F_LEDCR_LINK_100) ++ set_bit(TRIGGER_NETDEV_LINK_100, rules); ++ ++ if (val & RTL8211F_LEDCR_LINK_1000) ++ set_bit(TRIGGER_NETDEV_LINK_1000, rules); ++ ++ if (val & RTL8211F_LEDCR_ACT_TXRX) { ++ set_bit(TRIGGER_NETDEV_RX, rules); ++ set_bit(TRIGGER_NETDEV_TX, rules); ++ } ++ ++ return 0; ++} ++ ++static int rtl8211f_led_hw_control_set(struct phy_device *phydev, u8 index, ++ unsigned long rules) ++{ ++ const u16 mask = RTL8211F_LEDCR_MASK << (RTL8211F_LEDCR_SHIFT * index); ++ u16 reg = 0; ++ ++ if (index >= RTL8211F_LED_COUNT) ++ return -EINVAL; ++ ++ if (test_bit(TRIGGER_NETDEV_LINK_10, &rules)) ++ reg |= RTL8211F_LEDCR_LINK_10; ++ ++ if (test_bit(TRIGGER_NETDEV_LINK_100, &rules)) ++ reg |= RTL8211F_LEDCR_LINK_100; ++ ++ if (test_bit(TRIGGER_NETDEV_LINK_1000, &rules)) ++ reg |= RTL8211F_LEDCR_LINK_1000; ++ ++ if (test_bit(TRIGGER_NETDEV_RX, &rules) || ++ test_bit(TRIGGER_NETDEV_TX, &rules)) { ++ reg |= RTL8211F_LEDCR_ACT_TXRX; ++ } ++ ++ reg <<= RTL8211F_LEDCR_SHIFT * index; ++ reg |= RTL8211F_LEDCR_MODE; /* Mode B */ ++ ++ return phy_modify_paged(phydev, 0xd04, RTL8211F_LEDCR, mask, reg); ++} ++ ++static int rtl8211e_config_init(struct phy_device *phydev) ++{ ++ int ret = 0, oldpage; ++ u16 val; ++ ++ /* enable TX/RX delay for rgmii-* modes, and disable them for rgmii. */ ++ switch (phydev->interface) { ++ case PHY_INTERFACE_MODE_RGMII: ++ val = RTL8211E_CTRL_DELAY | 0; ++ break; ++ case PHY_INTERFACE_MODE_RGMII_ID: ++ val = RTL8211E_CTRL_DELAY | RTL8211E_TX_DELAY | RTL8211E_RX_DELAY; ++ break; ++ case PHY_INTERFACE_MODE_RGMII_RXID: ++ val = RTL8211E_CTRL_DELAY | RTL8211E_RX_DELAY; ++ break; ++ case PHY_INTERFACE_MODE_RGMII_TXID: ++ val = RTL8211E_CTRL_DELAY | RTL8211E_TX_DELAY; ++ break; ++ default: /* the rest of the modes imply leaving delays as is. */ ++ return 0; ++ } ++ ++ /* According to a sample driver there is a 0x1c config register on the ++ * 0xa4 extension page (0x7) layout. It can be used to disable/enable ++ * the RX/TX delays otherwise controlled by RXDLY/TXDLY pins. ++ * The configuration register definition: ++ * 14 = reserved ++ * 13 = Force Tx RX Delay controlled by bit12 bit11, ++ * 12 = RX Delay, 11 = TX Delay ++ * 10:0 = Test && debug settings reserved by realtek ++ */ ++ oldpage = phy_select_page(phydev, 0x7); ++ if (oldpage < 0) ++ goto err_restore_page; ++ ++ ret = __phy_write(phydev, RTL821x_EXT_PAGE_SELECT, 0xa4); ++ if (ret) ++ goto err_restore_page; ++ ++ ret = __phy_modify(phydev, 0x1c, RTL8211E_CTRL_DELAY ++ | RTL8211E_TX_DELAY | RTL8211E_RX_DELAY, ++ val); ++ ++err_restore_page: ++ return phy_restore_page(phydev, oldpage, ret); ++} ++ ++static int rtl8211b_suspend(struct phy_device *phydev) ++{ ++ phy_write(phydev, MII_MMD_DATA, BIT(9)); ++ ++ return genphy_suspend(phydev); ++} ++ ++static int rtl8211b_resume(struct phy_device *phydev) ++{ ++ phy_write(phydev, MII_MMD_DATA, 0); ++ ++ return genphy_resume(phydev); ++} ++ ++static int rtl8366rb_config_init(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = phy_set_bits(phydev, RTL8366RB_POWER_SAVE, ++ RTL8366RB_POWER_SAVE_ON); ++ if (ret) { ++ dev_err(&phydev->mdio.dev, ++ "error enabling power management\n"); ++ } ++ ++ return ret; ++} ++ ++/* get actual speed to cover the downshift case */ ++static void rtlgen_decode_physr(struct phy_device *phydev, int val) ++{ ++ /* bit 3 ++ * 0: Half Duplex ++ * 1: Full Duplex ++ */ ++ if (val & RTL_VND2_PHYSR_DUPLEX) ++ phydev->duplex = DUPLEX_FULL; ++ else ++ phydev->duplex = DUPLEX_HALF; ++ ++ switch (val & RTL_VND2_PHYSR_SPEED_MASK) { ++ case 0x0000: ++ phydev->speed = SPEED_10; ++ break; ++ case 0x0010: ++ phydev->speed = SPEED_100; ++ break; ++ case 0x0020: ++ phydev->speed = SPEED_1000; ++ break; ++ case 0x0200: ++ phydev->speed = SPEED_10000; ++ break; ++ case 0x0210: ++ phydev->speed = SPEED_2500; ++ break; ++ case 0x0220: ++ phydev->speed = SPEED_5000; ++ break; ++ default: ++ break; ++ } ++ ++ /* bit 11 ++ * 0: Slave Mode ++ * 1: Master Mode ++ */ ++ if (phydev->speed >= 1000) { ++ if (val & RTL_VND2_PHYSR_MASTER) ++ phydev->master_slave_state = MASTER_SLAVE_STATE_MASTER; ++ else ++ phydev->master_slave_state = MASTER_SLAVE_STATE_SLAVE; ++ } else { ++ phydev->master_slave_state = MASTER_SLAVE_STATE_UNSUPPORTED; ++ } ++} ++ ++static int rtlgen_read_status(struct phy_device *phydev) ++{ ++ int ret, val; ++ ++ ret = genphy_read_status(phydev); ++ if (ret < 0) ++ return ret; ++ ++ if (!phydev->link) ++ return 0; ++ ++ val = phy_read_paged(phydev, 0xa43, 0x12); ++ if (val < 0) ++ return val; ++ ++ rtlgen_decode_physr(phydev, val); ++ ++ return 0; ++} ++ ++static int rtlgen_read_mmd(struct phy_device *phydev, int devnum, u16 regnum) ++{ ++ int ret; ++ ++ if (devnum == MDIO_MMD_VEND2) { ++ rtl821x_write_page(phydev, regnum >> 4); ++ ret = __phy_read(phydev, 0x10 + ((regnum & 0xf) >> 1)); ++ rtl821x_write_page(phydev, 0); ++ } else if (devnum == MDIO_MMD_PCS && regnum == MDIO_PCS_EEE_ABLE) { ++ rtl821x_write_page(phydev, 0xa5c); ++ ret = __phy_read(phydev, 0x12); ++ rtl821x_write_page(phydev, 0); ++ } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) { ++ rtl821x_write_page(phydev, 0xa5d); ++ ret = __phy_read(phydev, 0x10); ++ rtl821x_write_page(phydev, 0); ++ } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_LPABLE) { ++ rtl821x_write_page(phydev, 0xa5d); ++ ret = __phy_read(phydev, 0x11); ++ rtl821x_write_page(phydev, 0); ++ } else { ++ ret = -EOPNOTSUPP; ++ } ++ ++ return ret; ++} ++ ++static int rtlgen_write_mmd(struct phy_device *phydev, int devnum, u16 regnum, ++ u16 val) ++{ ++ int ret; ++ ++ if (devnum == MDIO_MMD_VEND2) { ++ rtl821x_write_page(phydev, regnum >> 4); ++ ret = __phy_write(phydev, 0x10 + ((regnum & 0xf) >> 1), val); ++ rtl821x_write_page(phydev, 0); ++ } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) { ++ rtl821x_write_page(phydev, 0xa5d); ++ ret = __phy_write(phydev, 0x10, val); ++ rtl821x_write_page(phydev, 0); ++ } else { ++ ret = -EOPNOTSUPP; ++ } ++ ++ return ret; ++} ++ ++static int rtl822x_read_mmd(struct phy_device *phydev, int devnum, u16 regnum) ++{ ++ int ret = rtlgen_read_mmd(phydev, devnum, regnum); ++ ++ if (ret != -EOPNOTSUPP) ++ return ret; ++ ++ if (devnum == MDIO_MMD_PCS && regnum == MDIO_PCS_EEE_ABLE2) { ++ rtl821x_write_page(phydev, 0xa6e); ++ ret = __phy_read(phydev, 0x16); ++ rtl821x_write_page(phydev, 0); ++ } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV2) { ++ rtl821x_write_page(phydev, 0xa6d); ++ ret = __phy_read(phydev, 0x12); ++ rtl821x_write_page(phydev, 0); ++ } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_LPABLE2) { ++ rtl821x_write_page(phydev, 0xa6d); ++ ret = __phy_read(phydev, 0x10); ++ rtl821x_write_page(phydev, 0); ++ } ++ ++ return ret; ++} ++ ++static int rtl822x_write_mmd(struct phy_device *phydev, int devnum, u16 regnum, ++ u16 val) ++{ ++ int ret = rtlgen_write_mmd(phydev, devnum, regnum, val); ++ ++ if (ret != -EOPNOTSUPP) ++ return ret; ++ ++ if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV2) { ++ rtl821x_write_page(phydev, 0xa6d); ++ ret = __phy_write(phydev, 0x12, val); ++ rtl821x_write_page(phydev, 0); ++ } ++ ++ return ret; ++} ++ ++static int rtl822xb_config_init(struct phy_device *phydev) ++{ ++ bool has_2500, has_sgmii; ++ u16 mode; ++ int ret; ++ ++ has_2500 = test_bit(PHY_INTERFACE_MODE_2500BASEX, ++ phydev->host_interfaces) || ++ phydev->interface == PHY_INTERFACE_MODE_2500BASEX; ++ ++ has_sgmii = test_bit(PHY_INTERFACE_MODE_SGMII, ++ phydev->host_interfaces) || ++ phydev->interface == PHY_INTERFACE_MODE_SGMII; ++ ++ /* fill in possible interfaces */ ++ __assign_bit(PHY_INTERFACE_MODE_2500BASEX, phydev->possible_interfaces, ++ has_2500); ++ __assign_bit(PHY_INTERFACE_MODE_SGMII, phydev->possible_interfaces, ++ has_sgmii); ++ ++ if (!has_2500 && !has_sgmii) ++ return 0; ++ ++ /* determine SerDes option mode */ ++ if (has_2500 && !has_sgmii) { ++ mode = RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX; ++ phydev->rate_matching = RATE_MATCH_PAUSE; ++ } else { ++ mode = RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX_SGMII; ++ phydev->rate_matching = RATE_MATCH_NONE; ++ } ++ ++ /* the following sequence with magic numbers sets up the SerDes ++ * option mode ++ */ ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x75f3, 0); ++ if (ret < 0) ++ return ret; ++ ++ ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND1, ++ RTL822X_VND1_SERDES_OPTION, ++ RTL822X_VND1_SERDES_OPTION_MODE_MASK, ++ mode); ++ if (ret < 0) ++ return ret; ++ ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6a04, 0x0503); ++ if (ret < 0) ++ return ret; ++ ++ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f10, 0xd455); ++ if (ret < 0) ++ return ret; ++ ++ return phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x6f11, 0x8020); ++} ++ ++static int rtl822xb_get_rate_matching(struct phy_device *phydev, ++ phy_interface_t iface) ++{ ++ int val; ++ ++ /* Only rate matching at 2500base-x */ ++ if (iface != PHY_INTERFACE_MODE_2500BASEX) ++ return RATE_MATCH_NONE; ++ ++ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, RTL822X_VND1_SERDES_OPTION); ++ if (val < 0) ++ return val; ++ ++ if ((val & RTL822X_VND1_SERDES_OPTION_MODE_MASK) == ++ RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX) ++ return RATE_MATCH_PAUSE; ++ ++ /* RTL822X_VND1_SERDES_OPTION_MODE_2500BASEX_SGMII */ ++ return RATE_MATCH_NONE; ++} ++ ++static int rtl822x_get_features(struct phy_device *phydev) ++{ ++ int val; ++ ++ val = phy_read_paged(phydev, 0xa61, 0x13); ++ if (val < 0) ++ return val; ++ ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, ++ phydev->supported, val & MDIO_PMA_SPEED_2_5G); ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, ++ phydev->supported, val & MDIO_PMA_SPEED_5G); ++ linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, ++ phydev->supported, val & MDIO_SPEED_10G); ++ ++ return genphy_read_abilities(phydev); ++} ++ ++static int rtl822x_config_aneg(struct phy_device *phydev) ++{ ++ int ret = 0; ++ ++ if (phydev->autoneg == AUTONEG_ENABLE) { ++ u16 adv = linkmode_adv_to_mii_10gbt_adv_t(phydev->advertising); ++ ++ ret = phy_modify_paged_changed(phydev, 0xa5d, 0x12, ++ MDIO_AN_10GBT_CTRL_ADV2_5G | ++ MDIO_AN_10GBT_CTRL_ADV5G, ++ adv); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return __genphy_config_aneg(phydev, ret); ++} ++ ++static void rtl822xb_update_interface(struct phy_device *phydev) ++{ ++ int val; ++ ++ if (!phydev->link) ++ return; ++ ++ /* Change interface according to serdes mode */ ++ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, RTL822X_VND1_SERDES_CTRL3); ++ if (val < 0) ++ return; ++ ++ switch (val & RTL822X_VND1_SERDES_CTRL3_MODE_MASK) { ++ case RTL822X_VND1_SERDES_CTRL3_MODE_2500BASEX: ++ phydev->interface = PHY_INTERFACE_MODE_2500BASEX; ++ break; ++ case RTL822X_VND1_SERDES_CTRL3_MODE_SGMII: ++ phydev->interface = PHY_INTERFACE_MODE_SGMII; ++ break; ++ } ++} ++ ++static int rtl822x_read_status(struct phy_device *phydev) ++{ ++ int lpadv, ret; ++ ++ ret = rtlgen_read_status(phydev); ++ if (ret < 0) ++ return ret; ++ ++ if (phydev->autoneg == AUTONEG_DISABLE || ++ !phydev->autoneg_complete) { ++ mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, 0); ++ return 0; ++ } ++ ++ lpadv = phy_read_paged(phydev, 0xa5d, 0x13); ++ if (lpadv < 0) ++ return lpadv; ++ ++ mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, lpadv); ++ ++ return 0; ++} ++ ++static int rtl822xb_read_status(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = rtl822x_read_status(phydev); ++ if (ret < 0) ++ return ret; ++ ++ rtl822xb_update_interface(phydev); ++ ++ return 0; ++} ++ ++static int rtl822x_c45_get_features(struct phy_device *phydev) ++{ ++ linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT, ++ phydev->supported); ++ ++ return genphy_c45_pma_read_abilities(phydev); ++} ++ ++static int rtl822x_c45_config_aneg(struct phy_device *phydev) ++{ ++ bool changed = false; ++ int ret, val; ++ ++ if (phydev->autoneg == AUTONEG_DISABLE) ++ return genphy_c45_pma_setup_forced(phydev); ++ ++ ret = genphy_c45_an_config_aneg(phydev); ++ if (ret < 0) ++ return ret; ++ if (ret > 0) ++ changed = true; ++ ++ val = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising); ++ ++ /* Vendor register as C45 has no standardized support for 1000BaseT */ ++ ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, RTL822X_VND2_GBCR, ++ ADVERTISE_1000FULL, val); ++ if (ret < 0) ++ return ret; ++ if (ret > 0) ++ changed = true; ++ ++ return genphy_c45_check_and_restart_aneg(phydev, changed); ++} ++ ++static int rtl822x_c45_read_status(struct phy_device *phydev) ++{ ++ int ret, val; ++ ++ ret = genphy_c45_read_status(phydev); ++ if (ret < 0) ++ return ret; ++ ++ if (phydev->autoneg == AUTONEG_DISABLE || ++ !genphy_c45_aneg_done(phydev)) ++ mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, 0); ++ ++ /* Vendor register as C45 has no standardized support for 1000BaseT */ ++ if (phydev->autoneg == AUTONEG_ENABLE) { ++ val = phy_read_mmd(phydev, MDIO_MMD_VEND2, ++ RTL822X_VND2_GANLPAR); ++ if (val < 0) ++ return val; ++ ++ mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, val); ++ } ++ ++ if (!phydev->link) ++ return 0; ++ ++ /* Read actual speed from vendor register. */ ++ val = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL_VND2_PHYSR); ++ if (val < 0) ++ return val; ++ ++ rtlgen_decode_physr(phydev, val); ++ ++ return 0; ++} ++ ++static int rtl822xb_c45_read_status(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = rtl822x_c45_read_status(phydev); ++ if (ret < 0) ++ return ret; ++ ++ rtl822xb_update_interface(phydev); ++ ++ return 0; ++} ++ ++static bool rtlgen_supports_2_5gbps(struct phy_device *phydev) ++{ ++ int val; ++ ++ phy_write(phydev, RTL821x_PAGE_SELECT, 0xa61); ++ val = phy_read(phydev, 0x13); ++ phy_write(phydev, RTL821x_PAGE_SELECT, 0); ++ ++ return val >= 0 && val & MDIO_PMA_SPEED_2_5G; ++} ++ ++/* On internal PHY's MMD reads over C22 always return 0. ++ * Check a MMD register which is known to be non-zero. ++ */ ++static bool rtlgen_supports_mmd(struct phy_device *phydev) ++{ ++ int val; ++ ++ phy_lock_mdio_bus(phydev); ++ __phy_write(phydev, MII_MMD_CTRL, MDIO_MMD_PCS); ++ __phy_write(phydev, MII_MMD_DATA, MDIO_PCS_EEE_ABLE); ++ __phy_write(phydev, MII_MMD_CTRL, MDIO_MMD_PCS | MII_MMD_CTRL_NOINCR); ++ val = __phy_read(phydev, MII_MMD_DATA); ++ phy_unlock_mdio_bus(phydev); ++ ++ return val > 0; ++} ++ ++static int rtlgen_match_phy_device(struct phy_device *phydev) ++{ ++ return phydev->phy_id == RTL_GENERIC_PHYID && ++ !rtlgen_supports_2_5gbps(phydev); ++} ++ ++static int rtl8226_match_phy_device(struct phy_device *phydev) ++{ ++ return phydev->phy_id == RTL_GENERIC_PHYID && ++ rtlgen_supports_2_5gbps(phydev) && ++ rtlgen_supports_mmd(phydev); ++} ++ ++static int rtlgen_is_c45_match(struct phy_device *phydev, unsigned int id, ++ bool is_c45) ++{ ++ if (phydev->is_c45) ++ return is_c45 && (id == phydev->c45_ids.device_ids[1]); ++ else ++ return !is_c45 && (id == phydev->phy_id); ++} ++ ++static int rtl8221b_match_phy_device(struct phy_device *phydev) ++{ ++ return phydev->phy_id == RTL_8221B && rtlgen_supports_mmd(phydev); ++} ++ ++static int rtl8221b_vb_cg_c22_match_phy_device(struct phy_device *phydev) ++{ ++ return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, false); ++} ++ ++static int rtl8221b_vb_cg_c45_match_phy_device(struct phy_device *phydev) ++{ ++ return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, true); ++} ++ ++static int rtl8221b_vn_cg_c22_match_phy_device(struct phy_device *phydev) ++{ ++ return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, false); ++} ++ ++static int rtl8221b_vn_cg_c45_match_phy_device(struct phy_device *phydev) ++{ ++ return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, true); ++} ++ ++static int rtl_internal_nbaset_match_phy_device(struct phy_device *phydev) ++{ ++ if (phydev->is_c45) ++ return false; ++ ++ switch (phydev->phy_id) { ++ case RTL_GENERIC_PHYID: ++ case RTL_8221B: ++ case RTL_8251B: ++ case 0x001cc841: ++ break; ++ default: ++ return false; ++ } ++ ++ return rtlgen_supports_2_5gbps(phydev) && !rtlgen_supports_mmd(phydev); ++} ++ ++static int rtl8251b_c45_match_phy_device(struct phy_device *phydev) ++{ ++ return rtlgen_is_c45_match(phydev, RTL_8251B, true); ++} ++ ++static int rtlgen_resume(struct phy_device *phydev) ++{ ++ int ret = genphy_resume(phydev); ++ ++ /* Internal PHY's from RTL8168h up may not be instantly ready */ ++ msleep(20); ++ ++ return ret; ++} ++ ++static int rtlgen_c45_resume(struct phy_device *phydev) ++{ ++ int ret = genphy_c45_pma_resume(phydev); ++ ++ msleep(20); ++ ++ return ret; ++} ++ ++static int rtl9000a_config_init(struct phy_device *phydev) ++{ ++ phydev->autoneg = AUTONEG_DISABLE; ++ phydev->speed = SPEED_100; ++ phydev->duplex = DUPLEX_FULL; ++ ++ return 0; ++} ++ ++static int rtl9000a_config_aneg(struct phy_device *phydev) ++{ ++ int ret; ++ u16 ctl = 0; ++ ++ switch (phydev->master_slave_set) { ++ case MASTER_SLAVE_CFG_MASTER_FORCE: ++ ctl |= CTL1000_AS_MASTER; ++ break; ++ case MASTER_SLAVE_CFG_SLAVE_FORCE: ++ break; ++ case MASTER_SLAVE_CFG_UNKNOWN: ++ case MASTER_SLAVE_CFG_UNSUPPORTED: ++ return 0; ++ default: ++ phydev_warn(phydev, "Unsupported Master/Slave mode\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ ret = phy_modify_changed(phydev, MII_CTRL1000, CTL1000_AS_MASTER, ctl); ++ if (ret == 1) ++ ret = genphy_soft_reset(phydev); ++ ++ return ret; ++} ++ ++static int rtl9000a_read_status(struct phy_device *phydev) ++{ ++ int ret; ++ ++ phydev->master_slave_get = MASTER_SLAVE_CFG_UNKNOWN; ++ phydev->master_slave_state = MASTER_SLAVE_STATE_UNKNOWN; ++ ++ ret = genphy_update_link(phydev); ++ if (ret) ++ return ret; ++ ++ ret = phy_read(phydev, MII_CTRL1000); ++ if (ret < 0) ++ return ret; ++ if (ret & CTL1000_AS_MASTER) ++ phydev->master_slave_get = MASTER_SLAVE_CFG_MASTER_FORCE; ++ else ++ phydev->master_slave_get = MASTER_SLAVE_CFG_SLAVE_FORCE; ++ ++ ret = phy_read(phydev, MII_STAT1000); ++ if (ret < 0) ++ return ret; ++ if (ret & LPA_1000MSRES) ++ phydev->master_slave_state = MASTER_SLAVE_STATE_MASTER; ++ else ++ phydev->master_slave_state = MASTER_SLAVE_STATE_SLAVE; ++ ++ return 0; ++} ++ ++static int rtl9000a_ack_interrupt(struct phy_device *phydev) ++{ ++ int err; ++ ++ err = phy_read(phydev, RTL8211F_INSR); ++ ++ return (err < 0) ? err : 0; ++} ++ ++static int rtl9000a_config_intr(struct phy_device *phydev) ++{ ++ u16 val; ++ int err; ++ ++ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { ++ err = rtl9000a_ack_interrupt(phydev); ++ if (err) ++ return err; ++ ++ val = (u16)~RTL9000A_GINMR_LINK_STATUS; ++ err = phy_write_paged(phydev, 0xa42, RTL9000A_GINMR, val); ++ } else { ++ val = ~0; ++ err = phy_write_paged(phydev, 0xa42, RTL9000A_GINMR, val); ++ if (err) ++ return err; ++ ++ err = rtl9000a_ack_interrupt(phydev); ++ } ++ ++ return phy_write_paged(phydev, 0xa42, RTL9000A_GINMR, val); ++} ++ ++static irqreturn_t rtl9000a_handle_interrupt(struct phy_device *phydev) ++{ ++ int irq_status; ++ ++ irq_status = phy_read(phydev, RTL8211F_INSR); ++ if (irq_status < 0) { ++ phy_error(phydev); ++ return IRQ_NONE; ++ } ++ ++ if (!(irq_status & RTL8211F_INER_LINK_STATUS)) ++ return IRQ_NONE; ++ ++ phy_trigger_machine(phydev); ++ ++ return IRQ_HANDLED; ++} ++ ++static struct phy_driver realtek_drvs[] = { ++ { ++ PHY_ID_MATCH_EXACT(0x00008201), ++ .name = "RTL8201CP Ethernet", ++ .read_page = rtl821x_read_page, ++ .write_page = rtl821x_write_page, ++ }, { ++ PHY_ID_MATCH_EXACT(0x001cc816), ++ .name = "RTL8201F Fast Ethernet", ++ .config_intr = &rtl8201_config_intr, ++ .handle_interrupt = rtl8201_handle_interrupt, ++ .suspend = genphy_suspend, ++ .resume = genphy_resume, ++ .read_page = rtl821x_read_page, ++ .write_page = rtl821x_write_page, ++ }, { ++ PHY_ID_MATCH_MODEL(0x001cc880), ++ .name = "RTL8208 Fast Ethernet", ++ .read_mmd = genphy_read_mmd_unsupported, ++ .write_mmd = genphy_write_mmd_unsupported, ++ .suspend = genphy_suspend, ++ .resume = genphy_resume, ++ .read_page = rtl821x_read_page, ++ .write_page = rtl821x_write_page, ++ }, { ++ PHY_ID_MATCH_EXACT(0x001cc910), ++ .name = "RTL8211 Gigabit Ethernet", ++ .config_aneg = rtl8211_config_aneg, ++ .read_mmd = &genphy_read_mmd_unsupported, ++ .write_mmd = &genphy_write_mmd_unsupported, ++ .read_page = rtl821x_read_page, ++ .write_page = rtl821x_write_page, ++ }, { ++ PHY_ID_MATCH_EXACT(0x001cc912), ++ .name = "RTL8211B Gigabit Ethernet", ++ .config_intr = &rtl8211b_config_intr, ++ .handle_interrupt = rtl821x_handle_interrupt, ++ .read_mmd = &genphy_read_mmd_unsupported, ++ .write_mmd = &genphy_write_mmd_unsupported, ++ .suspend = rtl8211b_suspend, ++ .resume = rtl8211b_resume, ++ .read_page = rtl821x_read_page, ++ .write_page = rtl821x_write_page, ++ }, { ++ PHY_ID_MATCH_EXACT(0x001cc913), ++ .name = "RTL8211C Gigabit Ethernet", ++ .config_init = rtl8211c_config_init, ++ .read_mmd = &genphy_read_mmd_unsupported, ++ .write_mmd = &genphy_write_mmd_unsupported, ++ .read_page = rtl821x_read_page, ++ .write_page = rtl821x_write_page, ++ }, { ++ PHY_ID_MATCH_EXACT(0x001cc914), ++ .name = "RTL8211DN Gigabit Ethernet", ++ .config_intr = rtl8211e_config_intr, ++ .handle_interrupt = rtl821x_handle_interrupt, ++ .suspend = genphy_suspend, ++ .resume = genphy_resume, ++ .read_page = rtl821x_read_page, ++ .write_page = rtl821x_write_page, ++ }, { ++ PHY_ID_MATCH_EXACT(0x001cc915), ++ .name = "RTL8211E Gigabit Ethernet", ++ .config_init = &rtl8211e_config_init, ++ .config_intr = &rtl8211e_config_intr, ++ .handle_interrupt = rtl821x_handle_interrupt, ++ .suspend = genphy_suspend, ++ .resume = genphy_resume, ++ .read_page = rtl821x_read_page, ++ .write_page = rtl821x_write_page, ++ }, { ++ PHY_ID_MATCH_EXACT(0x001cc916), ++ .name = "RTL8211F Gigabit Ethernet", ++ .probe = rtl821x_probe, ++ .config_init = &rtl8211f_config_init, ++ .read_status = rtlgen_read_status, ++ .config_intr = &rtl8211f_config_intr, ++ .handle_interrupt = rtl8211f_handle_interrupt, ++ .suspend = rtl821x_suspend, ++ .resume = rtl821x_resume, ++ .read_page = rtl821x_read_page, ++ .write_page = rtl821x_write_page, ++ .flags = PHY_ALWAYS_CALL_SUSPEND, ++ .led_hw_is_supported = rtl8211f_led_hw_is_supported, ++ .led_hw_control_get = rtl8211f_led_hw_control_get, ++ .led_hw_control_set = rtl8211f_led_hw_control_set, ++ }, { ++ PHY_ID_MATCH_EXACT(RTL_8211FVD_PHYID), ++ .name = "RTL8211F-VD Gigabit Ethernet", ++ .probe = rtl821x_probe, ++ .config_init = &rtl8211f_config_init, ++ .read_status = rtlgen_read_status, ++ .config_intr = &rtl8211f_config_intr, ++ .handle_interrupt = rtl8211f_handle_interrupt, ++ .suspend = rtl821x_suspend, ++ .resume = rtl821x_resume, ++ .read_page = rtl821x_read_page, ++ .write_page = rtl821x_write_page, ++ .flags = PHY_ALWAYS_CALL_SUSPEND, ++ }, { ++ .name = "Generic FE-GE Realtek PHY", ++ .match_phy_device = rtlgen_match_phy_device, ++ .read_status = rtlgen_read_status, ++ .suspend = genphy_suspend, ++ .resume = rtlgen_resume, ++ .read_page = rtl821x_read_page, ++ .write_page = rtl821x_write_page, ++ .read_mmd = rtlgen_read_mmd, ++ .write_mmd = rtlgen_write_mmd, ++ }, { ++ .name = "RTL8226 2.5Gbps PHY", ++ .match_phy_device = rtl8226_match_phy_device, ++ .get_features = rtl822x_get_features, ++ .config_aneg = rtl822x_config_aneg, ++ .read_status = rtl822x_read_status, ++ .suspend = genphy_suspend, ++ .resume = rtlgen_resume, ++ .read_page = rtl821x_read_page, ++ .write_page = rtl821x_write_page, ++ }, { ++ .match_phy_device = rtl8221b_match_phy_device, ++ .name = "RTL8226B_RTL8221B 2.5Gbps PHY", ++ .get_features = rtl822x_get_features, ++ .config_aneg = rtl822x_config_aneg, ++ .config_init = rtl822xb_config_init, ++ .get_rate_matching = rtl822xb_get_rate_matching, ++ .read_status = rtl822xb_read_status, ++ .suspend = genphy_suspend, ++ .resume = rtlgen_resume, ++ .read_page = rtl821x_read_page, ++ .write_page = rtl821x_write_page, ++ }, { ++ PHY_ID_MATCH_EXACT(0x001cc838), ++ .name = "RTL8226-CG 2.5Gbps PHY", ++ .get_features = rtl822x_get_features, ++ .config_aneg = rtl822x_config_aneg, ++ .read_status = rtl822x_read_status, ++ .suspend = genphy_suspend, ++ .resume = rtlgen_resume, ++ .read_page = rtl821x_read_page, ++ .write_page = rtl821x_write_page, ++ }, { ++ PHY_ID_MATCH_EXACT(0x001cc848), ++ .name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY", ++ .get_features = rtl822x_get_features, ++ .config_aneg = rtl822x_config_aneg, ++ .config_init = rtl822xb_config_init, ++ .get_rate_matching = rtl822xb_get_rate_matching, ++ .read_status = rtl822xb_read_status, ++ .suspend = genphy_suspend, ++ .resume = rtlgen_resume, ++ .read_page = rtl821x_read_page, ++ .write_page = rtl821x_write_page, ++ }, { ++ .match_phy_device = rtl8221b_vb_cg_c22_match_phy_device, ++ .name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)", ++ .get_features = rtl822x_get_features, ++ .config_aneg = rtl822x_config_aneg, ++ .config_init = rtl822xb_config_init, ++ .get_rate_matching = rtl822xb_get_rate_matching, ++ .read_status = rtl822xb_read_status, ++ .suspend = genphy_suspend, ++ .resume = rtlgen_resume, ++ .read_page = rtl821x_read_page, ++ .write_page = rtl821x_write_page, ++ }, { ++ .match_phy_device = rtl8221b_vb_cg_c45_match_phy_device, ++ .name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)", ++ .config_init = rtl822xb_config_init, ++ .get_rate_matching = rtl822xb_get_rate_matching, ++ .get_features = rtl822x_c45_get_features, ++ .config_aneg = rtl822x_c45_config_aneg, ++ .read_status = rtl822xb_c45_read_status, ++ .suspend = genphy_c45_pma_suspend, ++ .resume = rtlgen_c45_resume, ++ }, { ++ .match_phy_device = rtl8221b_vn_cg_c22_match_phy_device, ++ .name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)", ++ .get_features = rtl822x_get_features, ++ .config_aneg = rtl822x_config_aneg, ++ .config_init = rtl822xb_config_init, ++ .get_rate_matching = rtl822xb_get_rate_matching, ++ .read_status = rtl822xb_read_status, ++ .suspend = genphy_suspend, ++ .resume = rtlgen_resume, ++ .read_page = rtl821x_read_page, ++ .write_page = rtl821x_write_page, ++ }, { ++ .match_phy_device = rtl8221b_vn_cg_c45_match_phy_device, ++ .name = "RTL8221B-VN-CG 2.5Gbps PHY (C45)", ++ .config_init = rtl822xb_config_init, ++ .get_rate_matching = rtl822xb_get_rate_matching, ++ .get_features = rtl822x_c45_get_features, ++ .config_aneg = rtl822x_c45_config_aneg, ++ .read_status = rtl822xb_c45_read_status, ++ .suspend = genphy_c45_pma_suspend, ++ .resume = rtlgen_c45_resume, ++ }, { ++ .match_phy_device = rtl8251b_c45_match_phy_device, ++ .name = "RTL8251B 5Gbps PHY", ++ .get_features = rtl822x_get_features, ++ .config_aneg = rtl822x_config_aneg, ++ .read_status = rtl822x_read_status, ++ .suspend = genphy_suspend, ++ .resume = rtlgen_resume, ++ .read_page = rtl821x_read_page, ++ .write_page = rtl821x_write_page, ++ }, { ++ .match_phy_device = rtl_internal_nbaset_match_phy_device, ++ .name = "Realtek Internal NBASE-T PHY", ++ .flags = PHY_IS_INTERNAL, ++ .get_features = rtl822x_get_features, ++ .config_aneg = rtl822x_config_aneg, ++ .read_status = rtl822x_read_status, ++ .suspend = genphy_suspend, ++ .resume = rtlgen_resume, ++ .read_page = rtl821x_read_page, ++ .write_page = rtl821x_write_page, ++ .read_mmd = rtl822x_read_mmd, ++ .write_mmd = rtl822x_write_mmd, ++ }, { ++ PHY_ID_MATCH_EXACT(0x001ccad0), ++ .name = "RTL8224 2.5Gbps PHY", ++ .get_features = rtl822x_c45_get_features, ++ .config_aneg = rtl822x_c45_config_aneg, ++ .read_status = rtl822x_c45_read_status, ++ .suspend = genphy_c45_pma_suspend, ++ .resume = rtlgen_c45_resume, ++ }, { ++ PHY_ID_MATCH_EXACT(0x001cc961), ++ .name = "RTL8366RB Gigabit Ethernet", ++ .config_init = &rtl8366rb_config_init, ++ /* These interrupts are handled by the irq controller ++ * embedded inside the RTL8366RB, they get unmasked when the ++ * irq is requested and ACKed by reading the status register, ++ * which is done by the irqchip code. ++ */ ++ .config_intr = genphy_no_config_intr, ++ .handle_interrupt = genphy_handle_interrupt_no_ack, ++ .suspend = genphy_suspend, ++ .resume = genphy_resume, ++ }, { ++ PHY_ID_MATCH_EXACT(0x001ccb00), ++ .name = "RTL9000AA_RTL9000AN Ethernet", ++ .features = PHY_BASIC_T1_FEATURES, ++ .config_init = rtl9000a_config_init, ++ .config_aneg = rtl9000a_config_aneg, ++ .read_status = rtl9000a_read_status, ++ .config_intr = rtl9000a_config_intr, ++ .handle_interrupt = rtl9000a_handle_interrupt, ++ .suspend = genphy_suspend, ++ .resume = genphy_resume, ++ .read_page = rtl821x_read_page, ++ .write_page = rtl821x_write_page, ++ }, { ++ PHY_ID_MATCH_EXACT(0x001cc942), ++ .name = "RTL8365MB-VC Gigabit Ethernet", ++ /* Interrupt handling analogous to RTL8366RB */ ++ .config_intr = genphy_no_config_intr, ++ .handle_interrupt = genphy_handle_interrupt_no_ack, ++ .suspend = genphy_suspend, ++ .resume = genphy_resume, ++ }, { ++ PHY_ID_MATCH_EXACT(0x001cc960), ++ .name = "RTL8366S Gigabit Ethernet", ++ .suspend = genphy_suspend, ++ .resume = genphy_resume, ++ .read_mmd = genphy_read_mmd_unsupported, ++ .write_mmd = genphy_write_mmd_unsupported, ++ }, ++}; ++ ++module_phy_driver(realtek_drvs); ++ ++static const struct mdio_device_id __maybe_unused realtek_tbl[] = { ++ { PHY_ID_MATCH_VENDOR(0x001cc800) }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(mdio, realtek_tbl); diff --git a/target/linux/generic/backport-6.6/781-22-v6.14-net-phy-realtek-add-hwmon-support-for-temp-sensor-on.patch b/target/linux/generic/backport-6.6/781-22-v6.14-net-phy-realtek-add-hwmon-support-for-temp-sensor-on.patch new file mode 100644 index 00000000000000..4c1e2f06240407 --- /dev/null +++ b/target/linux/generic/backport-6.6/781-22-v6.14-net-phy-realtek-add-hwmon-support-for-temp-sensor-on.patch @@ -0,0 +1,180 @@ +From 33700ca45b7d2e1655d4cad95e25671e8a94e2f0 Mon Sep 17 00:00:00 2001 +From: Heiner Kallweit +Date: Sat, 11 Jan 2025 21:51:24 +0100 +Subject: [PATCH] net: phy: realtek: add hwmon support for temp sensor on + RTL822x + +This adds hwmon support for the temperature sensor on RTL822x. +It's available on the standalone versions of the PHY's, and on +the integrated PHY's in RTL8125B/RTL8125D/RTL8126. + +Signed-off-by: Heiner Kallweit +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/ad6bfe9f-6375-4a00-84b4-bfb38a21bd71@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/realtek/Kconfig | 6 ++ + drivers/net/phy/realtek/Makefile | 1 + + drivers/net/phy/realtek/realtek.h | 10 ++++ + drivers/net/phy/realtek/realtek_hwmon.c | 79 +++++++++++++++++++++++++ + drivers/net/phy/realtek/realtek_main.c | 12 ++++ + 5 files changed, 108 insertions(+) + create mode 100644 drivers/net/phy/realtek/realtek.h + create mode 100644 drivers/net/phy/realtek/realtek_hwmon.c + +--- a/drivers/net/phy/realtek/Kconfig ++++ b/drivers/net/phy/realtek/Kconfig +@@ -3,3 +3,9 @@ config REALTEK_PHY + tristate "Realtek PHYs" + help + Currently supports RTL821x/RTL822x and fast ethernet PHYs ++ ++config REALTEK_PHY_HWMON ++ def_bool REALTEK_PHY && HWMON ++ depends on !(REALTEK_PHY=y && HWMON=m) ++ help ++ Optional hwmon support for the temperature sensor +--- a/drivers/net/phy/realtek/Makefile ++++ b/drivers/net/phy/realtek/Makefile +@@ -1,3 +1,4 @@ + # SPDX-License-Identifier: GPL-2.0 + realtek-y += realtek_main.o ++realtek-$(CONFIG_REALTEK_PHY_HWMON) += realtek_hwmon.o + obj-$(CONFIG_REALTEK_PHY) += realtek.o +--- /dev/null ++++ b/drivers/net/phy/realtek/realtek.h +@@ -0,0 +1,10 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++ ++#ifndef REALTEK_H ++#define REALTEK_H ++ ++#include ++ ++int rtl822x_hwmon_init(struct phy_device *phydev); ++ ++#endif /* REALTEK_H */ +--- /dev/null ++++ b/drivers/net/phy/realtek/realtek_hwmon.c +@@ -0,0 +1,86 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * HWMON support for Realtek PHY's ++ * ++ * Author: Heiner Kallweit ++ */ ++ ++#include ++#include ++ ++#include "realtek.h" ++ ++#define RTL822X_VND2_TSALRM 0xa662 ++#define RTL822X_VND2_TSRR 0xbd84 ++#define RTL822X_VND2_TSSR 0xb54c ++ ++static umode_t rtl822x_hwmon_is_visible(const void *drvdata, ++ enum hwmon_sensor_types type, ++ u32 attr, int channel) ++{ ++ return 0444; ++} ++ ++static int rtl822x_hwmon_get_temp(int raw) ++{ ++ if (raw >= 512) ++ raw -= 1024; ++ ++ return 1000 * raw / 2; ++} ++ ++static int rtl822x_hwmon_read(struct device *dev, enum hwmon_sensor_types type, ++ u32 attr, int channel, long *val) ++{ ++ struct phy_device *phydev = dev_get_drvdata(dev); ++ int raw; ++ ++ switch (attr) { ++ case hwmon_temp_input: ++ raw = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL822X_VND2_TSRR) & 0x3ff; ++ *val = rtl822x_hwmon_get_temp(raw); ++ break; ++ case hwmon_temp_max: ++ /* Chip reduces speed to 1G if threshold is exceeded */ ++ raw = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL822X_VND2_TSSR) >> 6; ++ *val = rtl822x_hwmon_get_temp(raw); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static const struct hwmon_ops rtl822x_hwmon_ops = { ++ .is_visible = rtl822x_hwmon_is_visible, ++ .read = rtl822x_hwmon_read, ++}; ++ ++static const struct hwmon_channel_info * const rtl822x_hwmon_info[] = { ++ HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MAX), ++ NULL ++}; ++ ++static const struct hwmon_chip_info rtl822x_hwmon_chip_info = { ++ .ops = &rtl822x_hwmon_ops, ++ .info = rtl822x_hwmon_info, ++}; ++ ++int rtl822x_hwmon_init(struct phy_device *phydev) ++{ ++ struct device *hwdev, *dev = &phydev->mdio.dev; ++ const char *name; ++ ++ /* Ensure over-temp alarm is reset. */ ++ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, RTL822X_VND2_TSALRM, 3); ++ ++ name = devm_hwmon_sanitize_name(dev, dev_name(dev)); ++ if (IS_ERR(name)) ++ return PTR_ERR(name); ++ ++ hwdev = devm_hwmon_device_register_with_info(dev, name, phydev, ++ &rtl822x_hwmon_chip_info, ++ NULL); ++ return PTR_ERR_OR_ZERO(hwdev); ++} +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -14,6 +14,8 @@ + #include + #include + ++#include "realtek.h" ++ + #define RTL821x_PHYSR 0x11 + #define RTL821x_PHYSR_DUPLEX BIT(13) + #define RTL821x_PHYSR_SPEED GENMASK(15, 14) +@@ -820,6 +822,15 @@ static int rtl822x_write_mmd(struct phy_ + return ret; + } + ++static int rtl822x_probe(struct phy_device *phydev) ++{ ++ if (IS_ENABLED(CONFIG_REALTEK_PHY_HWMON) && ++ phydev->phy_id != RTL_GENERIC_PHYID) ++ return rtl822x_hwmon_init(phydev); ++ ++ return 0; ++} ++ + static int rtl822xb_config_init(struct phy_device *phydev) + { + bool has_2500, has_sgmii; +@@ -1519,6 +1530,7 @@ static struct phy_driver realtek_drvs[] + .match_phy_device = rtl_internal_nbaset_match_phy_device, + .name = "Realtek Internal NBASE-T PHY", + .flags = PHY_IS_INTERNAL, ++ .probe = rtl822x_probe, + .get_features = rtl822x_get_features, + .config_aneg = rtl822x_config_aneg, + .read_status = rtl822x_read_status, diff --git a/target/linux/generic/pending-6.6/720-01-net-phy-realtek-use-genphy_soft_reset-for-2.5G-PHYs.patch b/target/linux/generic/pending-6.6/720-01-net-phy-realtek-use-genphy_soft_reset-for-2.5G-PHYs.patch index 8de57707a267c4..52ffc7a0f96d42 100644 --- a/target/linux/generic/pending-6.6/720-01-net-phy-realtek-use-genphy_soft_reset-for-2.5G-PHYs.patch +++ b/target/linux/generic/pending-6.6/720-01-net-phy-realtek-use-genphy_soft_reset-for-2.5G-PHYs.patch @@ -10,12 +10,12 @@ the PHY. Reported-by: Yevhen Kolomeiko Signed-off-by: Daniel Golle --- - drivers/net/phy/realtek.c | 6 ++++++ + drivers/net/phy/realtek/realtek_main.c | 6 ++++++ 1 file changed, 6 insertions(+) ---- a/drivers/net/phy/realtek.c -+++ b/drivers/net/phy/realtek.c -@@ -1412,6 +1412,7 @@ static struct phy_driver realtek_drvs[] +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -1431,6 +1431,7 @@ static struct phy_driver realtek_drvs[] }, { .name = "RTL8226 2.5Gbps PHY", .match_phy_device = rtl8226_match_phy_device, @@ -23,7 +23,7 @@ Signed-off-by: Daniel Golle .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, .read_status = rtl822x_read_status, -@@ -1422,6 +1423,7 @@ static struct phy_driver realtek_drvs[] +@@ -1441,6 +1442,7 @@ static struct phy_driver realtek_drvs[] }, { .match_phy_device = rtl8221b_match_phy_device, .name = "RTL8226B_RTL8221B 2.5Gbps PHY", @@ -31,7 +31,7 @@ Signed-off-by: Daniel Golle .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, .config_init = rtl822xb_config_init, -@@ -1434,6 +1436,7 @@ static struct phy_driver realtek_drvs[] +@@ -1453,6 +1455,7 @@ static struct phy_driver realtek_drvs[] }, { PHY_ID_MATCH_EXACT(0x001cc838), .name = "RTL8226-CG 2.5Gbps PHY", @@ -39,7 +39,7 @@ Signed-off-by: Daniel Golle .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, .read_status = rtl822x_read_status, -@@ -1444,6 +1447,7 @@ static struct phy_driver realtek_drvs[] +@@ -1463,6 +1466,7 @@ static struct phy_driver realtek_drvs[] }, { PHY_ID_MATCH_EXACT(0x001cc848), .name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY", @@ -47,7 +47,7 @@ Signed-off-by: Daniel Golle .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, .config_init = rtl822xb_config_init, -@@ -1456,6 +1460,7 @@ static struct phy_driver realtek_drvs[] +@@ -1475,6 +1479,7 @@ static struct phy_driver realtek_drvs[] }, { .match_phy_device = rtl8221b_vb_cg_c22_match_phy_device, .name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)", @@ -55,7 +55,7 @@ Signed-off-by: Daniel Golle .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, .config_init = rtl822xb_config_init, -@@ -1468,6 +1473,7 @@ static struct phy_driver realtek_drvs[] +@@ -1487,6 +1492,7 @@ static struct phy_driver realtek_drvs[] }, { .match_phy_device = rtl8221b_vb_cg_c45_match_phy_device, .name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)", @@ -63,7 +63,7 @@ Signed-off-by: Daniel Golle .config_init = rtl822xb_config_init, .get_rate_matching = rtl822xb_get_rate_matching, .get_features = rtl822x_c45_get_features, -@@ -1478,6 +1484,7 @@ static struct phy_driver realtek_drvs[] +@@ -1497,6 +1503,7 @@ static struct phy_driver realtek_drvs[] }, { .match_phy_device = rtl8221b_vn_cg_c22_match_phy_device, .name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)", @@ -71,7 +71,7 @@ Signed-off-by: Daniel Golle .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, .config_init = rtl822xb_config_init, -@@ -1490,6 +1497,7 @@ static struct phy_driver realtek_drvs[] +@@ -1509,6 +1516,7 @@ static struct phy_driver realtek_drvs[] }, { .match_phy_device = rtl8221b_vn_cg_c45_match_phy_device, .name = "RTL8221B-VN-CG 2.5Gbps PHY (C45)", diff --git a/target/linux/generic/pending-6.6/720-02-net-phy-realtek-disable-SGMII-in-band-AN-for-2-5G-PHYs.patch b/target/linux/generic/pending-6.6/720-02-net-phy-realtek-disable-SGMII-in-band-AN-for-2-5G-PHYs.patch index 7e48c16515db8e..edc03b55758ef1 100644 --- a/target/linux/generic/pending-6.6/720-02-net-phy-realtek-disable-SGMII-in-band-AN-for-2-5G-PHYs.patch +++ b/target/linux/generic/pending-6.6/720-02-net-phy-realtek-disable-SGMII-in-band-AN-for-2-5G-PHYs.patch @@ -15,12 +15,12 @@ Reported-by: Yevhen Kolomeiko Tested-by: Yevhen Kolomeiko Signed-off-by: Daniel Golle --- - drivers/net/phy/realtek.c | 27 +++++++++++++++++++++++++-- + drivers/net/phy/realtek/realtek_main.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) ---- a/drivers/net/phy/realtek.c -+++ b/drivers/net/phy/realtek.c -@@ -815,8 +815,8 @@ static int rtl822x_write_mmd(struct phy_ +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -834,8 +834,8 @@ static int rtl822x_probe(struct phy_devi static int rtl822xb_config_init(struct phy_device *phydev) { bool has_2500, has_sgmii; @@ -30,7 +30,7 @@ Signed-off-by: Daniel Golle has_2500 = test_bit(PHY_INTERFACE_MODE_2500BASEX, phydev->host_interfaces) || -@@ -866,7 +866,29 @@ static int rtl822xb_config_init(struct p +@@ -885,7 +885,29 @@ static int rtl822xb_config_init(struct p if (ret < 0) return ret; diff --git a/target/linux/generic/pending-6.6/720-03-net-phy-realtek-make-sure-paged-read-is-protected-by.patch b/target/linux/generic/pending-6.6/720-03-net-phy-realtek-make-sure-paged-read-is-protected-by.patch index 722ec02cdceff0..3a3d0525050e27 100644 --- a/target/linux/generic/pending-6.6/720-03-net-phy-realtek-make-sure-paged-read-is-protected-by.patch +++ b/target/linux/generic/pending-6.6/720-03-net-phy-realtek-make-sure-paged-read-is-protected-by.patch @@ -13,12 +13,12 @@ rtl821x_write_page instead of 3 individually locked MDIO bus operations. Signed-off-by: Daniel Golle --- - drivers/net/phy/realtek.c | 8 +++++--- + drivers/net/phy/realtek/realtek_main.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) ---- a/drivers/net/phy/realtek.c -+++ b/drivers/net/phy/realtek.c -@@ -1093,9 +1093,11 @@ static bool rtlgen_supports_2_5gbps(stru +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -1112,9 +1112,11 @@ static bool rtlgen_supports_2_5gbps(stru { int val; diff --git a/target/linux/generic/pending-6.6/720-04-net-phy-realtek-introduce-rtl822x_probe.patch b/target/linux/generic/pending-6.6/720-04-net-phy-realtek-introduce-rtl822x_probe.patch index 1b9cdada6dbe3b..42873e7bdf8be7 100644 --- a/target/linux/generic/pending-6.6/720-04-net-phy-realtek-introduce-rtl822x_probe.patch +++ b/target/linux/generic/pending-6.6/720-04-net-phy-realtek-introduce-rtl822x_probe.patch @@ -8,12 +8,12 @@ just like for RTL821x 1GE PHYs. Signed-off-by: Daniel Golle --- - drivers/net/phy/realtek.c | 11 +++++++++++ + drivers/net/phy/realtek/realtek_main.c | 11 +++++++++++ 1 file changed, 11 insertions(+) ---- a/drivers/net/phy/realtek.c -+++ b/drivers/net/phy/realtek.c -@@ -80,6 +80,10 @@ +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -82,6 +82,10 @@ #define RTL822X_VND2_GANLPAR 0xa414 @@ -24,11 +24,11 @@ Signed-off-by: Daniel Golle #define RTL8366RB_POWER_SAVE 0x15 #define RTL8366RB_POWER_SAVE_ON BIT(12) -@@ -1189,6 +1193,25 @@ static int rtl8251b_c45_match_phy_device +@@ -1208,6 +1212,25 @@ static int rtl8251b_c45_match_phy_device return rtlgen_is_c45_match(phydev, RTL_8251B, true); } -+static int rtl822x_probe(struct phy_device *phydev) ++static int rtl822x_aldps_probe(struct phy_device *phydev) +{ + struct device *dev = &phydev->mdio.dev; + int val; @@ -50,51 +50,51 @@ Signed-off-by: Daniel Golle static int rtlgen_resume(struct phy_device *phydev) { int ret = genphy_resume(phydev); -@@ -1460,6 +1483,7 @@ static struct phy_driver realtek_drvs[] +@@ -1479,6 +1502,7 @@ static struct phy_driver realtek_drvs[] }, { PHY_ID_MATCH_EXACT(0x001cc838), .name = "RTL8226-CG 2.5Gbps PHY", -+ .probe = rtl822x_probe, ++ .probe = rtl822x_aldps_probe, .soft_reset = genphy_soft_reset, .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, -@@ -1471,6 +1495,7 @@ static struct phy_driver realtek_drvs[] +@@ -1490,6 +1514,7 @@ static struct phy_driver realtek_drvs[] }, { PHY_ID_MATCH_EXACT(0x001cc848), .name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY", -+ .probe = rtl822x_probe, ++ .probe = rtl822x_aldps_probe, .soft_reset = genphy_soft_reset, .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, -@@ -1484,6 +1509,7 @@ static struct phy_driver realtek_drvs[] +@@ -1503,6 +1528,7 @@ static struct phy_driver realtek_drvs[] }, { .match_phy_device = rtl8221b_vb_cg_c22_match_phy_device, .name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)", -+ .probe = rtl822x_probe, ++ .probe = rtl822x_aldps_probe, .soft_reset = genphy_soft_reset, .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, -@@ -1497,6 +1523,7 @@ static struct phy_driver realtek_drvs[] +@@ -1516,6 +1542,7 @@ static struct phy_driver realtek_drvs[] }, { .match_phy_device = rtl8221b_vb_cg_c45_match_phy_device, .name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)", -+ .probe = rtl822x_probe, ++ .probe = rtl822x_aldps_probe, .soft_reset = genphy_soft_reset, .config_init = rtl822xb_config_init, .get_rate_matching = rtl822xb_get_rate_matching, -@@ -1508,6 +1535,7 @@ static struct phy_driver realtek_drvs[] +@@ -1527,6 +1554,7 @@ static struct phy_driver realtek_drvs[] }, { .match_phy_device = rtl8221b_vn_cg_c22_match_phy_device, .name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)", -+ .probe = rtl822x_probe, ++ .probe = rtl822x_aldps_probe, .soft_reset = genphy_soft_reset, .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, -@@ -1521,6 +1549,7 @@ static struct phy_driver realtek_drvs[] +@@ -1540,6 +1568,7 @@ static struct phy_driver realtek_drvs[] }, { .match_phy_device = rtl8221b_vn_cg_c45_match_phy_device, .name = "RTL8221B-VN-CG 2.5Gbps PHY (C45)", -+ .probe = rtl822x_probe, ++ .probe = rtl822x_aldps_probe, .soft_reset = genphy_soft_reset, .config_init = rtl822xb_config_init, .get_rate_matching = rtl822xb_get_rate_matching, diff --git a/target/linux/generic/pending-6.6/720-05-net-phy-realtek-detect-early-version-of-RTL8221B.patch b/target/linux/generic/pending-6.6/720-05-net-phy-realtek-detect-early-version-of-RTL8221B.patch index 63ffd0a0c9303e..39c1929b5f60e0 100644 --- a/target/linux/generic/pending-6.6/720-05-net-phy-realtek-detect-early-version-of-RTL8221B.patch +++ b/target/linux/generic/pending-6.6/720-05-net-phy-realtek-detect-early-version-of-RTL8221B.patch @@ -12,9 +12,9 @@ over the implemented MMDs. Signed-off-by: Daniel Golle [forward-port by @namiltd] Signed-off-by: Mieczyslaw Nalewaj ---- a/drivers/net/phy/realtek.c -+++ b/drivers/net/phy/realtek.c -@@ -1139,10 +1139,32 @@ static int rtl8226_match_phy_device(stru +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -1158,10 +1158,32 @@ static int rtl8226_match_phy_device(stru static int rtlgen_is_c45_match(struct phy_device *phydev, unsigned int id, bool is_c45) { diff --git a/target/linux/generic/pending-6.6/720-06-net-phy-realtek-support-interrupt-of-RTL8221B.patch b/target/linux/generic/pending-6.6/720-06-net-phy-realtek-support-interrupt-of-RTL8221B.patch index c9e15fb4630945..1ab2fe7618dd4a 100644 --- a/target/linux/generic/pending-6.6/720-06-net-phy-realtek-support-interrupt-of-RTL8221B.patch +++ b/target/linux/generic/pending-6.6/720-06-net-phy-realtek-support-interrupt-of-RTL8221B.patch @@ -7,12 +7,12 @@ This commit introduces interrupt support for RTL8221B. Signed-off-by: Jianhui Zhao --- - drivers/net/phy/realtek.c | 47 +++++++++++++++++++++++++++++++++++++++ + drivers/net/phy/realtek/realtek_main.c | 47 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) ---- a/drivers/net/phy/realtek.c -+++ b/drivers/net/phy/realtek.c -@@ -1369,6 +1369,51 @@ static irqreturn_t rtl9000a_handle_inter +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -1388,6 +1388,51 @@ static irqreturn_t rtl9000a_handle_inter return IRQ_HANDLED; } @@ -64,39 +64,39 @@ Signed-off-by: Jianhui Zhao static struct phy_driver realtek_drvs[] = { { PHY_ID_MATCH_EXACT(0x00008201), -@@ -1531,6 +1576,8 @@ static struct phy_driver realtek_drvs[] +@@ -1550,6 +1595,8 @@ static struct phy_driver realtek_drvs[] }, { .match_phy_device = rtl8221b_vb_cg_c22_match_phy_device, .name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)", + .config_intr = rtl8221b_config_intr, + .handle_interrupt = rtl8221b_handle_interrupt, - .probe = rtl822x_probe, + .probe = rtl822x_aldps_probe, .soft_reset = genphy_soft_reset, .get_features = rtl822x_get_features, -@@ -1545,6 +1592,8 @@ static struct phy_driver realtek_drvs[] +@@ -1564,6 +1611,8 @@ static struct phy_driver realtek_drvs[] }, { .match_phy_device = rtl8221b_vb_cg_c45_match_phy_device, .name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)", + .config_intr = rtl8221b_config_intr, + .handle_interrupt = rtl8221b_handle_interrupt, - .probe = rtl822x_probe, + .probe = rtl822x_aldps_probe, .soft_reset = genphy_soft_reset, .config_init = rtl822xb_config_init, -@@ -1557,6 +1606,8 @@ static struct phy_driver realtek_drvs[] +@@ -1576,6 +1625,8 @@ static struct phy_driver realtek_drvs[] }, { .match_phy_device = rtl8221b_vn_cg_c22_match_phy_device, .name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)", + .config_intr = rtl8221b_config_intr, + .handle_interrupt = rtl8221b_handle_interrupt, - .probe = rtl822x_probe, + .probe = rtl822x_aldps_probe, .soft_reset = genphy_soft_reset, .get_features = rtl822x_get_features, -@@ -1571,6 +1622,8 @@ static struct phy_driver realtek_drvs[] +@@ -1590,6 +1641,8 @@ static struct phy_driver realtek_drvs[] }, { .match_phy_device = rtl8221b_vn_cg_c45_match_phy_device, .name = "RTL8221B-VN-CG 2.5Gbps PHY (C45)", + .config_intr = rtl8221b_config_intr, + .handle_interrupt = rtl8221b_handle_interrupt, - .probe = rtl822x_probe, + .probe = rtl822x_aldps_probe, .soft_reset = genphy_soft_reset, .config_init = rtl822xb_config_init, diff --git a/target/linux/generic/pending-6.6/721-net-phy-realtek-clear-1000Base-T-lpa-bits-if-link-is.patch b/target/linux/generic/pending-6.6/721-net-phy-realtek-clear-1000Base-T-lpa-bits-if-link-is.patch new file mode 100644 index 00000000000000..5bc77ed3b83db1 --- /dev/null +++ b/target/linux/generic/pending-6.6/721-net-phy-realtek-clear-1000Base-T-lpa-bits-if-link-is.patch @@ -0,0 +1,78 @@ +From patchwork Wed Jan 15 14:43:35 2025 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Daniel Golle +X-Patchwork-Id: 13940510 +X-Patchwork-Delegate: kuba@kernel.org +Date: Wed, 15 Jan 2025 14:43:35 +0000 +From: Daniel Golle +To: Andrew Lunn , Heiner Kallweit , + Russell King , + "David S. Miller" , + Eric Dumazet , + Jakub Kicinski , Paolo Abeni , + Daniel Golle , + "Russell King (Oracle)" , + netdev@vger.kernel.org, linux-kernel@vger.kernel.org +Subject: [PATCH net 1/3] net: phy: realtek: clear 1000Base-T lpa if link is + down +Message-ID: + <67e38eee4c46b921938fb33f5bc86c8979b9aa33.1736951652.git.daniel@makrotopia.org> +References: +Precedence: bulk +X-Mailing-List: netdev@vger.kernel.org +List-Id: +List-Subscribe: +List-Unsubscribe: +MIME-Version: 1.0 +Content-Disposition: inline +In-Reply-To: +X-Patchwork-Delegate: kuba@kernel.org + +Only read 1000Base-T link partner advertisement if autonegotiation has +completed and otherwise 1000Base-T link partner advertisement bits. + +This fixes bogus 1000Base-T link partner advertisement after link goes +down (eg. by disconnecting the wire). +Fixes: 5cb409b3960e ("net: phy: realtek: clear 1000Base-T link partner advertisement") +Signed-off-by: Daniel Golle +Reviewed-by: Michal Swiatkowski +--- + drivers/net/phy/realtek/realtek_main.c | 19 ++++++++----------- + 1 file changed, 8 insertions(+), 11 deletions(-) + +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -1068,23 +1068,20 @@ static int rtl822x_c45_read_status(struc + { + int ret, val; + +- ret = genphy_c45_read_status(phydev); +- if (ret < 0) +- return ret; +- +- if (phydev->autoneg == AUTONEG_DISABLE || +- !genphy_c45_aneg_done(phydev)) +- mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, 0); +- + /* Vendor register as C45 has no standardized support for 1000BaseT */ +- if (phydev->autoneg == AUTONEG_ENABLE) { ++ if (phydev->autoneg == AUTONEG_ENABLE && genphy_c45_aneg_done(phydev)) { + val = phy_read_mmd(phydev, MDIO_MMD_VEND2, + RTL822X_VND2_GANLPAR); + if (val < 0) + return val; +- +- mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, val); ++ } else { ++ val = 0; + } ++ mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, val); ++ ++ ret = genphy_c45_read_status(phydev); ++ if (ret < 0) ++ return ret; + + if (!phydev->link) + return 0; diff --git a/target/linux/generic/pending-6.6/722-net-phy-realtek-clear-master_slave_state-if-link-is-.patch b/target/linux/generic/pending-6.6/722-net-phy-realtek-clear-master_slave_state-if-link-is-.patch new file mode 100644 index 00000000000000..b7e5f8b58fb012 --- /dev/null +++ b/target/linux/generic/pending-6.6/722-net-phy-realtek-clear-master_slave_state-if-link-is-.patch @@ -0,0 +1,61 @@ +From patchwork Wed Jan 15 14:43:43 2025 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Daniel Golle +X-Patchwork-Id: 13940511 +X-Patchwork-Delegate: kuba@kernel.org +Date: Wed, 15 Jan 2025 14:43:43 +0000 +From: Daniel Golle +To: Andrew Lunn , Heiner Kallweit , + Russell King , + "David S. Miller" , + Eric Dumazet , + Jakub Kicinski , Paolo Abeni , + Daniel Golle , + "Russell King (Oracle)" , + netdev@vger.kernel.org, linux-kernel@vger.kernel.org +Subject: [PATCH net 2/3] net: phy: realtek: clear master_slave_state if link + is down +Message-ID: + <2155887c3a665e4132a034df1e9cfdeec0ae48c9.1736951652.git.daniel@makrotopia.org> +References: +Precedence: bulk +X-Mailing-List: netdev@vger.kernel.org +List-Id: +List-Subscribe: +List-Unsubscribe: +MIME-Version: 1.0 +Content-Disposition: inline +In-Reply-To: +X-Patchwork-Delegate: kuba@kernel.org + +rtlgen_decode_physr() which sets master_slave_state isn't called in case +the link is down and other than rtlgen_read_status(), +rtl822x_c45_read_status() doesn't implicitely clear master_slave_state. + +Avoid stale master_slave_state by always setting it to +MASTER_SLAVE_STATE_UNKNOWN in rtl822x_c45_read_status() in case the link +is down. + +Fixes: 081c9c0265c9 ("net: phy: realtek: read duplex and gbit master from PHYSR register") +Signed-off-by: Daniel Golle +Reviewed-by: Michal Swiatkowski +--- + drivers/net/phy/realtek/realtek_main.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -1083,8 +1083,10 @@ static int rtl822x_c45_read_status(struc + if (ret < 0) + return ret; + +- if (!phydev->link) ++ if (!phydev->link) { ++ phydev->master_slave_state = MASTER_SLAVE_STATE_UNKNOWN; + return 0; ++ } + + /* Read actual speed from vendor register. */ + val = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL_VND2_PHYSR); diff --git a/target/linux/generic/pending-6.6/723-net-phy-realtek-always-clear-10gbase-t-link-partner-.patch b/target/linux/generic/pending-6.6/723-net-phy-realtek-always-clear-10gbase-t-link-partner-.patch new file mode 100644 index 00000000000000..23947c2200ed9d --- /dev/null +++ b/target/linux/generic/pending-6.6/723-net-phy-realtek-always-clear-10gbase-t-link-partner-.patch @@ -0,0 +1,67 @@ +From patchwork Wed Jan 15 14:45:00 2025 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Daniel Golle +X-Patchwork-Id: 13940519 +X-Patchwork-Delegate: kuba@kernel.org +Date: Wed, 15 Jan 2025 14:45:00 +0000 +From: Daniel Golle +To: Andrew Lunn , Heiner Kallweit , + Russell King , + "David S. Miller" , + Eric Dumazet , + Jakub Kicinski , Paolo Abeni , + Daniel Golle , + "Russell King (Oracle)" , + netdev@vger.kernel.org, linux-kernel@vger.kernel.org +Subject: [PATCH net 3/3] net: phy: realtek: always clear NBase-T lpa +Message-ID: + <566d4771d68a1e18d2d48860e25891e468e26551.1736951652.git.daniel@makrotopia.org> +References: +Precedence: bulk +X-Mailing-List: netdev@vger.kernel.org +List-Id: +List-Subscribe: +List-Unsubscribe: +MIME-Version: 1.0 +Content-Disposition: inline +In-Reply-To: +X-Patchwork-Delegate: kuba@kernel.org + +Clear NBase-T link partner advertisement before calling +rtlgen_read_status() to avoid phy_resolve_aneg_linkmode() wrongly +setting speed and duplex. + +This fixes bogus 2.5G/5G/10G link partner advertisement and thus +speed and duplex being set by phy_resolve_aneg_linkmode() due to stale +NBase-T lpa. + +Fixes: 68d5cd09e891 ("net: phy: realtek: change order of calls in C22 read_status()") +Signed-off-by: Daniel Golle +Reviewed-by: Michal Swiatkowski +--- + drivers/net/phy/realtek/realtek_main.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/net/phy/realtek/realtek_main.c ++++ b/drivers/net/phy/realtek/realtek_main.c +@@ -997,15 +997,15 @@ static int rtl822x_read_status(struct ph + { + int lpadv, ret; + ++ mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, 0); ++ + ret = rtlgen_read_status(phydev); + if (ret < 0) + return ret; + + if (phydev->autoneg == AUTONEG_DISABLE || +- !phydev->autoneg_complete) { +- mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, 0); ++ !phydev->autoneg_complete) + return 0; +- } + + lpadv = phy_read_paged(phydev, 0xa5d, 0x13); + if (lpadv < 0) diff --git a/target/linux/mediatek/base-files/etc/hotplug.d/iface/99-mtk-lro b/target/linux/mediatek/base-files/etc/hotplug.d/iface/99-mtk-lro deleted file mode 100755 index 9a2ffaeed870eb..00000000000000 --- a/target/linux/mediatek/base-files/etc/hotplug.d/iface/99-mtk-lro +++ /dev/null @@ -1,14 +0,0 @@ -[ ifup = "$ACTION" ] && { - [ -n "$DEVICE" ] && { - if [ "$INTERFACE" == "lan" ]; then - if [ -f /usr/sbin/ethtool ]; then - ifname=eth0 - lan_ip=`uci -q get network.lan.ipaddr` - ethdrv=`ethtool -i $ifname | grep mtk_soc_eth` - [ -n "$ethdrv" ] && { - ethtool -N $ifname flow-type tcp4 dst-ip $lan_ip loc 0 - } - fi - fi - } -} diff --git a/target/linux/mediatek/base-files/lib/preinit/06_set_rps_sock_flow b/target/linux/mediatek/base-files/lib/preinit/06_set_rps_sock_flow deleted file mode 100644 index 49b1dd1ca6fb9d..00000000000000 --- a/target/linux/mediatek/base-files/lib/preinit/06_set_rps_sock_flow +++ /dev/null @@ -1,6 +0,0 @@ -set_rps_sock_flow() { - echo 1024 > /proc/sys/net/core/rps_sock_flow_entries -} - -boot_hook_add preinit_main set_rps_sock_flow - diff --git a/target/linux/mediatek/patches-6.6/500-gsw-rtl8367s-mt7622-support.patch b/target/linux/mediatek/patches-6.6/500-gsw-rtl8367s-mt7622-support.patch index 73f735828f110d..bb7e7be6d24307 100644 --- a/target/linux/mediatek/patches-6.6/500-gsw-rtl8367s-mt7622-support.patch +++ b/target/linux/mediatek/patches-6.6/500-gsw-rtl8367s-mt7622-support.patch @@ -1,6 +1,6 @@ --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -419,6 +419,12 @@ config ROCKCHIP_PHY +@@ -416,6 +416,12 @@ config ROCKCHIP_PHY help Currently supports the integrated Ethernet PHY. @@ -16,7 +16,7 @@ --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -102,6 +102,7 @@ obj-$(CONFIG_QSEMI_PHY) += qsemi.o - obj-$(CONFIG_REALTEK_PHY) += realtek.o + obj-$(CONFIG_REALTEK_PHY) += realtek/ obj-$(CONFIG_RENESAS_PHY) += uPD60620.o obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o +obj-$(CONFIG_RTL8367S_GSW) += rtk/ diff --git a/target/linux/mediatek/patches-6.6/735-net-phy-realtek-rtl8261n.patch b/target/linux/mediatek/patches-6.6/735-net-phy-realtek-rtl8261n.patch index 40771202c56528..676bd7c093d24c 100644 --- a/target/linux/mediatek/patches-6.6/735-net-phy-realtek-rtl8261n.patch +++ b/target/linux/mediatek/patches-6.6/735-net-phy-realtek-rtl8261n.patch @@ -1,8 +1,8 @@ --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -399,6 +399,8 @@ config REALTEK_PHY - help - Supports the Realtek 821x PHY. +@@ -396,6 +396,8 @@ config QSEMI_PHY + + source "drivers/net/phy/realtek/Kconfig" +source "drivers/net/phy/rtl8261n/Kconfig" + @@ -14,7 +14,7 @@ @@ -100,6 +100,7 @@ obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja obj-y += qcom/ obj-$(CONFIG_QSEMI_PHY) += qsemi.o - obj-$(CONFIG_REALTEK_PHY) += realtek.o + obj-$(CONFIG_REALTEK_PHY) += realtek/ +obj-y += rtl8261n/ obj-$(CONFIG_RENESAS_PHY) += uPD60620.o obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o diff --git a/target/linux/mvebu/image/cortexa9.mk b/target/linux/mvebu/image/cortexa9.mk index d572264866b72e..b5f89aec20c977 100644 --- a/target/linux/mvebu/image/cortexa9.mk +++ b/target/linux/mvebu/image/cortexa9.mk @@ -453,7 +453,7 @@ define Device/wd_cloud-mirror-gen2 $(Device/NAND-128K) DEVICE_VENDOR := Western Digital DEVICE_MODEL := MyCloud Mirror Gen 2 (BWVZ/Grand Teton) - DEVICE_PACKAGES += -uboot-envtools coreutils-stty mkf2fs e2fsprogs \ + DEVICE_PACKAGES += -uboot-envtools mkf2fs e2fsprogs \ partx-utils kmod-hwmon-drivetemp -ppp -kmod-nft-offload -dnsmasq \ -odhcpd-ipv6only DEVICE_DTS := armada-385-wd_cloud-mirror-gen2 diff --git a/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8174-homewrk.dts b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8174-homewrk.dts new file mode 100644 index 00000000000000..0e184452e3063a --- /dev/null +++ b/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq8174-homewrk.dts @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; + +#include "ipq8174-mx4x00.dtsi" + +/ { + model = "Linksys HomeWRK"; + compatible = "linksys,homewrk", "qcom,ipq8074"; + + aliases { + ethernet3 = &dp4; + ethernet4 = &dp5; + }; + + chosen { + bootargs-append = " root=/dev/ubiblock0_1"; + }; +}; + +&qpic_nand { + status = "okay"; + + nand@0 { + reg = <0>; + /* + * Some devices use Micron NAND with with 8 bit ECC + * other AMD/Spansion NAND with 4 bit ECC + *nand-ecc-strength = <4>; + *nand-ecc-step-size = <512>; + */ + nand-bus-width = <8>; + + partitions { + compatible = "qcom,smem-part"; + }; + }; +}; + +&dp2 { + status = "okay"; + phy-handle = <&qca8075_1>; + label = "wan"; +}; + +&dp3 { + status = "okay"; + phy-handle = <&qca8075_2>; + label = "lan3"; +}; + +&dp4 { + status = "okay"; + phy-handle = <&qca8075_3>; + label = "lan2"; +}; + +&dp5 { + status = "okay"; + phy-handle = <&qca8075_4>; + label = "lan1"; +}; + +&wifi { + status = "okay"; + + qcom,ath11k-calibration-variant = "Linksys-HomeWRK"; +}; diff --git a/target/linux/qualcommax/image/ipq807x.mk b/target/linux/qualcommax/image/ipq807x.mk index 260b358ce89655..39fc63827cac45 100644 --- a/target/linux/qualcommax/image/ipq807x.mk +++ b/target/linux/qualcommax/image/ipq807x.mk @@ -156,6 +156,21 @@ define Device/edimax_cax1800 endef TARGET_DEVICES += edimax_cax1800 +define Device/linksys_homewrk + $(call Device/FitImage) + $(call Device/UbiFit) + DEVICE_VENDOR := Linksys + DEVICE_MODEL := HomeWRK + DEVICE_DTS_CONFIG := config@oak03 + BLOCKSIZE := 256k + PAGESIZE := 4096 + IMAGE_SIZE := 475m + NAND_SIZE := 1024m + SOC := ipq8174 + DEVICE_PACKAGES += kmod-leds-pca963x ipq-wifi-linksys_homewrk +endef +TARGET_DEVICES += linksys_homewrk + define Device/linksys_mx $(call Device/FitImage) DEVICE_VENDOR := Linksys diff --git a/target/linux/qualcommax/ipq807x/base-files/etc/board.d/02_network b/target/linux/qualcommax/ipq807x/base-files/etc/board.d/02_network index 5bacbd7dee1ef2..af1d2dfebbec2b 100644 --- a/target/linux/qualcommax/ipq807x/base-files/etc/board.d/02_network +++ b/target/linux/qualcommax/ipq807x/base-files/etc/board.d/02_network @@ -27,6 +27,7 @@ ipq807x_setup_interfaces() ucidef_set_interfaces_lan_wan "lan plc" "wan" ;; compex,wpq873|\ + linksys,homewrk|\ linksys,mx4200v1|\ linksys,mx4200v2|\ linksys,mx4300|\ diff --git a/target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/firmware/11-ath11k-caldata b/target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/firmware/11-ath11k-caldata index 65e064ea4d2fa7..ec772de8eb672a 100644 --- a/target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/firmware/11-ath11k-caldata +++ b/target/linux/qualcommax/ipq807x/base-files/etc/hotplug.d/firmware/11-ath11k-caldata @@ -30,6 +30,7 @@ case "$FIRMWARE" in zte,mf269) caldata_extract "0:art" 0x1000 0x20000 ;; + linksys,homewrk|\ linksys,mx4200v1|\ linksys,mx8500) caldata_extract "0:art" 0x1000 0x20000 diff --git a/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh b/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh index b53ec149fe2a99..2d68ec62ed7594 100644 --- a/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh +++ b/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh @@ -166,6 +166,11 @@ platform_do_upgrade() { fw_setenv upgrade_available 1 nand_do_upgrade "$1" ;; + linksys,homewrk) + CI_UBIPART="rootfs" + remove_oem_ubi_volume ubi_rootfs + nand_do_upgrade "$1" + ;; linksys,mx4200v1|\ linksys,mx4200v2|\ linksys,mx4300|\ diff --git a/target/linux/ramips/dts/mt7621_confiabits_mt7621-v1.dts b/target/linux/ramips/dts/mt7621_confiabits_mt7621-v1.dts new file mode 100644 index 00000000000000..858747ecada399 --- /dev/null +++ b/target/linux/ramips/dts/mt7621_confiabits_mt7621-v1.dts @@ -0,0 +1,215 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "mt7621.dtsi" + +#include +#include +#include + +/ { + compatible = "confiabits,mt7621-v1", "mediatek,mt7621-soc"; + model = "Confiabits MT7621 v1"; + + aliases { + led-boot = &led_power_green; + led-failsafe = &led_power_green; + led-running = &led_power_green; + led-upgrade = &led_power_green; + }; + + chosen { + bootargs = "console=ttyS0,57600"; + }; + + keys { + compatible = "gpio-keys"; + + button-wps { + label = "wps"; + gpios = <&gpio 13 GPIO_ACTIVE_LOW>; + debounce-interval = <60>; + linux,code = ; + }; + + button-reset { + label = "reset"; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; + debounce-interval = <60>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_power_green: led-power-green { + color = ; + function = LED_FUNCTION_POWER; + gpios = <&gpio 3 GPIO_ACTIVE_LOW>; + }; + + led-wan-red { + color = ; + function = LED_FUNCTION_WAN; + gpios = <&gpio 4 GPIO_ACTIVE_LOW>; + }; + + led-wlan5 { + color = ; + function = LED_FUNCTION_WLAN_5GHZ; + gpios = <&gpio 14 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy1tpt"; + }; + + led-wps { + color = ; + function = LED_FUNCTION_WPS; + gpios = <&gpio 15 GPIO_ACTIVE_LOW>; + }; + + led-wlan24 { + color = ; + function = LED_FUNCTION_WLAN_2GHZ; + gpios = <&gpio 16 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy0tpt"; + }; + + led-wan-green { + color = ; + function = LED_FUNCTION_WAN; + gpios = <&gpio 17 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&spi0 { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <40000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + partition@40000 { + label = "radio"; + reg = <0x40000 0x10000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_radio_0: eeprom@0 { + reg = <0x0 0x400>; + }; + + eeprom_radio_8000: eeprom@8000 { + reg = <0x8000 0x4da8>; + }; + + macaddr_radio_4: macaddr@4 { + reg = <0x4 0x6>; + }; + + macaddr_radio_8004: macaddr@8004 { + reg = <0x8004 0x6>; + }; + }; + }; + + partition@50000 { + label = "firmware"; + compatible = "denx,uimage"; + reg = <0x50000 0xfb0000>; + }; + }; + }; +}; + +&gmac0 { + nvmem-cells = <&macaddr_radio_4>; + nvmem-cell-names = "mac-address"; +}; + +&gmac1 { + status = "okay"; + label = "wan"; + phy-handle = <ðphy4>; + + nvmem-cells = <&macaddr_radio_4>; + nvmem-cell-names = "mac-address"; +}; + +ðphy4 { + /delete-property/ interrupts; +}; + +&pcie { + status = "okay"; +}; + +&pcie0 { + wifi@0,0 { + compatible = "mediatek,mt76"; + reg = <0x0000 0 0 0 0>; + ieee80211-freq-limit = <2400000 2500000>; + + nvmem-cells = <&eeprom_radio_0>; + nvmem-cell-names = "eeprom"; + }; +}; + +&pcie1 { + wifi@0,0 { + compatible = "mediatek,mt76"; + reg = <0x0000 0 0 0 0>; + ieee80211-freq-limit = <5000000 6000000>; + + nvmem-cells = <&eeprom_radio_8000>; + nvmem-cell-names = "eeprom"; + }; +}; + +&state_default { + gpio { + groups = "i2c", "jtag", "wdt"; + function = "gpio"; + }; +}; + +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + }; +}; diff --git a/target/linux/ramips/dts/mt7621_keenetic_kn-1910.dts b/target/linux/ramips/dts/mt7621_keenetic_kn-1910.dts new file mode 100644 index 00000000000000..97b7c956882160 --- /dev/null +++ b/target/linux/ramips/dts/mt7621_keenetic_kn-1910.dts @@ -0,0 +1,280 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +#include "mt7621.dtsi" + +#include +#include +#include + +/ { + compatible = "keenetic,kn-1910", "mediatek,mt7621-soc"; + model = "Keenetic KN-1910"; + + aliases { + led-boot = &led_power; + led-failsafe = &led_power; + led-running = &led_power; + led-upgrade = &led_power; + label-mac-device = &gmac0; + }; + + reg_usb_vbus: regulator-usb { + compatible = "regulator-fixed"; + regulator-name = "usb_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpios = <&gpio 5 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "fixed-3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpios = <&gpio 11 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + keys { + compatible = "gpio-keys"; + + restart { + label = "restart"; + gpios = <&gpio 6 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + wps { + label = "wps"; + gpios = <&gpio 12 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + fn1 { + label = "fn1"; + gpios = <&gpio 10 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + fn2 { + label = "fn2"; + gpios = <&gpio 7 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_power: power { + function = LED_FUNCTION_POWER; + color = ; + gpios = <&gpio 9 GPIO_ACTIVE_HIGH>; + }; + + internet { + function = LED_FUNCTION_WAN; + color = ; + gpios = <&gpio 17 GPIO_ACTIVE_HIGH>; + }; + + fn { + function = LED_FUNCTION_WLAN_2GHZ; + color = ; + gpios = <&gpio 13 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy0tpt"; + }; + + wifi { + function = LED_FUNCTION_WLAN_5GHZ; + color = ; + gpios = <&gpio 15 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy1tpt"; + }; + }; + + virtual_flash { + compatible = "mtd-concat"; + devices = <&firmware1 &firmware2 &storage_a &storage_b>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "kernel"; + reg = <0x0 0x400000>; + }; + + partition@400000 { + label = "ubi"; + reg = <0x400000 0x7540000>; + }; + }; + }; +}; + +&xhci { + vbus-supply = <®_usb_vbus>; + vusb33-supply = <®_3p3v>; +}; + +&nand { + status = "okay"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "U-Boot"; + reg = <0x0 0x80000>; + read-only; + }; + + partition@80000 { + label = "U-Config"; + reg = <0x80000 0x80000>; + read-only; + }; + + partition@100000 { + label = "RF-EEPROM"; + reg = <0x100000 0x80000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x4da8>; + }; + + macaddr_factory_4: macaddr@4 { + reg = <0x4 0x6>; + }; + + macaddr_factory_28: macaddr@28 { + reg = <0x28 0x6>; + }; + }; + }; + + firmware1: partition@180000 { + label = "Firmware_1"; + reg = <0x180000 0x1bc0000>; + }; + + partition@1d40000 { + label = "Config_1"; + reg = <0x1d40000 0x80000>; + read-only; + }; + + partition@1dc0000 { + label = "Storage_Legacy"; + reg = <0x1dc0000 0x200000>; + read-only; + }; + + partition@1fc0000 { + label = "Dump"; + reg = <0x1fc0000 0x40000>; + read-only; + }; + + storage_a: partition@2000000 { + label = "Storage_A"; + reg = <0x2000000 0x1fc0000>; + }; + + partition@3fc0000 { + label = "U-State"; + reg = <0x3fc0000 0x80000>; + read-only; + }; + + partition@4040000 { + label = "U-Config_res"; + reg = <0x4040000 0x80000>; + read-only; + }; + + partition@40c0000 { + label = "RF-EEPROM_res"; + reg = <0x40c0000 0x80000>; + read-only; + }; + + firmware2: partition@4140000 { + label = "Firmware_2"; + reg = <0x4140000 0x1bc0000>; + }; + + partition@5d00000 { + label = "Config_2"; + reg = <0x5d00000 0x80000>; + read-only; + }; + + storage_b: partition@5d80000 { + label = "Storage_B"; + reg = <0x5d80000 0x2200000>; + }; + }; +}; + +&pcie { + status = "okay"; +}; + +&pcie0 { + wifi@0,0 { + compatible = "mediatek,mt76"; + reg = <0x0000 0 0 0 0>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; + }; +}; + +ðphy0 { + /delete-property/ interrupts; +}; + +&gmac0 { + nvmem-cells = <&macaddr_factory_4>; + nvmem-cell-names = "mac-address"; +}; + +&gmac1 { + status = "okay"; + label = "wan"; + phy-handle = <ðphy0>; + + nvmem-cells = <&macaddr_factory_28>; + nvmem-cell-names = "mac-address"; +}; + +&switch0 { + ports { + port@1 { + status = "okay"; + }; + + port@2 { + status = "okay"; + }; + + port@3 { + status = "okay"; + }; + + port@4 { + status = "okay"; + }; + }; +}; diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk index ed0da90528799e..08b3dcc64f752d 100755 --- a/target/linux/ramips/image/mt7621.mk +++ b/target/linux/ramips/image/mt7621.mk @@ -687,6 +687,18 @@ define Device/comfast_cf-ew72-v2 endef TARGET_DEVICES += comfast_cf-ew72-v2 +define Device/confiabits_mt7621-v1 + $(Device/dsa-migration) + $(Device/uimage-lzma-loader) + IMAGE_SIZE := 16064k + DEVICE_VENDOR := Confiabits + DEVICE_MODEL := MT7621 + DEVICE_VARIANT := v1 + DEVICE_PACKAGES := kmod-mt7603 kmod-mt7615e kmod-mt7663-firmware-ap \ + -uboot-envtools +endef +TARGET_DEVICES += confiabits_mt7621-v1 + define Device/cudy_m1800 $(Device/dsa-migration) DEVICE_VENDOR := Cudy @@ -1787,6 +1799,22 @@ define Device/jdcloud_re-cp-02 endef TARGET_DEVICES += jdcloud_re-cp-02 +define Device/keenetic_kn-1910 + $(Device/nand) + $(Device/uimage-lzma-loader) + BLOCKSIZE := 128k + PAGESIZE := 2048 + IMAGE_SIZE := 24903680 + DEVICE_VENDOR := Keenetic + DEVICE_MODEL := KN-1910 + DEVICE_PACKAGES := kmod-mt7615-firmware kmod-usb3 \ + kmod-usb-ledtrig-usbport + IMAGES += factory.bin + IMAGE/factory.bin := append-kernel | pad-to $$(KERNEL_SIZE) | \ + append-ubi | check-size | zyimage -d 0x801910 -v "KN-1910" +endef +TARGET_DEVICES += keenetic_kn-1910 + define Device/keenetic_kn-3010 $(Device/dsa-migration) $(Device/uimage-lzma-loader) diff --git a/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds b/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds index 9a77b1b1bc4a65..1542eed8f62e2c 100644 --- a/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds +++ b/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds @@ -58,6 +58,10 @@ wifire,s1500-nbn) belkin,rt1800) ucidef_set_led_netdev "wan" "wan" "white:wan" "wan" ;; +confiabits,mt7621-v1|\ +netis,n6) + ucidef_set_led_netdev "wan" "wan" "green:wan" "wan" "link tx rx" + ;; cudy,wr2100) ucidef_set_led_netdev "lan1" "lan1" "green:lan1" "lan1" ucidef_set_led_netdev "lan2" "lan2" "green:lan2" "lan2" @@ -125,6 +129,7 @@ gnubee,gb-pc2) huasifei,ws1208v2) ucidef_set_led_netdev "wwan0" "wwan0" "green:cellular" "wwan0" "link tx rx" ;; +keenetic,kn-1910|\ keenetic,kn-3010) ucidef_set_led_netdev "internet" "internet" "green:internet" "wan" ;; @@ -188,9 +193,6 @@ netgear,r7450) netgear,wax202) ucidef_set_led_netdev "internet" "Internet" "green:net" "wan" ;; -netis,n6) - ucidef_set_led_netdev "wan" "wan" "green:wan" "wan" "link tx rx" - ;; oraybox,x3a) ucidef_set_led_netdev "wan" "wan link" "red:status" "wan" ucidef_set_led_netdev "lan" "lan link" "green:status" "br-lan" diff --git a/target/linux/ramips/mt7621/base-files/etc/board.d/02_network b/target/linux/ramips/mt7621/base-files/etc/board.d/02_network index c780443c1c58de..f40e9616d019e2 100644 --- a/target/linux/ramips/mt7621/base-files/etc/board.d/02_network +++ b/target/linux/ramips/mt7621/base-files/etc/board.d/02_network @@ -13,6 +13,7 @@ ramips_setup_interfaces() asus,rt-ax53u|\ buffalo,wsr-2533dhpl2|\ buffalo,wsr-2533dhpls|\ + confiabits,mt7621-v1|\ gehua,ghl-r-001|\ h3c,tx1800-plus|\ h3c,tx1801-plus|\ diff --git a/target/linux/realtek/base-files/etc/board.d/03_gpio_switches b/target/linux/realtek/base-files/etc/board.d/03_gpio_switches deleted file mode 100644 index c869153e4ca407..00000000000000 --- a/target/linux/realtek/base-files/etc/board.d/03_gpio_switches +++ /dev/null @@ -1,18 +0,0 @@ - -. /lib/functions/uci-defaults.sh - -board_config_update - -board=$(board_name) - -case "$board" in -hpe,1920-8g-poe-180w|\ -hpe,1920-24g-poe-180w|\ -hpe,1920-24g-poe-370w) - ucidef_add_gpio_switch "fan_ctrl" "Fan control" "456" "0" - ;; -esac - -board_config_flush - -exit 0 diff --git a/target/linux/realtek/base-files/etc/board.d/05_compat-version b/target/linux/realtek/base-files/etc/board.d/05_compat-version index 5c4ecb9aae363d..9c27314b241e4e 100644 --- a/target/linux/realtek/base-files/etc/board.d/05_compat-version +++ b/target/linux/realtek/base-files/etc/board.d/05_compat-version @@ -8,6 +8,11 @@ board_config_update case "$(board_name)" in + hpe,1920-8g-poe-180w | \ + hpe,1920-24g-poe-180w | \ + hpe,1920-24g-poe-370w) + ucidef_set_compat_version "1.1" + ;; zyxel,gs1900-8 | \ zyxel,gs1900-8hp-v1 | \ zyxel,gs1900-8hp-v2 | \ diff --git a/target/linux/realtek/dts/rtl8380_hpe_1920-8g-poe-180w.dts b/target/linux/realtek/dts/rtl8380_hpe_1920-8g-poe-180w.dts index 6398e6d034dee3..f15498354e9ae0 100644 --- a/target/linux/realtek/dts/rtl8380_hpe_1920-8g-poe-180w.dts +++ b/target/linux/realtek/dts/rtl8380_hpe_1920-8g-poe-180w.dts @@ -5,6 +5,17 @@ / { compatible = "hpe,1920-8g-poe-180w", "realtek,rtl838x-soc"; model = "HPE 1920-8G-PoE+ 180W (JG922A)"; + + gpio_fan_array { + compatible = "gpio-fan"; + + gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>; + gpio-fan,speed-map = <5000 0>, + <8200 1>; + + alarm-gpios = <&gpio1 6 GPIO_ACTIVE_LOW>; + #cooling-cells = <2>; + }; }; &uart1 { diff --git a/target/linux/realtek/dts/rtl8382_hpe_1920-24g-poe-180w.dts b/target/linux/realtek/dts/rtl8382_hpe_1920-24g-poe-180w.dts index 4783cec15ca18e..69e647c59a98e2 100644 --- a/target/linux/realtek/dts/rtl8382_hpe_1920-24g-poe-180w.dts +++ b/target/linux/realtek/dts/rtl8382_hpe_1920-24g-poe-180w.dts @@ -5,6 +5,17 @@ / { compatible = "hpe,1920-24g-poe-180w", "realtek,rtl838x-soc"; model = "HPE 1920-24G-PoE+ 180W (JG925A)"; + + gpio_fan_array { + compatible = "gpio-fan"; + + gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>; + gpio-fan,speed-map = <5000 0>, + <8200 1>; + + alarm-gpios = <&gpio1 6 GPIO_ACTIVE_LOW>; + #cooling-cells = <2>; + }; }; &uart1 { diff --git a/target/linux/realtek/dts/rtl8382_hpe_1920-24g-poe-370w.dts b/target/linux/realtek/dts/rtl8382_hpe_1920-24g-poe-370w.dts index ccdcf71d1bddb1..532f23ab2f2b6e 100644 --- a/target/linux/realtek/dts/rtl8382_hpe_1920-24g-poe-370w.dts +++ b/target/linux/realtek/dts/rtl8382_hpe_1920-24g-poe-370w.dts @@ -5,6 +5,17 @@ / { compatible = "hpe,1920-24g-poe-370w", "realtek,rtl838x-soc"; model = "HPE 1920-24G-PoE+ 370W (JG926A)"; + + gpio_fan_array { + compatible = "gpio-fan"; + + gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>; + gpio-fan,speed-map = <5000 0>, + <8200 1>; + + alarm-gpios = <&gpio1 6 GPIO_ACTIVE_LOW>; + #cooling-cells = <2>; + }; }; &uart1 { diff --git a/target/linux/realtek/image/common.mk b/target/linux/realtek/image/common.mk index d9647dbc07288e..e600b2347d71fc 100644 --- a/target/linux/realtek/image/common.mk +++ b/target/linux/realtek/image/common.mk @@ -56,6 +56,14 @@ define Device/hpe_1920 append-metadata endef +define Device/hwmon-fan-migration + DEVICE_COMPAT_VERSION := 1.1 + DEVICE_COMPAT_MESSAGE := Fan control switched to hwmon. Your fans will retain \ + bootloader speed unless another control scheme is in place. \ + Config cannot be kept due to conflict in gpio_switch config 'fan_ctrl' under \ + /etc/config/system. +endef + define Device/zyxel_gs1900 DEVICE_COMPAT_VERSION := 2.0 DEVICE_COMPAT_MESSAGE := Dual firmware paritition merged due to size constraints. \ diff --git a/target/linux/realtek/image/rtl838x.mk b/target/linux/realtek/image/rtl838x.mk index 866659ad141210..34464316c7f21a 100644 --- a/target/linux/realtek/image/rtl838x.mk +++ b/target/linux/realtek/image/rtl838x.mk @@ -120,9 +120,10 @@ TARGET_DEVICES += hpe_1920-8g-poe-65w define Device/hpe_1920-8g-poe-180w $(Device/hpe_1920) + $(Device/hwmon-fan-migration) SOC := rtl8380 DEVICE_MODEL := 1920-8G-PoE+ 180W (JG922A) - DEVICE_PACKAGES += realtek-poe + DEVICE_PACKAGES += realtek-poe kmod-hwmon-gpiofan H3C_DEVICE_ID := 0x00010025 SUPPORTED_DEVICES += hpe_1920-8g-poe endef @@ -146,18 +147,20 @@ TARGET_DEVICES += hpe_1920-24g define Device/hpe_1920-24g-poe-180w $(Device/hpe_1920) + $(Device/hwmon-fan-migration) SOC := rtl8382 DEVICE_MODEL := 1920-24G-PoE+ 180W (JG925A) - DEVICE_PACKAGES += realtek-poe + DEVICE_PACKAGES += realtek-poe kmod-hwmon-gpiofan H3C_DEVICE_ID := 0x00010028 endef TARGET_DEVICES += hpe_1920-24g-poe-180w define Device/hpe_1920-24g-poe-370w $(Device/hpe_1920) + $(Device/hwmon-fan-migration) SOC := rtl8382 DEVICE_MODEL := 1920-24G-PoE+ 370W (JG926A) - DEVICE_PACKAGES += realtek-poe + DEVICE_PACKAGES += realtek-poe kmod-hwmon-gpiofan H3C_DEVICE_ID := 0x00010029 endef TARGET_DEVICES += hpe_1920-24g-poe-370w diff --git a/target/linux/realtek/patches-6.6/720-add-rtl-phy.patch b/target/linux/realtek/patches-6.6/720-add-rtl-phy.patch index 43d4a7d4fccf51..4d6866db24f8c0 100644 --- a/target/linux/realtek/patches-6.6/720-add-rtl-phy.patch +++ b/target/linux/realtek/patches-6.6/720-add-rtl-phy.patch @@ -14,9 +14,9 @@ Submitted-by: Birger Koblitz --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -410,6 +410,12 @@ config REALTEK_PHY - help - Supports the Realtek 821x PHY. +@@ -407,6 +407,12 @@ config QSEMI_PHY + + source "drivers/net/phy/realtek/Kconfig" +config REALTEK_SOC_PHY + tristate "Realtek SoC PHYs" @@ -32,7 +32,7 @@ Submitted-by: Birger Koblitz @@ -100,6 +100,7 @@ obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja obj-y += qcom/ obj-$(CONFIG_QSEMI_PHY) += qsemi.o - obj-$(CONFIG_REALTEK_PHY) += realtek.o + obj-$(CONFIG_REALTEK_PHY) += realtek/ +obj-$(CONFIG_REALTEK_SOC_PHY) += rtl83xx-phy.o obj-$(CONFIG_RENESAS_PHY) += uPD60620.o obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o diff --git a/target/linux/realtek/patches-6.6/723-net-mdio-Add-Realtek-Otto-auxiliary-controller.patch b/target/linux/realtek/patches-6.6/723-net-mdio-Add-Realtek-Otto-auxiliary-controller.patch index 430f8f5c007ecc..a58cc496efe1dc 100644 --- a/target/linux/realtek/patches-6.6/723-net-mdio-Add-Realtek-Otto-auxiliary-controller.patch +++ b/target/linux/realtek/patches-6.6/723-net-mdio-Add-Realtek-Otto-auxiliary-controller.patch @@ -103,7 +103,7 @@ Signed-off-by: Sander Vanheule + if (err) + return err; + -+ err = regmap_read_poll_timeout(ctrl->map, ctrl->cmd_reg, run, (run != cmd), 3, 100); ++ err = regmap_read_poll_timeout_atomic(ctrl->map, ctrl->cmd_reg, run, (run != cmd), 3, 100); + + if ((run & ~mask_volatile) != (cmd & ~mask_volatile)) { + dev_err(ctrl->dev, "Command modified. Is offloading still active?"); diff --git a/tools/meson/Makefile b/tools/meson/Makefile index f967f33ecd1431..6593f41f538649 100644 --- a/tools/meson/Makefile +++ b/tools/meson/Makefile @@ -1,11 +1,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=meson -PKG_VERSION:=1.5.1 +PKG_VERSION:=1.6.1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://github.com/mesonbuild/meson/releases/download/$(PKG_VERSION) -PKG_HASH:=567e533adf255de73a2de35049b99923caf872a455af9ce03e01077e0d384bed +PKG_HASH:=1eca49eb6c26d58bbee67fd3337d8ef557c0804e30a6d16bfdf269db997464de PKG_MAINTAINER:=Andre Heider PKG_LICENSE:=Apache-2.0