diff --git a/config/Config-kernel.in b/config/Config-kernel.in index 0eecb4933e..f1b79b5ad5 100644 --- a/config/Config-kernel.in +++ b/config/Config-kernel.in @@ -550,9 +550,8 @@ config KERNEL_BPF_EVENTS or logging. config KERNEL_PROBE_EVENTS_BTF_ARGS - bool - depends on KERNEL_KPROBE_EVENTS && KERNEL_DEBUG_INFO_BTF - default n + bool "Support BTF function arguments for probe events" + depends on KERNEL_DEBUG_INFO_BTF && KERNEL_KPROBE_EVENTS && LINUX_6_6 config KERNEL_BPF_KPROBE_OVERRIDE bool diff --git a/include/kernel-6.6 b/include/kernel-6.6 index 4c6596969d..477ed1109b 100644 --- a/include/kernel-6.6 +++ b/include/kernel-6.6 @@ -1,2 +1,2 @@ -LINUX_VERSION-6.6 = .43 -LINUX_KERNEL_HASH-6.6.43 = 0ad83b1a1a780a1aad948d55aa55ee63c50c626f2d46910b9d2180028d100a5e +LINUX_VERSION-6.6 = .44 +LINUX_KERNEL_HASH-6.6.44 = 93218296934915636fe6ba08e125948424cc270fd8948502c0ab91087a9fccd8 diff --git a/package/firmware/omnia-mcu-firmware/Makefile b/package/firmware/omnia-mcu-firmware/Makefile new file mode 100644 index 0000000000..24455739d9 --- /dev/null +++ b/package/firmware/omnia-mcu-firmware/Makefile @@ -0,0 +1,49 @@ +# +# Copyright (C) 2024 CZ.NIC z.s.p.o. (http://www.nic.cz/) +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=omnia-mcu-firmware +PKG_DISTNAME:=omnia_hw_ctrl +PKG_VERSION:=4.0 +PKG_RELEASE:=1 + +PKG_SOURCE_SUBDIR:=$(PKG_DISTNAME)-binaries-v$(PKG_VERSION) +PKG_SOURCE:=$(PKG_SOURCE_SUBDIR).tar.bz2 +PKG_SOURCE_URL:=https://gitlab.nic.cz/turris/hw/$(PKG_DISTNAME)/-/releases/v$(PKG_VERSION)/downloads/ +PKG_HASH:=64b6010f587d89c192685d152644075a5e0abf431eb069ac42981524065a0053 + +PKG_MAINTAINER:=Marek Mojik +PKG_LICENSE:=GPL-3.0-or-later + +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_SOURCE_SUBDIR) + +include $(INCLUDE_DIR)/package.mk + +define Package/omnia-mcu-firmware + SECTION:=firmware + CATEGORY:=Firmware + URL:=https://gitlab.nic.cz/turris/hw/$(PKG_DISTNAME)/-/releases + TITLE:=CZ.NIC Turris Omnia MCU firmware + DEPENDS:=@TARGET_mvebu_cortexa9_DEVICE_cznic_turris-omnia +endef + +define Package/omnia-mcu-firmware/description +Firmware binaries for the microcontroller on the Turris Omnia router. These are +used by the omnia-mcutool utility when upgrading MCU firmware. +endef + +define Build/Compile + true +endef + +define Package/omnia-mcu-firmware/install + $(INSTALL_DIR) $(1)/usr/share/omnia-mcu-firmware/ + $(INSTALL_DATA) $(PKG_BUILD_DIR)/*.bin $(1)/usr/share/omnia-mcu-firmware/ +endef + +$(eval $(call BuildPackage,omnia-mcu-firmware)) diff --git a/package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c b/package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c index e36494c2fe..17748219e8 100644 --- a/package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c +++ b/package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c @@ -100,6 +100,7 @@ static struct bh_map button_map[] = { BH_MAP(KEY_WIMAX, "wwan"), BH_MAP(KEY_WLAN, "wlan"), BH_MAP(KEY_WPS_BUTTON, "wps"), + BH_MAP(KEY_VENDOR, "vendor"), }; /* -------------------------------------------------------------------------*/ diff --git a/package/kernel/linux/modules/other.mk b/package/kernel/linux/modules/other.mk index b4380153ab..5639d32674 100644 --- a/package/kernel/linux/modules/other.mk +++ b/package/kernel/linux/modules/other.mk @@ -598,6 +598,7 @@ define KernelPackage/mtdtests $(LINUX_DIR)/drivers/mtd/tests/mtd_speedtest.ko \ $(LINUX_DIR)/drivers/mtd/tests/mtd_stresstest.ko \ $(LINUX_DIR)/drivers/mtd/tests/mtd_subpagetest.ko \ + $(LINUX_DIR)/drivers/mtd/tests/mtd_test.ko \ $(LINUX_DIR)/drivers/mtd/tests/mtd_torturetest.ko endef diff --git a/package/network/services/hostapd/Makefile b/package/network/services/hostapd/Makefile index 8cedef976b..5fbbedc2b1 100644 --- a/package/network/services/hostapd/Makefile +++ b/package/network/services/hostapd/Makefile @@ -5,7 +5,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=hostapd -PKG_RELEASE:=2 +PKG_RELEASE:=3 PKG_SOURCE_URL:=https://w1.fi/hostap.git PKG_SOURCE_PROTO:=git diff --git a/package/network/services/hostapd/patches/800-SAE-Check-for-invalid-Rejected-Groups-element-length.patch b/package/network/services/hostapd/patches/800-SAE-Check-for-invalid-Rejected-Groups-element-length.patch new file mode 100644 index 0000000000..97402887bf --- /dev/null +++ b/package/network/services/hostapd/patches/800-SAE-Check-for-invalid-Rejected-Groups-element-length.patch @@ -0,0 +1,43 @@ +From 364c2da8741f0979dae497551e70b94c0e6c8636 Mon Sep 17 00:00:00 2001 +From: Jouni Malinen +Date: Sun, 7 Jul 2024 11:46:49 +0300 +Subject: [PATCH] SAE: Check for invalid Rejected Groups element length + explicitly + +Instead of practically ignoring an odd octet at the end of the element, +check for such invalid case explicitly. This is needed to avoid a +potential group downgrade attack. + +Signed-off-by: Jouni Malinen +--- + src/ap/ieee802_11.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +--- a/src/ap/ieee802_11.c ++++ b/src/ap/ieee802_11.c +@@ -1229,7 +1229,7 @@ static int check_sae_rejected_groups(str + struct sae_data *sae) + { + const struct wpabuf *groups; +- size_t i, count; ++ size_t i, count, len; + const u8 *pos; + + if (!sae->tmp) +@@ -1239,7 +1239,15 @@ static int check_sae_rejected_groups(str + return 0; + + pos = wpabuf_head(groups); +- count = wpabuf_len(groups) / 2; ++ len = wpabuf_len(groups); ++ if (len & 1) { ++ wpa_printf(MSG_DEBUG, ++ "SAE: Invalid length of the Rejected Groups element payload: %zu", ++ len); ++ return 1; ++ } ++ ++ count = len / 2; + for (i = 0; i < count; i++) { + int enabled; + u16 group; diff --git a/package/network/services/hostapd/patches/801-SAE-Check-for-invalid-Rejected-Groups-element-length.patch b/package/network/services/hostapd/patches/801-SAE-Check-for-invalid-Rejected-Groups-element-length.patch new file mode 100644 index 0000000000..8d88a4aa13 --- /dev/null +++ b/package/network/services/hostapd/patches/801-SAE-Check-for-invalid-Rejected-Groups-element-length.patch @@ -0,0 +1,42 @@ +From 593a7c2f8c93edd6b552f2d42e28164464b4e6ff Mon Sep 17 00:00:00 2001 +From: Jouni Malinen +Date: Tue, 9 Jul 2024 23:33:38 +0300 +Subject: [PATCH] SAE: Check for invalid Rejected Groups element length + explicitly on STA + +Instead of practically ignoring an odd octet at the end of the element, +check for such invalid case explicitly. This is needed to avoid a +potential group downgrade attack. + +Fixes: 444d76f74f65 ("SAE: Check that peer's rejected groups are not enabled") +Signed-off-by: Jouni Malinen +--- + wpa_supplicant/sme.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +--- a/wpa_supplicant/sme.c ++++ b/wpa_supplicant/sme.c +@@ -1561,14 +1561,21 @@ static int sme_sae_is_group_enabled(stru + static int sme_check_sae_rejected_groups(struct wpa_supplicant *wpa_s, + const struct wpabuf *groups) + { +- size_t i, count; ++ size_t i, count, len; + const u8 *pos; + + if (!groups) + return 0; + + pos = wpabuf_head(groups); +- count = wpabuf_len(groups) / 2; ++ len = wpabuf_len(groups); ++ if (len & 1) { ++ wpa_printf(MSG_DEBUG, ++ "SAE: Invalid length of the Rejected Groups element payload: %zu", ++ len); ++ return 1; ++ } ++ count = len / 2; + for (i = 0; i < count; i++) { + int enabled; + u16 group; diff --git a/package/network/services/hostapd/patches/802-SAE-Reject-invalid-Rejected-Groups-element-in-the-pa.patch b/package/network/services/hostapd/patches/802-SAE-Reject-invalid-Rejected-Groups-element-in-the-pa.patch new file mode 100644 index 0000000000..572a3f721f --- /dev/null +++ b/package/network/services/hostapd/patches/802-SAE-Reject-invalid-Rejected-Groups-element-in-the-pa.patch @@ -0,0 +1,30 @@ +From 9716bf1160beb677e965d9e6475d6c9e162e8374 Mon Sep 17 00:00:00 2001 +From: Jouni Malinen +Date: Tue, 9 Jul 2024 23:34:34 +0300 +Subject: [PATCH] SAE: Reject invalid Rejected Groups element in the parser + +There is no need to depend on all uses (i.e., both hostapd and +wpa_supplicant) to verify that the length of the Rejected Groups field +in the Rejected Groups element is valid (i.e., a multiple of two octets) +since the common parser can reject the message when detecting this. + +Signed-off-by: Jouni Malinen +--- + src/common/sae.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/src/common/sae.c ++++ b/src/common/sae.c +@@ -2120,6 +2120,12 @@ static int sae_parse_rejected_groups(str + return WLAN_STATUS_UNSPECIFIED_FAILURE; + epos++; /* skip ext ID */ + len--; ++ if (len & 1) { ++ wpa_printf(MSG_DEBUG, ++ "SAE: Invalid length of the Rejected Groups element payload: %u", ++ len); ++ return WLAN_STATUS_UNSPECIFIED_FAILURE; ++ } + + wpabuf_free(sae->tmp->peer_rejected_groups); + sae->tmp->peer_rejected_groups = wpabuf_alloc(len); diff --git a/package/utils/omnia-mcutool/Makefile b/package/utils/omnia-mcutool/Makefile new file mode 100644 index 0000000000..d34ad014ae --- /dev/null +++ b/package/utils/omnia-mcutool/Makefile @@ -0,0 +1,52 @@ +# +# Copyright (C) 2016-2024 CZ.NIC z.s.p.o. (http://www.nic.cz/) +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=omnia-mcutool +PKG_VERSION:=0.3-rc2 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 +PKG_SOURCE_URL:=https://gitlab.nic.cz/turris/$(PKG_NAME)/-/archive/$(PKG_VERSION)/ +PKG_HASH:=68e407fca16ccaf4bd87401f710d6a4061029b4d474ac10c4c3253af73c242ac + +PKG_MAINTAINER:=Marek Mojik +PKG_LICENSE:=GPL-2.0-or-later + +include $(INCLUDE_DIR)/package.mk + +define Package/omnia-mcutool + SECTION:=utils + CATEGORY:=Utilities + URL:=https://gitlab.nic.cz/turris/$(PKG_NAME) + TITLE:=CZ.NIC Turris Omnia MCU utility + DEPENDS:=+libopenssl +omnia-mcu-firmware @TARGET_mvebu_cortexa9_DEVICE_cznic_turris-omnia +endef + +define Package/omnia-mcutool/description +The omnia-mcutool utility is mainly used to upgrade the firmware on the +microcontroller on the Turris Omnia router. It can also show state of MCU +settings and configure MCU options (GPIOs, LEDs, power). +endef + +TARGET_LDFLAGS += -lcrypto + +define Build/Compile + $(MAKE) -C $(PKG_BUILD_DIR) \ + CC="$(TARGET_CC)" \ + CFLAGS="$(TARGET_CFLAGS) -Wall" \ + LDFLAGS="$(TARGET_LDFLAGS)" \ + MCUTOOL_VERSION="$(PKG_VERSION)" +endef + +define Package/omnia-mcutool/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/omnia-mcutool $(1)/usr/bin/ +endef + +$(eval $(call BuildPackage,omnia-mcutool)) diff --git a/target/linux/apm821xx/dts/netgear-wndap6x0.dtsi b/target/linux/apm821xx/dts/netgear-wndap6x0.dtsi index 9d98776626..7c9faa883f 100644 --- a/target/linux/apm821xx/dts/netgear-wndap6x0.dtsi +++ b/target/linux/apm821xx/dts/netgear-wndap6x0.dtsi @@ -224,7 +224,7 @@ rtl8367b { compatible = "realtek,rtl8367b"; - realtek,extif0 = <1 2 1 1 1 1 1 1 2>; + realtek,extif = <5 1 2 1 1 1 1 1 1 2>; mii-bus = <&mdio0>; }; }; diff --git a/target/linux/ath79/dts/ar7242_tplink_tl-wr2543-v1.dts b/target/linux/ath79/dts/ar7242_tplink_tl-wr2543-v1.dts index 77eeedc588..0124ddff87 100644 --- a/target/linux/ath79/dts/ar7242_tplink_tl-wr2543-v1.dts +++ b/target/linux/ath79/dts/ar7242_tplink_tl-wr2543-v1.dts @@ -78,7 +78,7 @@ compatible = "realtek,rtl8367"; gpio-sda = <&gpio 1 GPIO_ACTIVE_HIGH>; gpio-sck = <&gpio 6 GPIO_ACTIVE_HIGH>; - realtek,extif0 = <1 0 1 1 1 1 1 1 2>; + realtek,extif = <9 1 0 1 1 1 1 1 1 2>; mdio-bus { #address-cells = <1>; diff --git a/target/linux/ath79/patches-6.6/340-register_gpio_driver_earlier.patch b/target/linux/ath79/patches-6.6/340-register_gpio_driver_earlier.patch new file mode 100644 index 0000000000..a3bdf890c4 --- /dev/null +++ b/target/linux/ath79/patches-6.6/340-register_gpio_driver_earlier.patch @@ -0,0 +1,26 @@ +From: John Crispin +Subject: ath79: Register GPIO driver earlier + +HACK: register the GPIO driver earlier to ensure that gpio_request calls +from mach files succeed. + +Submitted-by: John Crispin +--- + drivers/gpio/gpio-ath79.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/gpio/gpio-ath79.c ++++ b/drivers/gpio/gpio-ath79.c +@@ -300,7 +300,11 @@ static struct platform_driver ath79_gpio + .probe = ath79_gpio_probe, + }; + +-module_platform_driver(ath79_gpio_driver); ++static int __init ath79_gpio_init(void) ++{ ++ return platform_driver_register(&ath79_gpio_driver); ++} ++postcore_initcall(ath79_gpio_init); + + MODULE_DESCRIPTION("Atheros AR71XX/AR724X/AR913X GPIO API support"); + MODULE_LICENSE("GPL v2"); diff --git a/target/linux/ath79/patches-6.6/430-mtd-ar934x-nand-driver.patch b/target/linux/ath79/patches-6.6/430-mtd-ar934x-nand-driver.patch index 603750cbe9..fc4c3804a7 100644 --- a/target/linux/ath79/patches-6.6/430-mtd-ar934x-nand-driver.patch +++ b/target/linux/ath79/patches-6.6/430-mtd-ar934x-nand-driver.patch @@ -9,7 +9,7 @@ SVN-Revision: 33385 --- a/drivers/mtd/nand/raw/Kconfig +++ b/drivers/mtd/nand/raw/Kconfig -@@ -543,4 +543,12 @@ config MTD_NAND_DISKONCHIP_BBTWRITE +@@ -542,4 +542,12 @@ config MTD_NAND_DISKONCHIP_BBTWRITE load time (assuming you build diskonchip as a module) with the module parameter "inftl_bbt_write=1". diff --git a/target/linux/ath79/patches-6.6/900-unaligned_access_hacks.patch b/target/linux/ath79/patches-6.6/900-unaligned_access_hacks.patch index acc2379611..8e91a243c4 100644 --- a/target/linux/ath79/patches-6.6/900-unaligned_access_hacks.patch +++ b/target/linux/ath79/patches-6.6/900-unaligned_access_hacks.patch @@ -259,7 +259,7 @@ SVN-Revision: 35130 #include #include #include -@@ -897,10 +898,10 @@ static void tcp_v6_send_response(const s +@@ -893,10 +894,10 @@ static void tcp_v6_send_response(const s topt = (__be32 *)(t1 + 1); if (tsecr) { diff --git a/target/linux/ath79/patches-6.6/910-mikrotik-rb4xx.patch b/target/linux/ath79/patches-6.6/910-mikrotik-rb4xx.patch index 980f29eef1..674cc2fe66 100644 --- a/target/linux/ath79/patches-6.6/910-mikrotik-rb4xx.patch +++ b/target/linux/ath79/patches-6.6/910-mikrotik-rb4xx.patch @@ -97,7 +97,7 @@ Submitted-by: Christopher Hill obj-$(CONFIG_GPIO_RDA) += gpio-rda.o --- a/drivers/mtd/nand/raw/Kconfig +++ b/drivers/mtd/nand/raw/Kconfig -@@ -551,4 +551,11 @@ config MTD_NAND_AR934X +@@ -550,4 +550,11 @@ config MTD_NAND_AR934X Enables support for NAND controller on Qualcomm Atheros SoCs. This controller is found on AR934x and QCA955x SoCs. diff --git a/target/linux/ath79/patches-6.6/911-mikrotik-rb91x.patch b/target/linux/ath79/patches-6.6/911-mikrotik-rb91x.patch index e610a4ff14..ddb7b52cbe 100644 --- a/target/linux/ath79/patches-6.6/911-mikrotik-rb91x.patch +++ b/target/linux/ath79/patches-6.6/911-mikrotik-rb91x.patch @@ -73,7 +73,7 @@ Tested-by: Koen Vandeputte obj-$(CONFIG_GPIO_RDA) += gpio-rda.o --- a/drivers/mtd/nand/raw/Kconfig +++ b/drivers/mtd/nand/raw/Kconfig -@@ -558,4 +558,10 @@ config MTD_NAND_RB4XX +@@ -557,4 +557,10 @@ config MTD_NAND_RB4XX Enables support for the NAND flash chip on Mikrotik Routerboard RB4xx series. diff --git a/target/linux/bcm27xx/patches-6.6/950-0106-Add-support-for-all-the-downstream-rpi-sound-card-dr.patch b/target/linux/bcm27xx/patches-6.6/950-0106-Add-support-for-all-the-downstream-rpi-sound-card-dr.patch index 0474076e77..b55df94070 100644 --- a/target/linux/bcm27xx/patches-6.6/950-0106-Add-support-for-all-the-downstream-rpi-sound-card-dr.patch +++ b/target/linux/bcm27xx/patches-6.6/950-0106-Add-support-for-all-the-downstream-rpi-sound-card-dr.patch @@ -17583,7 +17583,7 @@ Signed-off-by: Phil Elwell * For devices with more than one control interface, we assume the --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c -@@ -2185,6 +2185,8 @@ static const struct usb_audio_quirk_flag +@@ -2189,6 +2189,8 @@ static const struct usb_audio_quirk_flag QUIRK_FLAG_ALIGN_TRANSFER), DEVICE_FLG(0x534d, 0x2109, /* MacroSilicon MS2109 */ QUIRK_FLAG_ALIGN_TRANSFER), diff --git a/target/linux/bcm27xx/patches-6.6/950-0277-kbuild-Silence-unavoidable-dtc-overlay-warnings.patch b/target/linux/bcm27xx/patches-6.6/950-0277-kbuild-Silence-unavoidable-dtc-overlay-warnings.patch index b5e790665e..2e3de46259 100644 --- a/target/linux/bcm27xx/patches-6.6/950-0277-kbuild-Silence-unavoidable-dtc-overlay-warnings.patch +++ b/target/linux/bcm27xx/patches-6.6/950-0277-kbuild-Silence-unavoidable-dtc-overlay-warnings.patch @@ -16,7 +16,7 @@ Signed-off-by: Phil Elwell --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib -@@ -428,6 +428,12 @@ cmd_dtco = mkdir -p $(dir ${dtc-tmp}) ; +@@ -432,6 +432,12 @@ cmd_dtco = mkdir -p $(dir ${dtc-tmp}) ; $(DTC) -@ -H epapr -O dtb -o $@ -b 0 \ -i $(dir $<) $(DTC_FLAGS) \ -Wno-interrupts_property \ diff --git a/target/linux/bcm27xx/patches-6.6/950-0526-mfd-Add-rp1-driver.patch b/target/linux/bcm27xx/patches-6.6/950-0526-mfd-Add-rp1-driver.patch index 764a38ff19..b900c1edae 100644 --- a/target/linux/bcm27xx/patches-6.6/950-0526-mfd-Add-rp1-driver.patch +++ b/target/linux/bcm27xx/patches-6.6/950-0526-mfd-Add-rp1-driver.patch @@ -39,11 +39,11 @@ Signed-off-by: Phil Elwell depends on I2C && OF --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile -@@ -285,3 +285,5 @@ rsmu-i2c-objs := rsmu_core.o rsmu_i2c. - rsmu-spi-objs := rsmu_core.o rsmu_spi.o - obj-$(CONFIG_MFD_RSMU_I2C) += rsmu-i2c.o - obj-$(CONFIG_MFD_RSMU_SPI) += rsmu-spi.o -+ +@@ -283,3 +283,5 @@ obj-$(CONFIG_MFD_ATC260X_I2C) += atc260x + + obj-$(CONFIG_MFD_RSMU_I2C) += rsmu_i2c.o rsmu_core.o + obj-$(CONFIG_MFD_RSMU_SPI) += rsmu_spi.o rsmu_core.o ++ +obj-$(CONFIG_MFD_RP1) += rp1.o --- /dev/null +++ b/drivers/mfd/rp1.c diff --git a/target/linux/generic/backport-6.6/310-v6.7-mips-kexec-fix-the-incorrect-ifdeffery-and-dependenc.patch b/target/linux/generic/backport-6.6/310-v6.7-mips-kexec-fix-the-incorrect-ifdeffery-and-dependenc.patch index 99a6bfe638..6d3c7d04fe 100644 --- a/target/linux/generic/backport-6.6/310-v6.7-mips-kexec-fix-the-incorrect-ifdeffery-and-dependenc.patch +++ b/target/linux/generic/backport-6.6/310-v6.7-mips-kexec-fix-the-incorrect-ifdeffery-and-dependenc.patch @@ -134,7 +134,7 @@ Signed-off-by: Andrew Morton }; --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c -@@ -392,7 +392,7 @@ static void cps_smp_finish(void) +@@ -395,7 +395,7 @@ static void cps_smp_finish(void) local_irq_enable(); } @@ -143,7 +143,7 @@ Signed-off-by: Andrew Morton enum cpu_death { CPU_DEATH_HALT, -@@ -429,7 +429,7 @@ static void cps_shutdown_this_cpu(enum c +@@ -432,7 +432,7 @@ static void cps_shutdown_this_cpu(enum c } } @@ -152,7 +152,7 @@ Signed-off-by: Andrew Morton static void cps_kexec_nonboot_cpu(void) { -@@ -439,9 +439,9 @@ static void cps_kexec_nonboot_cpu(void) +@@ -442,9 +442,9 @@ static void cps_kexec_nonboot_cpu(void) cps_shutdown_this_cpu(CPU_DEATH_POWER); } @@ -164,7 +164,7 @@ Signed-off-by: Andrew Morton #ifdef CONFIG_HOTPLUG_CPU -@@ -610,7 +610,7 @@ static const struct plat_smp_ops cps_smp +@@ -613,7 +613,7 @@ static const struct plat_smp_ops cps_smp .cpu_die = cps_cpu_die, .cleanup_dead_cpu = cps_cleanup_dead_cpu, #endif @@ -175,8 +175,8 @@ Signed-off-by: Andrew Morton }; --- a/arch/mips/loongson64/reset.c +++ b/arch/mips/loongson64/reset.c -@@ -53,7 +53,7 @@ static void loongson_halt(void) - } +@@ -39,7 +39,7 @@ static int firmware_poweroff(struct sys_ + return NOTIFY_DONE; } -#ifdef CONFIG_KEXEC @@ -184,9 +184,9 @@ Signed-off-by: Andrew Morton /* 0X80000000~0X80200000 is safe */ #define MAX_ARGS 64 -@@ -158,7 +158,7 @@ static int __init mips_reboot_setup(void - _machine_halt = loongson_halt; - pm_power_off = loongson_poweroff; +@@ -152,7 +152,7 @@ static int __init mips_reboot_setup(void + firmware_poweroff, NULL); + } -#ifdef CONFIG_KEXEC +#ifdef CONFIG_KEXEC_CORE @@ -195,7 +195,7 @@ Signed-off-by: Andrew Morton return -ENOMEM; --- a/arch/mips/loongson64/smp.c +++ b/arch/mips/loongson64/smp.c -@@ -864,7 +864,7 @@ const struct plat_smp_ops loongson3_smp_ +@@ -883,7 +883,7 @@ const struct plat_smp_ops loongson3_smp_ .cpu_disable = loongson3_cpu_disable, .cpu_die = loongson3_cpu_die, #endif diff --git a/target/linux/generic/backport-6.6/896-01-v6.9-net-dsa-mv88e6xxx-rename-mv88e6xxx_g2_scratch_gpio_s.patch b/target/linux/generic/backport-6.6/896-01-v6.9-net-dsa-mv88e6xxx-rename-mv88e6xxx_g2_scratch_gpio_s.patch index d9265cad10..48dd6ffb67 100644 --- a/target/linux/generic/backport-6.6/896-01-v6.9-net-dsa-mv88e6xxx-rename-mv88e6xxx_g2_scratch_gpio_s.patch +++ b/target/linux/generic/backport-6.6/896-01-v6.9-net-dsa-mv88e6xxx-rename-mv88e6xxx_g2_scratch_gpio_s.patch @@ -19,7 +19,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -3668,7 +3668,7 @@ static int mv88e6xxx_mdio_register(struc +@@ -3669,7 +3669,7 @@ static int mv88e6xxx_mdio_register(struc if (external) { mv88e6xxx_reg_lock(chip); diff --git a/target/linux/generic/backport-6.6/896-02-v6.9-net-dsa-mv88e6xxx-add-Amethyst-specific-SMI-GPIO-fun.patch b/target/linux/generic/backport-6.6/896-02-v6.9-net-dsa-mv88e6xxx-add-Amethyst-specific-SMI-GPIO-fun.patch index 5661d50adb..e5931573f7 100644 --- a/target/linux/generic/backport-6.6/896-02-v6.9-net-dsa-mv88e6xxx-add-Amethyst-specific-SMI-GPIO-fun.patch +++ b/target/linux/generic/backport-6.6/896-02-v6.9-net-dsa-mv88e6xxx-add-Amethyst-specific-SMI-GPIO-fun.patch @@ -27,7 +27,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -3668,7 +3668,10 @@ static int mv88e6xxx_mdio_register(struc +@@ -3669,7 +3669,10 @@ static int mv88e6xxx_mdio_register(struc if (external) { mv88e6xxx_reg_lock(chip); diff --git a/target/linux/generic/config-6.6 b/target/linux/generic/config-6.6 index ac56aff9bd..cd315b1e8c 100644 --- a/target/linux/generic/config-6.6 +++ b/target/linux/generic/config-6.6 @@ -875,6 +875,7 @@ CONFIG_CFG80211_HEADERS=y # CONFIG_CHELSIO_T4 is not set # CONFIG_CHELSIO_T4VF is not set # CONFIG_CHROME_PLATFORMS is not set +# CONFIG_CZNIC_PLATFORMS is not set # CONFIG_CHR_DEV_SCH is not set # CONFIG_CHR_DEV_SG is not set # CONFIG_CHR_DEV_ST is not set diff --git a/target/linux/generic/files/drivers/net/phy/rtl8366_smi.h b/target/linux/generic/files/drivers/net/phy/rtl8366_smi.h index 3fcae81fa4..4b3b3fe98c 100644 --- a/target/linux/generic/files/drivers/net/phy/rtl8366_smi.h +++ b/target/linux/generic/files/drivers/net/phy/rtl8366_smi.h @@ -23,6 +23,16 @@ struct dentry; struct inode; struct file; +typedef enum rtl8367b_chip_e { + RTL8367B_CHIP_UNKNOWN, + /* Family B */ + RTL8367B_CHIP_RTL8367RB, + RTL8367B_CHIP_RTL8367R_VB, /* chip with exception in extif assignment */ +/* Family C */ + RTL8367B_CHIP_RTL8367RB_VB, + RTL8367B_CHIP_RTL8367S +} rtl8367b_chip_t; + struct rtl8366_mib_counter { unsigned base; unsigned offset; @@ -64,6 +74,7 @@ struct rtl8366_smi { u8 dbg_vlan_4k_page; #endif u32 phy_id; + rtl8367b_chip_t rtl8367b_chip; struct mii_bus *ext_mbus; }; diff --git a/target/linux/generic/files/drivers/net/phy/rtl8367.c b/target/linux/generic/files/drivers/net/phy/rtl8367.c index b14b63e036..0acfeb54bb 100644 --- a/target/linux/generic/files/drivers/net/phy/rtl8367.c +++ b/target/linux/generic/files/drivers/net/phy/rtl8367.c @@ -1077,21 +1077,37 @@ static int rtl8367_led_blinkrate_set(struct rtl8366_smi *smi, unsigned int rate) } #ifdef CONFIG_OF -static int rtl8367_extif_init_of(struct rtl8366_smi *smi, int id, +static int rtl8367_extif_init_of(struct rtl8366_smi *smi, const char *name) { struct rtl8367_extif_config *cfg; const __be32 *prop; int size; int err; + unsigned cpu_port; + unsigned id = UINT_MAX; prop = of_get_property(smi->parent->of_node, name, &size); - if (!prop) - return rtl8367_extif_init(smi, id, NULL); + if (!prop || (size != (10 * sizeof(*prop)))) { + dev_err(smi->parent, "%s property is not defined or invalid\n", name); + err = -EINVAL; + goto err_init; + } - if (size != (9 * sizeof(*prop))) { - dev_err(smi->parent, "%s property is invalid\n", name); - return -EINVAL; + cpu_port = be32_to_cpup(prop++); + switch (cpu_port) { + case RTL8367_CPU_PORT_NUM - 1: + case RTL8367_CPU_PORT_NUM: + id = RTL8367_CPU_PORT_NUM - cpu_port; + if (smi->cpu_port == UINT_MAX) { + dev_info(smi->parent, "cpu_port:%u, assigned to extif%u\n", cpu_port, id); + smi->cpu_port = cpu_port; + } + break; + default: + dev_err(smi->parent, "wrong cpu_port %u in %s property\n", cpu_port, name); + err = -EINVAL; + goto err_init; } cfg = kzalloc(sizeof(struct rtl8367_extif_config), GFP_KERNEL); @@ -1111,10 +1127,14 @@ static int rtl8367_extif_init_of(struct rtl8366_smi *smi, int id, err = rtl8367_extif_init(smi, id, cfg); kfree(cfg); +err_init: + if (id != 0) rtl8367_extif_init(smi, 0, NULL); + if (id != 1) rtl8367_extif_init(smi, 1, NULL); + return err; } #else -static int rtl8367_extif_init_of(struct rtl8366_smi *smi, int id, +static int rtl8367_extif_init_of(struct rtl8366_smi *smi, const char *name) { return -EINVAL; @@ -1135,11 +1155,7 @@ static int rtl8367_setup(struct rtl8366_smi *smi) /* initialize external interfaces */ if (smi->parent->of_node) { - err = rtl8367_extif_init_of(smi, 0, "realtek,extif0"); - if (err) - return err; - - err = rtl8367_extif_init_of(smi, 1, "realtek,extif1"); + err = rtl8367_extif_init_of(smi, "realtek,extif"); if (err) return err; } else { @@ -1722,11 +1738,6 @@ static int rtl8367_detect(struct rtl8366_smi *smi) dev_info(smi->parent, "RTL%s ver. %u chip found\n", chip_name, rtl_ver & RTL8367_RTL_VER_MASK); - if (of_property_present(smi->parent->of_node, "realtek,extif1")) - smi->cpu_port = RTL8367_CPU_PORT_NUM - 1; - - dev_info(smi->parent, "CPU port: %u\n", smi->cpu_port); - return 0; } @@ -1764,7 +1775,7 @@ static int rtl8367_probe(struct platform_device *pdev) smi->cmd_read = 0xb9; smi->cmd_write = 0xb8; smi->ops = &rtl8367_smi_ops; - smi->cpu_port = RTL8367_CPU_PORT_NUM; + smi->cpu_port = UINT_MAX; /* not defined yet */ smi->num_ports = RTL8367_NUM_PORTS; smi->num_vlan_mc = RTL8367_NUM_VLANS; smi->mib_counters = rtl8367_mib_counters; diff --git a/target/linux/generic/files/drivers/net/phy/rtl8367b.c b/target/linux/generic/files/drivers/net/phy/rtl8367b.c index 04c790e924..534da05517 100644 --- a/target/linux/generic/files/drivers/net/phy/rtl8367b.c +++ b/target/linux/generic/files/drivers/net/phy/rtl8367b.c @@ -1,5 +1,6 @@ /* - * Platform driver for the Realtek RTL8367R-VB ethernet switches + * Platform driver for Realtek RTL8367B family chips, i.e. RTL8367RB and RTL8367R-VB + * extended with support for RTL8367C family chips, i.e. RTL8367RB-VB and RTL8367S * * Copyright (C) 2012 Gabor Juhos * @@ -120,8 +121,6 @@ #define RTL8367B_CHIP_NUMBER_REG 0x1300/*GOOD*/ #define RTL8367B_CHIP_VER_REG 0x1301/*GOOD*/ -#define RTL8367B_CHIP_VER_RLVID_SHIFT 12/*GOOD*/ -#define RTL8367B_CHIP_VER_RLVID_MASK 0xf/*GOOD*/ #define RTL8367B_CHIP_VER_MCID_SHIFT 8/*GOOD*/ #define RTL8367B_CHIP_VER_MCID_MASK 0xf/*GOOD*/ #define RTL8367B_CHIP_VER_BOID_SHIFT 4/*GOOD*/ @@ -351,220 +350,7 @@ rtl8367b_mib_counters[RTL8367B_NUM_MIB_COUNTERS] = { return err; \ } while (0) -static const struct rtl8367b_initval rtl8367r_vb_initvals_0[] = { - {0x1B03, 0x0876}, {0x1200, 0x7FC4}, {0x0301, 0x0026}, {0x1722, 0x0E14}, - {0x205F, 0x0002}, {0x2059, 0x1A00}, {0x205F, 0x0000}, {0x207F, 0x0002}, - {0x2077, 0x0000}, {0x2078, 0x0000}, {0x2079, 0x0000}, {0x207A, 0x0000}, - {0x207B, 0x0000}, {0x207F, 0x0000}, {0x205F, 0x0002}, {0x2053, 0x0000}, - {0x2054, 0x0000}, {0x2055, 0x0000}, {0x2056, 0x0000}, {0x2057, 0x0000}, - {0x205F, 0x0000}, {0x12A4, 0x110A}, {0x12A6, 0x150A}, {0x13F1, 0x0013}, - {0x13F4, 0x0010}, {0x13F5, 0x0000}, {0x0018, 0x0F00}, {0x0038, 0x0F00}, - {0x0058, 0x0F00}, {0x0078, 0x0F00}, {0x0098, 0x0F00}, {0x12B6, 0x0C02}, - {0x12B7, 0x030F}, {0x12B8, 0x11FF}, {0x12BC, 0x0004}, {0x1362, 0x0115}, - {0x1363, 0x0002}, {0x1363, 0x0000}, {0x133F, 0x0030}, {0x133E, 0x000E}, - {0x221F, 0x0007}, {0x221E, 0x002D}, {0x2218, 0xF030}, {0x221F, 0x0007}, - {0x221E, 0x0023}, {0x2216, 0x0005}, {0x2215, 0x00B9}, {0x2219, 0x0044}, - {0x2215, 0x00BA}, {0x2219, 0x0020}, {0x2215, 0x00BB}, {0x2219, 0x00C1}, - {0x2215, 0x0148}, {0x2219, 0x0096}, {0x2215, 0x016E}, {0x2219, 0x0026}, - {0x2216, 0x0000}, {0x2216, 0x0000}, {0x221E, 0x002D}, {0x2218, 0xF010}, - {0x221F, 0x0007}, {0x221E, 0x0020}, {0x2215, 0x0D00}, {0x221F, 0x0000}, - {0x221F, 0x0000}, {0x2217, 0x2160}, {0x221F, 0x0001}, {0x2210, 0xF25E}, - {0x221F, 0x0007}, {0x221E, 0x0042}, {0x2215, 0x0F00}, {0x2215, 0x0F00}, - {0x2216, 0x7408}, {0x2215, 0x0E00}, {0x2215, 0x0F00}, {0x2215, 0x0F01}, - {0x2216, 0x4000}, {0x2215, 0x0E01}, {0x2215, 0x0F01}, {0x2215, 0x0F02}, - {0x2216, 0x9400}, {0x2215, 0x0E02}, {0x2215, 0x0F02}, {0x2215, 0x0F03}, - {0x2216, 0x7408}, {0x2215, 0x0E03}, {0x2215, 0x0F03}, {0x2215, 0x0F04}, - {0x2216, 0x4008}, {0x2215, 0x0E04}, {0x2215, 0x0F04}, {0x2215, 0x0F05}, - {0x2216, 0x9400}, {0x2215, 0x0E05}, {0x2215, 0x0F05}, {0x2215, 0x0F06}, - {0x2216, 0x0803}, {0x2215, 0x0E06}, {0x2215, 0x0F06}, {0x2215, 0x0D00}, - {0x2215, 0x0100}, {0x221F, 0x0001}, {0x2210, 0xF05E}, {0x221F, 0x0000}, - {0x2217, 0x2100}, {0x221F, 0x0000}, {0x220D, 0x0003}, {0x220E, 0x0015}, - {0x220D, 0x4003}, {0x220E, 0x0006}, {0x221F, 0x0000}, {0x2200, 0x1340}, - {0x133F, 0x0010}, {0x12A0, 0x0058}, {0x12A1, 0x0058}, {0x133E, 0x000E}, - {0x133F, 0x0030}, {0x221F, 0x0000}, {0x2210, 0x0166}, {0x221F, 0x0000}, - {0x133E, 0x000E}, {0x133F, 0x0010}, {0x133F, 0x0030}, {0x133E, 0x000E}, - {0x221F, 0x0005}, {0x2205, 0xFFF6}, {0x2206, 0x0080}, {0x2205, 0x8B6E}, - {0x2206, 0x0000}, {0x220F, 0x0100}, {0x2205, 0x8000}, {0x2206, 0x0280}, - {0x2206, 0x28F7}, {0x2206, 0x00E0}, {0x2206, 0xFFF7}, {0x2206, 0xA080}, - {0x2206, 0x02AE}, {0x2206, 0xF602}, {0x2206, 0x0153}, {0x2206, 0x0201}, - {0x2206, 0x6602}, {0x2206, 0x80B9}, {0x2206, 0xE08B}, {0x2206, 0x8CE1}, - {0x2206, 0x8B8D}, {0x2206, 0x1E01}, {0x2206, 0xE18B}, {0x2206, 0x8E1E}, - {0x2206, 0x01A0}, {0x2206, 0x00E7}, {0x2206, 0xAEDB}, {0x2206, 0xEEE0}, - {0x2206, 0x120E}, {0x2206, 0xEEE0}, {0x2206, 0x1300}, {0x2206, 0xEEE0}, - {0x2206, 0x2001}, {0x2206, 0xEEE0}, {0x2206, 0x2166}, {0x2206, 0xEEE0}, - {0x2206, 0xC463}, {0x2206, 0xEEE0}, {0x2206, 0xC5E8}, {0x2206, 0xEEE0}, - {0x2206, 0xC699}, {0x2206, 0xEEE0}, {0x2206, 0xC7C2}, {0x2206, 0xEEE0}, - {0x2206, 0xC801}, {0x2206, 0xEEE0}, {0x2206, 0xC913}, {0x2206, 0xEEE0}, - {0x2206, 0xCA30}, {0x2206, 0xEEE0}, {0x2206, 0xCB3E}, {0x2206, 0xEEE0}, - {0x2206, 0xDCE1}, {0x2206, 0xEEE0}, {0x2206, 0xDD00}, {0x2206, 0xEEE2}, - {0x2206, 0x0001}, {0x2206, 0xEEE2}, {0x2206, 0x0100}, {0x2206, 0xEEE4}, - {0x2206, 0x8860}, {0x2206, 0xEEE4}, {0x2206, 0x8902}, {0x2206, 0xEEE4}, - {0x2206, 0x8C00}, {0x2206, 0xEEE4}, {0x2206, 0x8D30}, {0x2206, 0xEEEA}, - {0x2206, 0x1480}, {0x2206, 0xEEEA}, {0x2206, 0x1503}, {0x2206, 0xEEEA}, - {0x2206, 0xC600}, {0x2206, 0xEEEA}, {0x2206, 0xC706}, {0x2206, 0xEE85}, - {0x2206, 0xEE00}, {0x2206, 0xEE85}, {0x2206, 0xEF00}, {0x2206, 0xEE8B}, - {0x2206, 0x6750}, {0x2206, 0xEE8B}, {0x2206, 0x6632}, {0x2206, 0xEE8A}, - {0x2206, 0xD448}, {0x2206, 0xEE8A}, {0x2206, 0xD548}, {0x2206, 0xEE8A}, - {0x2206, 0xD649}, {0x2206, 0xEE8A}, {0x2206, 0xD7F8}, {0x2206, 0xEE8B}, - {0x2206, 0x85E2}, {0x2206, 0xEE8B}, {0x2206, 0x8700}, {0x2206, 0xEEFF}, - {0x2206, 0xF600}, {0x2206, 0xEEFF}, {0x2206, 0xF7FC}, {0x2206, 0x04F8}, - {0x2206, 0xE08B}, {0x2206, 0x8EAD}, {0x2206, 0x2023}, {0x2206, 0xF620}, - {0x2206, 0xE48B}, {0x2206, 0x8E02}, {0x2206, 0x2877}, {0x2206, 0x0225}, - {0x2206, 0xC702}, {0x2206, 0x26A1}, {0x2206, 0x0281}, {0x2206, 0xB302}, - {0x2206, 0x8496}, {0x2206, 0x0202}, {0x2206, 0xA102}, {0x2206, 0x27F1}, - {0x2206, 0x0228}, {0x2206, 0xF902}, {0x2206, 0x2AA0}, {0x2206, 0x0282}, - {0x2206, 0xB8E0}, {0x2206, 0x8B8E}, {0x2206, 0xAD21}, {0x2206, 0x08F6}, - {0x2206, 0x21E4}, {0x2206, 0x8B8E}, {0x2206, 0x0202}, {0x2206, 0x80E0}, - {0x2206, 0x8B8E}, {0x2206, 0xAD22}, {0x2206, 0x05F6}, {0x2206, 0x22E4}, - {0x2206, 0x8B8E}, {0x2206, 0xE08B}, {0x2206, 0x8EAD}, {0x2206, 0x2305}, - {0x2206, 0xF623}, {0x2206, 0xE48B}, {0x2206, 0x8EE0}, {0x2206, 0x8B8E}, - {0x2206, 0xAD24}, {0x2206, 0x08F6}, {0x2206, 0x24E4}, {0x2206, 0x8B8E}, - {0x2206, 0x0227}, {0x2206, 0x6AE0}, {0x2206, 0x8B8E}, {0x2206, 0xAD25}, - {0x2206, 0x05F6}, {0x2206, 0x25E4}, {0x2206, 0x8B8E}, {0x2206, 0xE08B}, - {0x2206, 0x8EAD}, {0x2206, 0x260B}, {0x2206, 0xF626}, {0x2206, 0xE48B}, - {0x2206, 0x8E02}, {0x2206, 0x830D}, {0x2206, 0x021D}, {0x2206, 0x6BE0}, - {0x2206, 0x8B8E}, {0x2206, 0xAD27}, {0x2206, 0x05F6}, {0x2206, 0x27E4}, - {0x2206, 0x8B8E}, {0x2206, 0x0281}, {0x2206, 0x4402}, {0x2206, 0x045C}, - {0x2206, 0xFC04}, {0x2206, 0xF8E0}, {0x2206, 0x8B83}, {0x2206, 0xAD23}, - {0x2206, 0x30E0}, {0x2206, 0xE022}, {0x2206, 0xE1E0}, {0x2206, 0x2359}, - {0x2206, 0x02E0}, {0x2206, 0x85EF}, {0x2206, 0xE585}, {0x2206, 0xEFAC}, - {0x2206, 0x2907}, {0x2206, 0x1F01}, {0x2206, 0x9E51}, {0x2206, 0xAD29}, - {0x2206, 0x20E0}, {0x2206, 0x8B83}, {0x2206, 0xAD21}, {0x2206, 0x06E1}, - {0x2206, 0x8B84}, {0x2206, 0xAD28}, {0x2206, 0x42E0}, {0x2206, 0x8B85}, - {0x2206, 0xAD21}, {0x2206, 0x06E1}, {0x2206, 0x8B84}, {0x2206, 0xAD29}, - {0x2206, 0x36BF}, {0x2206, 0x34BF}, {0x2206, 0x022C}, {0x2206, 0x31AE}, - {0x2206, 0x2EE0}, {0x2206, 0x8B83}, {0x2206, 0xAD21}, {0x2206, 0x10E0}, - {0x2206, 0x8B84}, {0x2206, 0xF620}, {0x2206, 0xE48B}, {0x2206, 0x84EE}, - {0x2206, 0x8ADA}, {0x2206, 0x00EE}, {0x2206, 0x8ADB}, {0x2206, 0x00E0}, - {0x2206, 0x8B85}, {0x2206, 0xAD21}, {0x2206, 0x0CE0}, {0x2206, 0x8B84}, - {0x2206, 0xF621}, {0x2206, 0xE48B}, {0x2206, 0x84EE}, {0x2206, 0x8B72}, - {0x2206, 0xFFBF}, {0x2206, 0x34C2}, {0x2206, 0x022C}, {0x2206, 0x31FC}, - {0x2206, 0x04F8}, {0x2206, 0xFAEF}, {0x2206, 0x69E0}, {0x2206, 0x8B85}, - {0x2206, 0xAD21}, {0x2206, 0x42E0}, {0x2206, 0xE022}, {0x2206, 0xE1E0}, - {0x2206, 0x2358}, {0x2206, 0xC059}, {0x2206, 0x021E}, {0x2206, 0x01E1}, - {0x2206, 0x8B72}, {0x2206, 0x1F10}, {0x2206, 0x9E2F}, {0x2206, 0xE48B}, - {0x2206, 0x72AD}, {0x2206, 0x2123}, {0x2206, 0xE18B}, {0x2206, 0x84F7}, - {0x2206, 0x29E5}, {0x2206, 0x8B84}, {0x2206, 0xAC27}, {0x2206, 0x10AC}, - {0x2206, 0x2605}, {0x2206, 0x0205}, {0x2206, 0x23AE}, {0x2206, 0x1602}, - {0x2206, 0x0535}, {0x2206, 0x0282}, {0x2206, 0x30AE}, {0x2206, 0x0E02}, - {0x2206, 0x056A}, {0x2206, 0x0282}, {0x2206, 0x75AE}, {0x2206, 0x0602}, - {0x2206, 0x04DC}, {0x2206, 0x0282}, {0x2206, 0x04EF}, {0x2206, 0x96FE}, - {0x2206, 0xFC04}, {0x2206, 0xF8F9}, {0x2206, 0xE08B}, {0x2206, 0x87AD}, - {0x2206, 0x2321}, {0x2206, 0xE0EA}, {0x2206, 0x14E1}, {0x2206, 0xEA15}, - {0x2206, 0xAD26}, {0x2206, 0x18F6}, {0x2206, 0x27E4}, {0x2206, 0xEA14}, - {0x2206, 0xE5EA}, {0x2206, 0x15F6}, {0x2206, 0x26E4}, {0x2206, 0xEA14}, - {0x2206, 0xE5EA}, {0x2206, 0x15F7}, {0x2206, 0x27E4}, {0x2206, 0xEA14}, - {0x2206, 0xE5EA}, {0x2206, 0x15FD}, {0x2206, 0xFC04}, {0x2206, 0xF8F9}, - {0x2206, 0xE08B}, {0x2206, 0x87AD}, {0x2206, 0x233A}, {0x2206, 0xAD22}, - {0x2206, 0x37E0}, {0x2206, 0xE020}, {0x2206, 0xE1E0}, {0x2206, 0x21AC}, - {0x2206, 0x212E}, {0x2206, 0xE0EA}, {0x2206, 0x14E1}, {0x2206, 0xEA15}, - {0x2206, 0xF627}, {0x2206, 0xE4EA}, {0x2206, 0x14E5}, {0x2206, 0xEA15}, - {0x2206, 0xE2EA}, {0x2206, 0x12E3}, {0x2206, 0xEA13}, {0x2206, 0x5A8F}, - {0x2206, 0x6A20}, {0x2206, 0xE6EA}, {0x2206, 0x12E7}, {0x2206, 0xEA13}, - {0x2206, 0xF726}, {0x2206, 0xE4EA}, {0x2206, 0x14E5}, {0x2206, 0xEA15}, - {0x2206, 0xF727}, {0x2206, 0xE4EA}, {0x2206, 0x14E5}, {0x2206, 0xEA15}, - {0x2206, 0xFDFC}, {0x2206, 0x04F8}, {0x2206, 0xF9E0}, {0x2206, 0x8B87}, - {0x2206, 0xAD23}, {0x2206, 0x38AD}, {0x2206, 0x2135}, {0x2206, 0xE0E0}, - {0x2206, 0x20E1}, {0x2206, 0xE021}, {0x2206, 0xAC21}, {0x2206, 0x2CE0}, - {0x2206, 0xEA14}, {0x2206, 0xE1EA}, {0x2206, 0x15F6}, {0x2206, 0x27E4}, - {0x2206, 0xEA14}, {0x2206, 0xE5EA}, {0x2206, 0x15E2}, {0x2206, 0xEA12}, - {0x2206, 0xE3EA}, {0x2206, 0x135A}, {0x2206, 0x8FE6}, {0x2206, 0xEA12}, - {0x2206, 0xE7EA}, {0x2206, 0x13F7}, {0x2206, 0x26E4}, {0x2206, 0xEA14}, - {0x2206, 0xE5EA}, {0x2206, 0x15F7}, {0x2206, 0x27E4}, {0x2206, 0xEA14}, - {0x2206, 0xE5EA}, {0x2206, 0x15FD}, {0x2206, 0xFC04}, {0x2206, 0xF8FA}, - {0x2206, 0xEF69}, {0x2206, 0xE08B}, {0x2206, 0x86AD}, {0x2206, 0x2146}, - {0x2206, 0xE0E0}, {0x2206, 0x22E1}, {0x2206, 0xE023}, {0x2206, 0x58C0}, - {0x2206, 0x5902}, {0x2206, 0x1E01}, {0x2206, 0xE18B}, {0x2206, 0x651F}, - {0x2206, 0x109E}, {0x2206, 0x33E4}, {0x2206, 0x8B65}, {0x2206, 0xAD21}, - {0x2206, 0x22AD}, {0x2206, 0x272A}, {0x2206, 0xD400}, {0x2206, 0x01BF}, - {0x2206, 0x34F2}, {0x2206, 0x022C}, {0x2206, 0xA2BF}, {0x2206, 0x34F5}, - {0x2206, 0x022C}, {0x2206, 0xE0E0}, {0x2206, 0x8B67}, {0x2206, 0x1B10}, - {0x2206, 0xAA14}, {0x2206, 0xE18B}, {0x2206, 0x660D}, {0x2206, 0x1459}, - {0x2206, 0x0FAE}, {0x2206, 0x05E1}, {0x2206, 0x8B66}, {0x2206, 0x590F}, - {0x2206, 0xBF85}, {0x2206, 0x6102}, {0x2206, 0x2CA2}, {0x2206, 0xEF96}, - {0x2206, 0xFEFC}, {0x2206, 0x04F8}, {0x2206, 0xF9FA}, {0x2206, 0xFBEF}, - {0x2206, 0x79E2}, {0x2206, 0x8AD2}, {0x2206, 0xAC19}, {0x2206, 0x2DE0}, - {0x2206, 0xE036}, {0x2206, 0xE1E0}, {0x2206, 0x37EF}, {0x2206, 0x311F}, - {0x2206, 0x325B}, {0x2206, 0x019E}, {0x2206, 0x1F7A}, {0x2206, 0x0159}, - {0x2206, 0x019F}, {0x2206, 0x0ABF}, {0x2206, 0x348E}, {0x2206, 0x022C}, - {0x2206, 0x31F6}, {0x2206, 0x06AE}, {0x2206, 0x0FF6}, {0x2206, 0x0302}, - {0x2206, 0x0470}, {0x2206, 0xF703}, {0x2206, 0xF706}, {0x2206, 0xBF34}, - {0x2206, 0x9302}, {0x2206, 0x2C31}, {0x2206, 0xAC1A}, {0x2206, 0x25E0}, - {0x2206, 0xE022}, {0x2206, 0xE1E0}, {0x2206, 0x23EF}, {0x2206, 0x300D}, - {0x2206, 0x311F}, {0x2206, 0x325B}, {0x2206, 0x029E}, {0x2206, 0x157A}, - {0x2206, 0x0258}, {0x2206, 0xC4A0}, {0x2206, 0x0408}, {0x2206, 0xBF34}, - {0x2206, 0x9E02}, {0x2206, 0x2C31}, {0x2206, 0xAE06}, {0x2206, 0xBF34}, - {0x2206, 0x9C02}, {0x2206, 0x2C31}, {0x2206, 0xAC1B}, {0x2206, 0x4AE0}, - {0x2206, 0xE012}, {0x2206, 0xE1E0}, {0x2206, 0x13EF}, {0x2206, 0x300D}, - {0x2206, 0x331F}, {0x2206, 0x325B}, {0x2206, 0x1C9E}, {0x2206, 0x3AEF}, - {0x2206, 0x325B}, {0x2206, 0x1C9F}, {0x2206, 0x09BF}, {0x2206, 0x3498}, - {0x2206, 0x022C}, {0x2206, 0x3102}, {0x2206, 0x83C5}, {0x2206, 0x5A03}, - {0x2206, 0x0D03}, {0x2206, 0x581C}, {0x2206, 0x1E20}, {0x2206, 0x0207}, - {0x2206, 0xA0A0}, {0x2206, 0x000E}, {0x2206, 0x0284}, {0x2206, 0x17AD}, - {0x2206, 0x1817}, {0x2206, 0xBF34}, {0x2206, 0x9A02}, {0x2206, 0x2C31}, - {0x2206, 0xAE0F}, {0x2206, 0xBF34}, {0x2206, 0xC802}, {0x2206, 0x2C31}, - {0x2206, 0xBF34}, {0x2206, 0xC502}, {0x2206, 0x2C31}, {0x2206, 0x0284}, - {0x2206, 0x52E6}, {0x2206, 0x8AD2}, {0x2206, 0xEF97}, {0x2206, 0xFFFE}, - {0x2206, 0xFDFC}, {0x2206, 0x04F8}, {0x2206, 0xBF34}, {0x2206, 0xDA02}, - {0x2206, 0x2CE0}, {0x2206, 0xE58A}, {0x2206, 0xD3BF}, {0x2206, 0x34D4}, - {0x2206, 0x022C}, {0x2206, 0xE00C}, {0x2206, 0x1159}, {0x2206, 0x02E0}, - {0x2206, 0x8AD3}, {0x2206, 0x1E01}, {0x2206, 0xE48A}, {0x2206, 0xD3D1}, - {0x2206, 0x00BF}, {0x2206, 0x34DA}, {0x2206, 0x022C}, {0x2206, 0xA2D1}, - {0x2206, 0x01BF}, {0x2206, 0x34D4}, {0x2206, 0x022C}, {0x2206, 0xA2BF}, - {0x2206, 0x34CB}, {0x2206, 0x022C}, {0x2206, 0xE0E5}, {0x2206, 0x8ACE}, - {0x2206, 0xBF85}, {0x2206, 0x6702}, {0x2206, 0x2CE0}, {0x2206, 0xE58A}, - {0x2206, 0xCFBF}, {0x2206, 0x8564}, {0x2206, 0x022C}, {0x2206, 0xE0E5}, - {0x2206, 0x8AD0}, {0x2206, 0xBF85}, {0x2206, 0x6A02}, {0x2206, 0x2CE0}, - {0x2206, 0xE58A}, {0x2206, 0xD1FC}, {0x2206, 0x04F8}, {0x2206, 0xE18A}, - {0x2206, 0xD1BF}, {0x2206, 0x856A}, {0x2206, 0x022C}, {0x2206, 0xA2E1}, - {0x2206, 0x8AD0}, {0x2206, 0xBF85}, {0x2206, 0x6402}, {0x2206, 0x2CA2}, - {0x2206, 0xE18A}, {0x2206, 0xCFBF}, {0x2206, 0x8567}, {0x2206, 0x022C}, - {0x2206, 0xA2E1}, {0x2206, 0x8ACE}, {0x2206, 0xBF34}, {0x2206, 0xCB02}, - {0x2206, 0x2CA2}, {0x2206, 0xE18A}, {0x2206, 0xD3BF}, {0x2206, 0x34DA}, - {0x2206, 0x022C}, {0x2206, 0xA2E1}, {0x2206, 0x8AD3}, {0x2206, 0x0D11}, - {0x2206, 0xBF34}, {0x2206, 0xD402}, {0x2206, 0x2CA2}, {0x2206, 0xFC04}, - {0x2206, 0xF9A0}, {0x2206, 0x0405}, {0x2206, 0xE38A}, {0x2206, 0xD4AE}, - {0x2206, 0x13A0}, {0x2206, 0x0805}, {0x2206, 0xE38A}, {0x2206, 0xD5AE}, - {0x2206, 0x0BA0}, {0x2206, 0x0C05}, {0x2206, 0xE38A}, {0x2206, 0xD6AE}, - {0x2206, 0x03E3}, {0x2206, 0x8AD7}, {0x2206, 0xEF13}, {0x2206, 0xBF34}, - {0x2206, 0xCB02}, {0x2206, 0x2CA2}, {0x2206, 0xEF13}, {0x2206, 0x0D11}, - {0x2206, 0xBF85}, {0x2206, 0x6702}, {0x2206, 0x2CA2}, {0x2206, 0xEF13}, - {0x2206, 0x0D14}, {0x2206, 0xBF85}, {0x2206, 0x6402}, {0x2206, 0x2CA2}, - {0x2206, 0xEF13}, {0x2206, 0x0D17}, {0x2206, 0xBF85}, {0x2206, 0x6A02}, - {0x2206, 0x2CA2}, {0x2206, 0xFD04}, {0x2206, 0xF8E0}, {0x2206, 0x8B85}, - {0x2206, 0xAD27}, {0x2206, 0x2DE0}, {0x2206, 0xE036}, {0x2206, 0xE1E0}, - {0x2206, 0x37E1}, {0x2206, 0x8B73}, {0x2206, 0x1F10}, {0x2206, 0x9E20}, - {0x2206, 0xE48B}, {0x2206, 0x73AC}, {0x2206, 0x200B}, {0x2206, 0xAC21}, - {0x2206, 0x0DAC}, {0x2206, 0x250F}, {0x2206, 0xAC27}, {0x2206, 0x0EAE}, - {0x2206, 0x0F02}, {0x2206, 0x84CC}, {0x2206, 0xAE0A}, {0x2206, 0x0284}, - {0x2206, 0xD1AE}, {0x2206, 0x05AE}, {0x2206, 0x0302}, {0x2206, 0x84D8}, - {0x2206, 0xFC04}, {0x2206, 0xEE8B}, {0x2206, 0x6800}, {0x2206, 0x0402}, - {0x2206, 0x84E5}, {0x2206, 0x0285}, {0x2206, 0x2804}, {0x2206, 0x0285}, - {0x2206, 0x4904}, {0x2206, 0xEE8B}, {0x2206, 0x6800}, {0x2206, 0xEE8B}, - {0x2206, 0x6902}, {0x2206, 0x04F8}, {0x2206, 0xF9E0}, {0x2206, 0x8B85}, - {0x2206, 0xAD26}, {0x2206, 0x38D0}, {0x2206, 0x0B02}, {0x2206, 0x2B4D}, - {0x2206, 0x5882}, {0x2206, 0x7882}, {0x2206, 0x9F2D}, {0x2206, 0xE08B}, - {0x2206, 0x68E1}, {0x2206, 0x8B69}, {0x2206, 0x1F10}, {0x2206, 0x9EC8}, - {0x2206, 0x10E4}, {0x2206, 0x8B68}, {0x2206, 0xE0E0}, {0x2206, 0x00E1}, - {0x2206, 0xE001}, {0x2206, 0xF727}, {0x2206, 0xE4E0}, {0x2206, 0x00E5}, - {0x2206, 0xE001}, {0x2206, 0xE2E0}, {0x2206, 0x20E3}, {0x2206, 0xE021}, - {0x2206, 0xAD30}, {0x2206, 0xF7F6}, {0x2206, 0x27E4}, {0x2206, 0xE000}, - {0x2206, 0xE5E0}, {0x2206, 0x01FD}, {0x2206, 0xFC04}, {0x2206, 0xF8FA}, - {0x2206, 0xEF69}, {0x2206, 0xE08B}, {0x2206, 0x86AD}, {0x2206, 0x2212}, - {0x2206, 0xE0E0}, {0x2206, 0x14E1}, {0x2206, 0xE015}, {0x2206, 0xAD26}, - {0x2206, 0x9CE1}, {0x2206, 0x85E0}, {0x2206, 0xBF85}, {0x2206, 0x6D02}, - {0x2206, 0x2CA2}, {0x2206, 0xEF96}, {0x2206, 0xFEFC}, {0x2206, 0x04F8}, - {0x2206, 0xFAEF}, {0x2206, 0x69E0}, {0x2206, 0x8B86}, {0x2206, 0xAD22}, - {0x2206, 0x09E1}, {0x2206, 0x85E1}, {0x2206, 0xBF85}, {0x2206, 0x6D02}, - {0x2206, 0x2CA2}, {0x2206, 0xEF96}, {0x2206, 0xFEFC}, {0x2206, 0x0464}, - {0x2206, 0xE48C}, {0x2206, 0xFDE4}, {0x2206, 0x80CA}, {0x2206, 0xE480}, - {0x2206, 0x66E0}, {0x2206, 0x8E70}, {0x2206, 0xE076}, {0x2205, 0xE142}, - {0x2206, 0x0701}, {0x2205, 0xE140}, {0x2206, 0x0405}, {0x220F, 0x0000}, - {0x221F, 0x0000}, {0x2200, 0x1340}, {0x133E, 0x000E}, {0x133F, 0x0010}, - {0x13EB, 0x11BB} -}; - -static const struct rtl8367b_initval rtl8367r_vb_initvals_1[] = { +static const struct rtl8367b_initval rtl8367b_initvals[] = { {0x1B03, 0x0876}, {0x1200, 0x7FC4}, {0x1305, 0xC000}, {0x121E, 0x03CA}, {0x1233, 0x0352}, {0x1234, 0x0064}, {0x1237, 0x0096}, {0x1238, 0x0078}, {0x1239, 0x0084}, {0x123A, 0x0030}, {0x205F, 0x0002}, {0x2059, 0x1A00}, @@ -730,39 +516,23 @@ static int rtl8367b_write_phy_reg(struct rtl8366_smi *smi, static int rtl8367b_init_regs(struct rtl8366_smi *smi) { const struct rtl8367b_initval *initvals; - u32 chip_num; - u32 chip_ver; - u32 rlvid; int count; - int err; - REG_WR(smi, RTL8367B_RTL_MAGIC_ID_REG, RTL8367B_RTL_MAGIC_ID_VAL); - REG_RD(smi, RTL8367B_CHIP_NUMBER_REG, &chip_num); - REG_RD(smi, RTL8367B_CHIP_VER_REG, &chip_ver); - - if ((chip_ver == 0x0020 || chip_ver == 0x00A0) && chip_num == 0x6367) { + switch (smi->rtl8367b_chip) { + case RTL8367B_CHIP_RTL8367RB: + case RTL8367B_CHIP_RTL8367R_VB: + initvals = rtl8367b_initvals; + count = ARRAY_SIZE(rtl8367b_initvals); + break; + case RTL8367B_CHIP_RTL8367RB_VB: + case RTL8367B_CHIP_RTL8367S: initvals = rtl8367c_initvals; count = ARRAY_SIZE(rtl8367c_initvals); - } else { - rlvid = (chip_ver >> RTL8367B_CHIP_VER_RLVID_SHIFT) & - RTL8367B_CHIP_VER_RLVID_MASK; - switch (rlvid) { - case 0: - initvals = rtl8367r_vb_initvals_0; - count = ARRAY_SIZE(rtl8367r_vb_initvals_0); - break; - case 1: - initvals = rtl8367r_vb_initvals_1; - count = ARRAY_SIZE(rtl8367r_vb_initvals_1); - break; - default: - dev_err(smi->parent, "unknow rlvid %u\n", rlvid); - return -ENODEV; - } + break; + default: + return -ENODEV; } - /* TODO: disable RLTP */ - return rtl8367b_write_initvals(smi, initvals, count); } @@ -939,21 +709,48 @@ static int rtl8367b_extif_init(struct rtl8366_smi *smi, int id, } #ifdef CONFIG_OF -static int rtl8367b_extif_init_of(struct rtl8366_smi *smi, int id, +static int rtl8367b_extif_init_of(struct rtl8366_smi *smi, const char *name) { struct rtl8367_extif_config *cfg; const __be32 *prop; int size; int err; + unsigned cpu_port; + unsigned id = UINT_MAX; prop = of_get_property(smi->parent->of_node, name, &size); - if (!prop) - return rtl8367b_extif_init(smi, id, NULL); + if (!prop || (size != (10 * sizeof(*prop)))) { + dev_err(smi->parent, "%s property is not defined or invalid\n", name); + err = -EINVAL; + goto err_init; + } - if (size != (9 * sizeof(*prop))) { - dev_err(smi->parent, "%s property is invalid\n", name); - return -EINVAL; + cpu_port = be32_to_cpup(prop++); + switch (cpu_port) { + case RTL8367B_CPU_PORT_NUM: + case RTL8367B_CPU_PORT_NUM + 1: + case RTL8367B_CPU_PORT_NUM + 2: + if (smi->rtl8367b_chip == RTL8367B_CHIP_RTL8367R_VB) { /* for the RTL8367R-VB chip, cpu_port 5 corresponds to extif1 */ + if (cpu_port == RTL8367B_CPU_PORT_NUM) + id = 1; + else { + dev_err(smi->parent, "wrong cpu_port %u in %s property\n", cpu_port, name); + err = -EINVAL; + goto err_init; + } + } else { + id = cpu_port - RTL8367B_CPU_PORT_NUM; + } + if (smi->cpu_port == UINT_MAX) { + dev_info(smi->parent, "cpu_port:%u, assigned to extif%u\n", cpu_port, id); + smi->cpu_port = cpu_port; + } + break; + default: + dev_err(smi->parent, "wrong cpu_port %u in %s property\n", cpu_port, name); + err = -EINVAL; + goto err_init; } cfg = kzalloc(sizeof(struct rtl8367_extif_config), GFP_KERNEL); @@ -973,10 +770,15 @@ static int rtl8367b_extif_init_of(struct rtl8366_smi *smi, int id, err = rtl8367b_extif_init(smi, id, cfg); kfree(cfg); +err_init: + if (id != 0) rtl8367b_extif_init(smi, 0, NULL); + if (id != 1) rtl8367b_extif_init(smi, 1, NULL); + if (id != 2) rtl8367b_extif_init(smi, 2, NULL); + return err; } #else -static int rtl8367b_extif_init_of(struct rtl8366_smi *smi, int id, +static int rtl8367b_extif_init_of(struct rtl8366_smi *smi, const char *name) { return -EINVAL; @@ -997,15 +799,7 @@ static int rtl8367b_setup(struct rtl8366_smi *smi) /* initialize external interfaces */ if (smi->parent->of_node) { - err = rtl8367b_extif_init_of(smi, 0, "realtek,extif0"); - if (err) - return err; - - err = rtl8367b_extif_init_of(smi, 1, "realtek,extif1"); - if (err) - return err; - - err = rtl8367b_extif_init_of(smi, 2, "realtek,extif2"); + err = rtl8367b_extif_init_of(smi, "realtek,extif"); if (err) return err; } else { @@ -1530,10 +1324,10 @@ static int rtl8367b_detect(struct rtl8366_smi *smi) const char *chip_name = NULL; u32 chip_num; u32 chip_ver; - u32 chip_mode; int ret; - /* TODO: improve chip detection */ + smi->rtl8367b_chip = RTL8367B_CHIP_UNKNOWN; + rtl8366_smi_write_reg(smi, RTL8367B_RTL_MAGIC_ID_REG, RTL8367B_RTL_MAGIC_ID_VAL); @@ -1551,44 +1345,36 @@ static int rtl8367b_detect(struct rtl8366_smi *smi) return ret; } - ret = rtl8366_smi_read_reg(smi, RTL8367B_CHIP_MODE_REG, &chip_mode); - if (ret) { - dev_err(smi->parent, "unable to read %s register\n", - "chip mode"); - return ret; - } - switch (chip_ver) { case 0x0020: - if (chip_num == 0x6367) + if (chip_num == 0x6367) { chip_name = "8367RB-VB"; + smi->rtl8367b_chip = RTL8367B_CHIP_RTL8367RB_VB; + } break; case 0x00A0: - if (chip_num == 0x6367) + if (chip_num == 0x6367) { chip_name = "8367S"; + smi->rtl8367b_chip = RTL8367B_CHIP_RTL8367S; + } break; case 0x1000: chip_name = "8367RB"; + smi->rtl8367b_chip = RTL8367B_CHIP_RTL8367RB; break; case 0x1010: chip_name = "8367R-VB"; + smi->rtl8367b_chip = RTL8367B_CHIP_RTL8367R_VB; } if (!chip_name) { dev_err(smi->parent, - "unknown chip num:%04x ver:%04x, mode:%04x\n", - chip_num, chip_ver, chip_mode); + "unknown chip (num:%04x ver:%04x)\n", + chip_num, chip_ver); return -ENODEV; } - dev_info(smi->parent, "RTL%s chip found\n", chip_name); - - if (of_property_present(smi->parent->of_node, "realtek,extif2")) - smi->cpu_port = RTL8367B_CPU_PORT_NUM + 2; - else if (of_property_present(smi->parent->of_node, "realtek,extif1") && (chip_ver != 0x1010)) /* for the RTL8367R-VB chip, extif1 corresponds to cpu_port 5 */ - smi->cpu_port = RTL8367B_CPU_PORT_NUM + 1; - - dev_info(smi->parent, "CPU port: %u\n", smi->cpu_port); + dev_info(smi->parent, "RTL%s chip found (num:%04x ver:%04x)\n", chip_name, chip_num, chip_ver); return 0; } @@ -1628,7 +1414,7 @@ static int rtl8367b_probe(struct platform_device *pdev) smi->cmd_write = 0xb8; smi->ops = &rtl8367b_smi_ops; smi->num_ports = RTL8367B_NUM_PORTS; - smi->cpu_port = RTL8367B_CPU_PORT_NUM; + smi->cpu_port = UINT_MAX; /* not defined yet */ smi->num_vlan_mc = RTL8367B_NUM_VLANS; smi->mib_counters = rtl8367b_mib_counters; smi->num_mib_counters = ARRAY_SIZE(rtl8367b_mib_counters); diff --git a/target/linux/generic/hack-6.6/230-openwrt_lzma_options.patch b/target/linux/generic/hack-6.6/230-openwrt_lzma_options.patch index a22acafea1..ca70da7e31 100644 --- a/target/linux/generic/hack-6.6/230-openwrt_lzma_options.patch +++ b/target/linux/generic/hack-6.6/230-openwrt_lzma_options.patch @@ -23,7 +23,7 @@ Signed-off-by: Imre Kaloz { {0x02, 0x21}, "lz4", unlz4 }, --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib -@@ -456,10 +456,10 @@ quiet_cmd_bzip2_with_size = BZIP2 $@ +@@ -460,10 +460,10 @@ quiet_cmd_bzip2_with_size = BZIP2 $@ # --------------------------------------------------------------------------- quiet_cmd_lzma = LZMA $@ diff --git a/target/linux/generic/hack-6.6/902-debloat_proc.patch b/target/linux/generic/hack-6.6/902-debloat_proc.patch index bf14d95999..8b774863a9 100644 --- a/target/linux/generic/hack-6.6/902-debloat_proc.patch +++ b/target/linux/generic/hack-6.6/902-debloat_proc.patch @@ -341,7 +341,7 @@ Signed-off-by: Felix Fietkau --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c -@@ -3036,11 +3036,13 @@ static const struct seq_operations fib_r +@@ -3037,11 +3037,13 @@ static const struct seq_operations fib_r int __net_init fib_proc_init(struct net *net) { @@ -357,7 +357,7 @@ Signed-off-by: Felix Fietkau fib_triestat_seq_show, NULL)) goto out2; -@@ -3051,17 +3053,21 @@ int __net_init fib_proc_init(struct net +@@ -3052,17 +3054,21 @@ int __net_init fib_proc_init(struct net return 0; out3: diff --git a/target/linux/generic/hack-6.6/904-debloat_dma_buf.patch b/target/linux/generic/hack-6.6/904-debloat_dma_buf.patch index 4d2ea46212..355bd0d70c 100644 --- a/target/linux/generic/hack-6.6/904-debloat_dma_buf.patch +++ b/target/linux/generic/hack-6.6/904-debloat_dma_buf.patch @@ -73,7 +73,7 @@ Signed-off-by: Felix Fietkau +MODULE_LICENSE("GPL"); --- a/kernel/sched/core.c +++ b/kernel/sched/core.c -@@ -4486,6 +4486,7 @@ int wake_up_state(struct task_struct *p, +@@ -4483,6 +4483,7 @@ int wake_up_state(struct task_struct *p, { return try_to_wake_up(p, state, 0); } diff --git a/target/linux/generic/hack-6.6/911-kobject_add_broadcast_uevent.patch b/target/linux/generic/hack-6.6/911-kobject_add_broadcast_uevent.patch index 7a21e73dae..56cd696e18 100644 --- a/target/linux/generic/hack-6.6/911-kobject_add_broadcast_uevent.patch +++ b/target/linux/generic/hack-6.6/911-kobject_add_broadcast_uevent.patch @@ -30,7 +30,7 @@ Signed-off-by: Felix Fietkau #endif /* _KOBJECT_H_ */ --- a/lib/kobject_uevent.c +++ b/lib/kobject_uevent.c -@@ -691,6 +691,43 @@ int add_uevent_var(struct kobj_uevent_en +@@ -706,6 +706,43 @@ int add_uevent_var(struct kobj_uevent_en EXPORT_SYMBOL_GPL(add_uevent_var); #if defined(CONFIG_NET) diff --git a/target/linux/generic/pending-6.6/630-packet_socket_type.patch b/target/linux/generic/pending-6.6/630-packet_socket_type.patch index fd00e1e052..2b753efa67 100644 --- a/target/linux/generic/pending-6.6/630-packet_socket_type.patch +++ b/target/linux/generic/pending-6.6/630-packet_socket_type.patch @@ -30,7 +30,7 @@ Signed-off-by: Felix Fietkau #define PACKET_FANOUT_LB 1 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c -@@ -1864,6 +1864,7 @@ static int packet_rcv_spkt(struct sk_buf +@@ -1925,6 +1925,7 @@ static int packet_rcv_spkt(struct sk_buf { struct sock *sk; struct sockaddr_pkt *spkt; @@ -38,7 +38,7 @@ Signed-off-by: Felix Fietkau /* * When we registered the protocol we saved the socket in the data -@@ -1871,6 +1872,7 @@ static int packet_rcv_spkt(struct sk_buf +@@ -1932,6 +1933,7 @@ static int packet_rcv_spkt(struct sk_buf */ sk = pt->af_packet_priv; @@ -46,7 +46,7 @@ Signed-off-by: Felix Fietkau /* * Yank back the headers [hope the device set this -@@ -1883,7 +1885,7 @@ static int packet_rcv_spkt(struct sk_buf +@@ -1944,7 +1946,7 @@ static int packet_rcv_spkt(struct sk_buf * so that this procedure is noop. */ @@ -55,7 +55,7 @@ Signed-off-by: Felix Fietkau goto out; if (!net_eq(dev_net(dev), sock_net(sk))) -@@ -2129,12 +2131,12 @@ static int packet_rcv(struct sk_buff *sk +@@ -2190,12 +2192,12 @@ static int packet_rcv(struct sk_buff *sk unsigned int snaplen, res; bool is_drop_n_account = false; @@ -71,7 +71,7 @@ Signed-off-by: Felix Fietkau if (!net_eq(dev_net(dev), sock_net(sk))) goto drop; -@@ -2261,12 +2263,12 @@ static int tpacket_rcv(struct sk_buff *s +@@ -2322,12 +2324,12 @@ static int tpacket_rcv(struct sk_buff *s BUILD_BUG_ON(TPACKET_ALIGN(sizeof(*h.h2)) != 32); BUILD_BUG_ON(TPACKET_ALIGN(sizeof(*h.h3)) != 48); @@ -87,7 +87,7 @@ Signed-off-by: Felix Fietkau if (!net_eq(dev_net(dev), sock_net(sk))) goto drop; -@@ -3385,6 +3387,7 @@ static int packet_create(struct net *net +@@ -3451,6 +3453,7 @@ static int packet_create(struct net *net mutex_init(&po->pg_vec_lock); po->rollover = NULL; po->prot_hook.func = packet_rcv; @@ -95,7 +95,7 @@ Signed-off-by: Felix Fietkau if (sock->type == SOCK_PACKET) po->prot_hook.func = packet_rcv_spkt; -@@ -4036,6 +4039,16 @@ packet_setsockopt(struct socket *sock, i +@@ -4118,6 +4121,16 @@ packet_setsockopt(struct socket *sock, i packet_sock_flag_set(po, PACKET_SOCK_QDISC_BYPASS, val); return 0; } @@ -112,7 +112,7 @@ Signed-off-by: Felix Fietkau default: return -ENOPROTOOPT; } -@@ -4095,6 +4108,13 @@ static int packet_getsockopt(struct sock +@@ -4177,6 +4190,13 @@ static int packet_getsockopt(struct sock case PACKET_VNET_HDR_SZ: val = READ_ONCE(po->vnet_hdr_sz); break; diff --git a/target/linux/generic/pending-6.6/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch b/target/linux/generic/pending-6.6/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch index cc92e20f63..f754705dc6 100644 --- a/target/linux/generic/pending-6.6/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch +++ b/target/linux/generic/pending-6.6/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch @@ -66,7 +66,7 @@ Signed-off-by: Jonas Gorski static void rt_fibinfo_free(struct rtable __rcu **rtp) --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c -@@ -2783,6 +2783,7 @@ static const char *const rtn_type_names[ +@@ -2784,6 +2784,7 @@ static const char *const rtn_type_names[ [RTN_THROW] = "THROW", [RTN_NAT] = "NAT", [RTN_XRESOLVE] = "XRESOLVE", diff --git a/target/linux/generic/pending-6.6/680-net-add-TCP-fraglist-GRO-support.patch b/target/linux/generic/pending-6.6/680-net-add-TCP-fraglist-GRO-support.patch index 7672f46d20..6ce095cc10 100644 --- a/target/linux/generic/pending-6.6/680-net-add-TCP-fraglist-GRO-support.patch +++ b/target/linux/generic/pending-6.6/680-net-add-TCP-fraglist-GRO-support.patch @@ -31,7 +31,7 @@ Signe-off-by: Felix Fietkau static inline void gro_normal_list(struct napi_struct *napi) --- a/include/net/tcp.h +++ b/include/net/tcp.h -@@ -2083,7 +2083,10 @@ void tcp_v4_destroy_sock(struct sock *sk +@@ -2084,7 +2084,10 @@ void tcp_v4_destroy_sock(struct sock *sk struct sk_buff *tcp_gso_segment(struct sk_buff *skb, netdev_features_t features); diff --git a/target/linux/generic/pending-6.6/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch b/target/linux/generic/pending-6.6/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch index 15d385c5fd..3f3d7572e0 100644 --- a/target/linux/generic/pending-6.6/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch +++ b/target/linux/generic/pending-6.6/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch @@ -17,7 +17,7 @@ Signed-off-by: Tobias Waldekranz --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -6992,6 +6992,7 @@ static int mv88e6xxx_register_switch(str +@@ -6993,6 +6993,7 @@ static int mv88e6xxx_register_switch(str ds->ops = &mv88e6xxx_switch_ops; ds->ageing_time_min = chip->info->age_time_coeff; ds->ageing_time_max = chip->info->age_time_coeff * U8_MAX; diff --git a/target/linux/ipq40xx/Makefile b/target/linux/ipq40xx/Makefile index 9aab99b4f2..4f816d9532 100644 --- a/target/linux/ipq40xx/Makefile +++ b/target/linux/ipq40xx/Makefile @@ -3,7 +3,7 @@ include $(TOPDIR)/rules.mk ARCH:=arm BOARD:=ipq40xx BOARDNAME:=Qualcomm Atheros IPQ40XX -FEATURES:=squashfs fpu ramdisk nand +FEATURES:=squashfs fpu ramdisk CPU_TYPE:=cortex-a7 CPU_SUBTYPE:=neon-vfpv4 SUBTARGETS:=generic chromium mikrotik diff --git a/target/linux/ipq40xx/config-6.6 b/target/linux/ipq40xx/config-6.6 index 3049efc3d6..683463628f 100644 --- a/target/linux/ipq40xx/config-6.6 +++ b/target/linux/ipq40xx/config-6.6 @@ -306,11 +306,6 @@ CONFIG_MTD_SPI_NOR=y CONFIG_MTD_SPLIT_FIRMWARE=y CONFIG_MTD_SPLIT_FIT_FW=y CONFIG_MTD_SPLIT_WRGG_FW=y -CONFIG_MTD_UBI=y -CONFIG_MTD_UBI_BEB_LIMIT=20 -CONFIG_MTD_UBI_BLOCK=y -CONFIG_MTD_UBI_NVMEM=y -CONFIG_MTD_UBI_WL_THRESHOLD=4096 CONFIG_MUTEX_SPIN_ON_OWNER=y CONFIG_NEED_DMA_MAP_STATE=y CONFIG_NEON=y @@ -532,7 +527,6 @@ CONFIG_TIMER_OF=y CONFIG_TIMER_PROBE=y CONFIG_TREE_RCU=y CONFIG_TREE_SRCU=y -CONFIG_UBIFS_FS=y CONFIG_UEVENT_HELPER_PATH="" CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" CONFIG_UNWINDER_ARM=y diff --git a/target/linux/ipq40xx/generic/config-default b/target/linux/ipq40xx/generic/config-default new file mode 100644 index 0000000000..bd9876a0b6 --- /dev/null +++ b/target/linux/ipq40xx/generic/config-default @@ -0,0 +1,6 @@ +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_BEB_LIMIT=20 +CONFIG_MTD_UBI_BLOCK=y +CONFIG_MTD_UBI_NVMEM=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_UBIFS_FS=y diff --git a/target/linux/ipq40xx/generic/target.mk b/target/linux/ipq40xx/generic/target.mk index 90c1b762af..4ff40dea2b 100644 --- a/target/linux/ipq40xx/generic/target.mk +++ b/target/linux/ipq40xx/generic/target.mk @@ -1,3 +1,3 @@ BOARDNAME:=Generic -FEATURES+=emmc +FEATURES+=emmc nand DEFAULT_PACKAGES += ath10k-board-qca4019 diff --git a/target/linux/ipq40xx/mikrotik/config-default b/target/linux/ipq40xx/mikrotik/config-default index ab470ecb41..805e6db23b 100644 --- a/target/linux/ipq40xx/mikrotik/config-default +++ b/target/linux/ipq40xx/mikrotik/config-default @@ -4,3 +4,9 @@ CONFIG_MTD_ROUTERBOOT_PARTS=y CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE=y CONFIG_MTD_SPLIT_MINOR_FW=y # CONFIG_NVMEM_LAYOUT_MIKROTIK is not set +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_BEB_LIMIT=20 +CONFIG_MTD_UBI_BLOCK=y +CONFIG_MTD_UBI_NVMEM=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_UBIFS_FS=y diff --git a/target/linux/ipq40xx/mikrotik/target.mk b/target/linux/ipq40xx/mikrotik/target.mk index 4530a90985..12bf8a4cd3 100644 --- a/target/linux/ipq40xx/mikrotik/target.mk +++ b/target/linux/ipq40xx/mikrotik/target.mk @@ -1,4 +1,4 @@ BOARDNAME:=MikroTik -FEATURES += minor +FEATURES += minor nand KERNEL_IMAGES:=vmlinux IMAGES_DIR:=compressed diff --git a/target/linux/lantiq/patches-6.6/0001-MIPS-lantiq-add-pcie-driver.patch b/target/linux/lantiq/patches-6.6/0001-MIPS-lantiq-add-pcie-driver.patch index 3e23c0f23d..fea925247b 100644 --- a/target/linux/lantiq/patches-6.6/0001-MIPS-lantiq-add-pcie-driver.patch +++ b/target/linux/lantiq/patches-6.6/0001-MIPS-lantiq-add-pcie-driver.patch @@ -5524,7 +5524,7 @@ Signed-off-by: John Crispin (transaction layer end-to-end CRC checking). --- a/include/linux/pci.h +++ b/include/linux/pci.h -@@ -1599,6 +1599,8 @@ void pci_walk_bus_locked(struct pci_bus +@@ -1600,6 +1600,8 @@ void pci_walk_bus_locked(struct pci_bus void *userdata); int pci_cfg_space_size(struct pci_dev *dev); unsigned char pci_bus_max_busnr(struct pci_bus *bus); diff --git a/target/linux/mvebu/image/cortexa9.mk b/target/linux/mvebu/image/cortexa9.mk index ec532b8439..e37f5689cb 100644 --- a/target/linux/mvebu/image/cortexa9.mk +++ b/target/linux/mvebu/image/cortexa9.mk @@ -106,7 +106,8 @@ define Device/cznic_turris-omnia DEVICE_PACKAGES := \ mkf2fs e2fsprogs kmod-fs-vfat kmod-nls-cp437 kmod-nls-iso8859-1 \ wpad-basic-openssl kmod-ath9k kmod-ath10k-ct ath10k-firmware-qca988x-ct \ - kmod-mt7915-firmware partx-utils kmod-i2c-mux-pca954x kmod-leds-turris-omnia + kmod-mt7915-firmware partx-utils kmod-i2c-mux-pca954x kmod-leds-turris-omnia \ + kmod-turris-omnia-mcu kmod-gpio-button-hotplug omnia-mcu-firmware omnia-mcutool IMAGES := sysupgrade.img.gz IMAGE/sysupgrade.img.gz := boot-scr | boot-img | sdcard-img | gzip | append-metadata SUPPORTED_DEVICES += armada-385-turris-omnia diff --git a/target/linux/mvebu/modules.mk b/target/linux/mvebu/modules.mk index 311cc07c7f..e6fa6ab3ed 100644 --- a/target/linux/mvebu/modules.mk +++ b/target/linux/mvebu/modules.mk @@ -17,6 +17,27 @@ endef $(eval $(call KernelPackage,linkstation-poweroff)) +define KernelPackage/turris-omnia-mcu + SUBMENU:=$(OTHER_MENU) + TITLE:=CZ.NIC's Turris Omnia MCU driver + DEPENDS:=@TARGET_mvebu_cortexa9 + KCONFIG:= \ + CONFIG_CZNIC_PLATFORMS=y \ + CONFIG_TURRIS_OMNIA_MCU + FILES:=$(LINUX_DIR)/drivers/platform/cznic/turris-omnia-mcu.ko + AUTOLOAD:=$(call AutoProbe,turris-omnia-mcu,1) +endef + +define KernelPackage/turris-omnia-mcu/description + This adds support for the features implemented by the microcontroller + on the CZ.NIC's Turris Omnia SOHO router, including true board + poweroff, the ability to configure wake up from powered off state at + a specific time, MCU watchdog and MCU connected GPIO pins. +endef + +$(eval $(call KernelPackage,turris-omnia-mcu)) + + define KernelPackage/leds-turris-omnia SUBMENU:=$(LEDS_MENU) TITLE:=LED support for CZ.NIC's Turris Omnia diff --git a/target/linux/mvebu/patches-6.6/820-v6.11-01-dt-bindings-firmware-add-cznic-turris-omnia-mcu-bind.patch b/target/linux/mvebu/patches-6.6/820-v6.11-01-dt-bindings-firmware-add-cznic-turris-omnia-mcu-bind.patch new file mode 100644 index 0000000000..4d6d8e82c2 --- /dev/null +++ b/target/linux/mvebu/patches-6.6/820-v6.11-01-dt-bindings-firmware-add-cznic-turris-omnia-mcu-bind.patch @@ -0,0 +1,125 @@ +From cdfed4d05780450817ef96567e2cd8d355ca9e70 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 1 Jul 2024 13:30:03 +0200 +Subject: [PATCH 01/11] dt-bindings: firmware: add cznic,turris-omnia-mcu + binding +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add binding for cznic,turris-omnia-mcu, the device-tree node +representing the system-controller features provided by the MCU on the +Turris Omnia router. + +Signed-off-by: Marek Behún +Reviewed-by: Krzysztof Kozlowski +Reviewed-by: Conor Dooley +Reviewed-by: Andy Shevchenko +Acked-by: Bartosz Golaszewski +Link: https://lore.kernel.org/r/20240701113010.16447-2-kabel@kernel.org +Signed-off-by: Arnd Bergmann +--- + .../firmware/cznic,turris-omnia-mcu.yaml | 86 +++++++++++++++++++ + MAINTAINERS | 1 + + 2 files changed, 87 insertions(+) + create mode 100644 Documentation/devicetree/bindings/firmware/cznic,turris-omnia-mcu.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/firmware/cznic,turris-omnia-mcu.yaml +@@ -0,0 +1,86 @@ ++# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/firmware/cznic,turris-omnia-mcu.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: CZ.NIC's Turris Omnia MCU ++ ++maintainers: ++ - Marek Behún ++ ++description: ++ The MCU on Turris Omnia acts as a system controller providing additional ++ GPIOs, interrupts, watchdog, system power off and wakeup configuration. ++ ++properties: ++ compatible: ++ const: cznic,turris-omnia-mcu ++ ++ reg: ++ description: MCU I2C slave address ++ maxItems: 1 ++ ++ interrupts: ++ maxItems: 1 ++ ++ interrupt-controller: true ++ ++ '#interrupt-cells': ++ const: 2 ++ description: | ++ The first cell specifies the interrupt number (0 to 63), the second cell ++ specifies interrupt type (which can be one of IRQ_TYPE_EDGE_RISING, ++ IRQ_TYPE_EDGE_FALLING or IRQ_TYPE_EDGE_BOTH). ++ The interrupt numbers correspond sequentially to GPIO numbers, taking the ++ GPIO banks into account: ++ IRQ number GPIO bank GPIO pin within bank ++ 0 - 15 0 0 - 15 ++ 16 - 47 1 0 - 31 ++ 48 - 63 2 0 - 15 ++ There are several exceptions: ++ IRQ number meaning ++ 11 LED panel brightness changed by button press ++ 13 TRNG entropy ready ++ 14 ECDSA message signature computation done ++ ++ gpio-controller: true ++ ++ '#gpio-cells': ++ const: 3 ++ description: ++ The first cell is bank number (0, 1 or 2), the second cell is pin number ++ within the bank (0 to 15 for banks 0 and 2, 0 to 31 for bank 1), and the ++ third cell specifies consumer flags. ++ ++required: ++ - compatible ++ - reg ++ - interrupts ++ - interrupt-controller ++ - gpio-controller ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ ++ i2c { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ system-controller@2a { ++ compatible = "cznic,turris-omnia-mcu"; ++ reg = <0x2a>; ++ ++ interrupt-parent = <&gpio1>; ++ interrupts = <11 IRQ_TYPE_NONE>; ++ ++ gpio-controller; ++ #gpio-cells = <3>; ++ ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ }; ++ }; +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -2104,6 +2104,7 @@ F: Documentation/ABI/testing/sysfs-bus-m + F: Documentation/ABI/testing/sysfs-firmware-turris-mox-rwtm + F: Documentation/devicetree/bindings/bus/moxtet.txt + F: Documentation/devicetree/bindings/firmware/cznic,turris-mox-rwtm.txt ++F: Documentation/devicetree/bindings/firmware/cznic,turris-omnia-mcu.yaml + F: Documentation/devicetree/bindings/gpio/gpio-moxtet.txt + F: Documentation/devicetree/bindings/leds/cznic,turris-omnia-leds.yaml + F: Documentation/devicetree/bindings/watchdog/armada-37xx-wdt.txt diff --git a/target/linux/mvebu/patches-6.6/820-v6.11-02-platform-cznic-Add-preliminary-support-for-Turris-Om.patch b/target/linux/mvebu/patches-6.6/820-v6.11-02-platform-cznic-Add-preliminary-support-for-Turris-Om.patch new file mode 100644 index 0000000000..72bd18d144 --- /dev/null +++ b/target/linux/mvebu/patches-6.6/820-v6.11-02-platform-cznic-Add-preliminary-support-for-Turris-Om.patch @@ -0,0 +1,922 @@ +From 4a63f684c8badfc43f384df2291ed2566909a3bc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 1 Jul 2024 13:30:04 +0200 +Subject: [PATCH 02/11] platform: cznic: Add preliminary support for Turris + Omnia MCU +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add the basic skeleton for a new platform driver for the microcontroller +found on the Turris Omnia board. + +Signed-off-by: Marek Behún +Reviewed-by: Andy Shevchenko +Acked-by: Bartosz Golaszewski +Link: https://lore.kernel.org/r/20240701113010.16447-3-kabel@kernel.org +Signed-off-by: Arnd Bergmann +--- + .../sysfs-bus-i2c-devices-turris-omnia-mcu | 81 ++++ + MAINTAINERS | 3 + + drivers/platform/Kconfig | 2 + + drivers/platform/Makefile | 1 + + drivers/platform/cznic/Kconfig | 25 ++ + drivers/platform/cznic/Makefile | 4 + + .../platform/cznic/turris-omnia-mcu-base.c | 393 ++++++++++++++++++ + drivers/platform/cznic/turris-omnia-mcu.h | 74 ++++ + include/linux/turris-omnia-mcu-interface.h | 249 +++++++++++ + 9 files changed, 832 insertions(+) + create mode 100644 Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu + create mode 100644 drivers/platform/cznic/Kconfig + create mode 100644 drivers/platform/cznic/Makefile + create mode 100644 drivers/platform/cznic/turris-omnia-mcu-base.c + create mode 100644 drivers/platform/cznic/turris-omnia-mcu.h + create mode 100644 include/linux/turris-omnia-mcu-interface.h + +--- /dev/null ++++ b/Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu +@@ -0,0 +1,81 @@ ++What: /sys/bus/i2c/devices//board_revision ++Date: September 2024 ++KernelVersion: 6.11 ++Contact: Marek Behún ++Description: (RO) Contains board revision number. ++ ++ Only available if board information is burned in the MCU (older ++ revisions have board information burned in the ATSHA204-A chip). ++ ++ Format: %u. ++ ++What: /sys/bus/i2c/devices//first_mac_address ++Date: September 2024 ++KernelVersion: 6.11 ++Contact: Marek Behún ++Description: (RO) Contains device first MAC address. Each Turris Omnia is ++ allocated 3 MAC addresses. The two additional addresses are ++ computed from the first one by incrementing it. ++ ++ Only available if board information is burned in the MCU (older ++ revisions have board information burned in the ATSHA204-A chip). ++ ++ Format: %pM. ++ ++What: /sys/bus/i2c/devices//fw_features ++Date: September 2024 ++KernelVersion: 6.11 ++Contact: Marek Behún ++Description: (RO) Newer versions of the microcontroller firmware report the ++ features they support. These can be read from this file. If the ++ MCU firmware is too old, this file reads 0x0. ++ ++ Format: 0x%x. ++ ++What: /sys/bus/i2c/devices//fw_version_hash_application ++Date: September 2024 ++KernelVersion: 6.11 ++Contact: Marek Behún ++Description: (RO) Contains the version hash (commit hash) of the application ++ part of the microcontroller firmware. ++ ++ Format: %s. ++ ++What: /sys/bus/i2c/devices//fw_version_hash_bootloader ++Date: September 2024 ++KernelVersion: 6.11 ++Contact: Marek Behún ++Description: (RO) Contains the version hash (commit hash) of the bootloader ++ part of the microcontroller firmware. ++ ++ Format: %s. ++ ++What: /sys/bus/i2c/devices//mcu_type ++Date: September 2024 ++KernelVersion: 6.11 ++Contact: Marek Behún ++Description: (RO) Contains the microcontroller type (STM32, GD32, MKL). ++ ++ Format: %s. ++ ++What: /sys/bus/i2c/devices//reset_selector ++Date: September 2024 ++KernelVersion: 6.11 ++Contact: Marek Behún ++Description: (RO) Contains the selected factory reset level, determined by ++ how long the rear reset button was held by the user during board ++ reset. ++ ++ Format: %i. ++ ++What: /sys/bus/i2c/devices//serial_number ++Date: September 2024 ++KernelVersion: 6.11 ++Contact: Marek Behún ++Description: (RO) Contains the 64-bit board serial number in hexadecimal ++ format. ++ ++ Only available if board information is burned in the MCU (older ++ revisions have board information burned in the ATSHA204-A chip). ++ ++ Format: %016X. +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -2100,6 +2100,7 @@ M: Marek Behún + S: Maintained + W: https://www.turris.cz/ + F: Documentation/ABI/testing/debugfs-moxtet ++F: Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu + F: Documentation/ABI/testing/sysfs-bus-moxtet-devices + F: Documentation/ABI/testing/sysfs-firmware-turris-mox-rwtm + F: Documentation/devicetree/bindings/bus/moxtet.txt +@@ -2113,10 +2114,12 @@ F: drivers/firmware/turris-mox-rwtm.c + F: drivers/gpio/gpio-moxtet.c + F: drivers/leds/leds-turris-omnia.c + F: drivers/mailbox/armada-37xx-rwtm-mailbox.c ++F: drivers/platform/cznic/ + F: drivers/watchdog/armada_37xx_wdt.c + F: include/dt-bindings/bus/moxtet.h + F: include/linux/armada-37xx-rwtm-mailbox.h + F: include/linux/moxtet.h ++F: include/linux/turris-omnia-mcu-interface.h + + ARM/FARADAY FA526 PORT + M: Hans Ulli Kroll +--- a/drivers/platform/Kconfig ++++ b/drivers/platform/Kconfig +@@ -7,6 +7,8 @@ source "drivers/platform/goldfish/Kconfi + + source "drivers/platform/chrome/Kconfig" + ++source "drivers/platform/cznic/Kconfig" ++ + source "drivers/platform/mellanox/Kconfig" + + source "drivers/platform/olpc/Kconfig" +--- a/drivers/platform/Makefile ++++ b/drivers/platform/Makefile +@@ -10,5 +10,6 @@ obj-$(CONFIG_MIPS) += mips/ + obj-$(CONFIG_OLPC_EC) += olpc/ + obj-$(CONFIG_GOLDFISH) += goldfish/ + obj-$(CONFIG_CHROME_PLATFORMS) += chrome/ ++obj-$(CONFIG_CZNIC_PLATFORMS) += cznic/ + obj-$(CONFIG_SURFACE_PLATFORMS) += surface/ + obj-$(CONFIG_MIKROTIK) += mikrotik/ +--- /dev/null ++++ b/drivers/platform/cznic/Kconfig +@@ -0,0 +1,25 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++# ++# For a description of the syntax of this configuration file, ++# see Documentation/kbuild/kconfig-language.rst. ++# ++ ++menuconfig CZNIC_PLATFORMS ++ bool "Platform support for CZ.NIC's Turris hardware" ++ help ++ Say Y here to be able to choose driver support for CZ.NIC's Turris ++ devices. This option alone does not add any kernel code. ++ ++if CZNIC_PLATFORMS ++ ++config TURRIS_OMNIA_MCU ++ tristate "Turris Omnia MCU driver" ++ depends on MACH_ARMADA_38X || COMPILE_TEST ++ depends on I2C ++ help ++ Say Y here to add support for the features implemented by the ++ microcontroller on the CZ.NIC's Turris Omnia SOHO router. ++ To compile this driver as a module, choose M here; the module will be ++ called turris-omnia-mcu. ++ ++endif # CZNIC_PLATFORMS +--- /dev/null ++++ b/drivers/platform/cznic/Makefile +@@ -0,0 +1,4 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++ ++obj-$(CONFIG_TURRIS_OMNIA_MCU) += turris-omnia-mcu.o ++turris-omnia-mcu-y := turris-omnia-mcu-base.o +--- /dev/null ++++ b/drivers/platform/cznic/turris-omnia-mcu-base.c +@@ -0,0 +1,393 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * CZ.NIC's Turris Omnia MCU driver ++ * ++ * 2024 by Marek Behún ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include "turris-omnia-mcu.h" ++ ++#define OMNIA_FW_VERSION_LEN 20 ++#define OMNIA_FW_VERSION_HEX_LEN (2 * OMNIA_FW_VERSION_LEN + 1) ++#define OMNIA_BOARD_INFO_LEN 16 ++ ++int omnia_cmd_write_read(const struct i2c_client *client, ++ void *cmd, unsigned int cmd_len, ++ void *reply, unsigned int reply_len) ++{ ++ struct i2c_msg msgs[2]; ++ int ret, num; ++ ++ msgs[0].addr = client->addr; ++ msgs[0].flags = 0; ++ msgs[0].len = cmd_len; ++ msgs[0].buf = cmd; ++ num = 1; ++ ++ if (reply_len) { ++ msgs[1].addr = client->addr; ++ msgs[1].flags = I2C_M_RD; ++ msgs[1].len = reply_len; ++ msgs[1].buf = reply; ++ num++; ++ } ++ ++ ret = i2c_transfer(client->adapter, msgs, num); ++ if (ret < 0) ++ return ret; ++ if (ret != num) ++ return -EIO; ++ ++ return 0; ++} ++ ++static int omnia_get_version_hash(struct omnia_mcu *mcu, bool bootloader, ++ char version[static OMNIA_FW_VERSION_HEX_LEN]) ++{ ++ u8 reply[OMNIA_FW_VERSION_LEN]; ++ char *p; ++ int err; ++ ++ err = omnia_cmd_read(mcu->client, ++ bootloader ? OMNIA_CMD_GET_FW_VERSION_BOOT ++ : OMNIA_CMD_GET_FW_VERSION_APP, ++ reply, sizeof(reply)); ++ if (err) ++ return err; ++ ++ p = bin2hex(version, reply, OMNIA_FW_VERSION_LEN); ++ *p = '\0'; ++ ++ return 0; ++} ++ ++static ssize_t fw_version_hash_show(struct device *dev, char *buf, ++ bool bootloader) ++{ ++ struct omnia_mcu *mcu = dev_get_drvdata(dev); ++ char version[OMNIA_FW_VERSION_HEX_LEN]; ++ int err; ++ ++ err = omnia_get_version_hash(mcu, bootloader, version); ++ if (err) ++ return err; ++ ++ return sysfs_emit(buf, "%s\n", version); ++} ++ ++static ssize_t fw_version_hash_application_show(struct device *dev, ++ struct device_attribute *a, ++ char *buf) ++{ ++ return fw_version_hash_show(dev, buf, false); ++} ++static DEVICE_ATTR_RO(fw_version_hash_application); ++ ++static ssize_t fw_version_hash_bootloader_show(struct device *dev, ++ struct device_attribute *a, ++ char *buf) ++{ ++ return fw_version_hash_show(dev, buf, true); ++} ++static DEVICE_ATTR_RO(fw_version_hash_bootloader); ++ ++static ssize_t fw_features_show(struct device *dev, struct device_attribute *a, ++ char *buf) ++{ ++ struct omnia_mcu *mcu = dev_get_drvdata(dev); ++ ++ return sysfs_emit(buf, "0x%x\n", mcu->features); ++} ++static DEVICE_ATTR_RO(fw_features); ++ ++static ssize_t mcu_type_show(struct device *dev, struct device_attribute *a, ++ char *buf) ++{ ++ struct omnia_mcu *mcu = dev_get_drvdata(dev); ++ ++ return sysfs_emit(buf, "%s\n", mcu->type); ++} ++static DEVICE_ATTR_RO(mcu_type); ++ ++static ssize_t reset_selector_show(struct device *dev, ++ struct device_attribute *a, char *buf) ++{ ++ u8 reply; ++ int err; ++ ++ err = omnia_cmd_read_u8(to_i2c_client(dev), OMNIA_CMD_GET_RESET, ++ &reply); ++ if (err) ++ return err; ++ ++ return sysfs_emit(buf, "%d\n", reply); ++} ++static DEVICE_ATTR_RO(reset_selector); ++ ++static ssize_t serial_number_show(struct device *dev, ++ struct device_attribute *a, char *buf) ++{ ++ struct omnia_mcu *mcu = dev_get_drvdata(dev); ++ ++ return sysfs_emit(buf, "%016llX\n", mcu->board_serial_number); ++} ++static DEVICE_ATTR_RO(serial_number); ++ ++static ssize_t first_mac_address_show(struct device *dev, ++ struct device_attribute *a, char *buf) ++{ ++ struct omnia_mcu *mcu = dev_get_drvdata(dev); ++ ++ return sysfs_emit(buf, "%pM\n", mcu->board_first_mac); ++} ++static DEVICE_ATTR_RO(first_mac_address); ++ ++static ssize_t board_revision_show(struct device *dev, ++ struct device_attribute *a, char *buf) ++{ ++ struct omnia_mcu *mcu = dev_get_drvdata(dev); ++ ++ return sysfs_emit(buf, "%u\n", mcu->board_revision); ++} ++static DEVICE_ATTR_RO(board_revision); ++ ++static struct attribute *omnia_mcu_base_attrs[] = { ++ &dev_attr_fw_version_hash_application.attr, ++ &dev_attr_fw_version_hash_bootloader.attr, ++ &dev_attr_fw_features.attr, ++ &dev_attr_mcu_type.attr, ++ &dev_attr_reset_selector.attr, ++ &dev_attr_serial_number.attr, ++ &dev_attr_first_mac_address.attr, ++ &dev_attr_board_revision.attr, ++ NULL ++}; ++ ++static umode_t omnia_mcu_base_attrs_visible(struct kobject *kobj, ++ struct attribute *a, int n) ++{ ++ struct device *dev = kobj_to_dev(kobj); ++ struct omnia_mcu *mcu = dev_get_drvdata(dev); ++ ++ if ((a == &dev_attr_serial_number.attr || ++ a == &dev_attr_first_mac_address.attr || ++ a == &dev_attr_board_revision.attr) && ++ !(mcu->features & OMNIA_FEAT_BOARD_INFO)) ++ return 0; ++ ++ return a->mode; ++} ++ ++static const struct attribute_group omnia_mcu_base_group = { ++ .attrs = omnia_mcu_base_attrs, ++ .is_visible = omnia_mcu_base_attrs_visible, ++}; ++ ++static const struct attribute_group *omnia_mcu_groups[] = { ++ &omnia_mcu_base_group, ++ NULL ++}; ++ ++static void omnia_mcu_print_version_hash(struct omnia_mcu *mcu, bool bootloader) ++{ ++ const char *type = bootloader ? "bootloader" : "application"; ++ struct device *dev = &mcu->client->dev; ++ char version[OMNIA_FW_VERSION_HEX_LEN]; ++ int err; ++ ++ err = omnia_get_version_hash(mcu, bootloader, version); ++ if (err) { ++ dev_err(dev, "Cannot read MCU %s firmware version: %d\n", ++ type, err); ++ return; ++ } ++ ++ dev_info(dev, "MCU %s firmware version hash: %s\n", type, version); ++} ++ ++static const char *omnia_status_to_mcu_type(u16 status) ++{ ++ switch (status & OMNIA_STS_MCU_TYPE_MASK) { ++ case OMNIA_STS_MCU_TYPE_STM32: ++ return "STM32"; ++ case OMNIA_STS_MCU_TYPE_GD32: ++ return "GD32"; ++ case OMNIA_STS_MCU_TYPE_MKL: ++ return "MKL"; ++ default: ++ return "unknown"; ++ } ++} ++ ++static void omnia_info_missing_feature(struct device *dev, const char *feature) ++{ ++ dev_info(dev, ++ "Your board's MCU firmware does not support the %s feature.\n", ++ feature); ++} ++ ++static int omnia_mcu_read_features(struct omnia_mcu *mcu) ++{ ++ static const struct { ++ u16 mask; ++ const char *name; ++ } features[] = { ++#define _DEF_FEAT(_n, _m) { OMNIA_FEAT_ ## _n, _m } ++ _DEF_FEAT(EXT_CMDS, "extended control and status"), ++ _DEF_FEAT(WDT_PING, "watchdog pinging"), ++ _DEF_FEAT(LED_STATE_EXT_MASK, "peripheral LED pins reading"), ++ _DEF_FEAT(NEW_INT_API, "new interrupt API"), ++ _DEF_FEAT(POWEROFF_WAKEUP, "poweroff and wakeup"), ++ _DEF_FEAT(TRNG, "true random number generator"), ++#undef _DEF_FEAT ++ }; ++ struct i2c_client *client = mcu->client; ++ struct device *dev = &client->dev; ++ bool suggest_fw_upgrade = false; ++ u16 status; ++ int err; ++ ++ /* status word holds MCU type, which we need below */ ++ err = omnia_cmd_read_u16(client, OMNIA_CMD_GET_STATUS_WORD, &status); ++ if (err) ++ return err; ++ ++ /* ++ * Check whether MCU firmware supports the OMNIA_CMD_GET_FEATURES ++ * command. ++ */ ++ if (status & OMNIA_STS_FEATURES_SUPPORTED) { ++ /* try read 32-bit features */ ++ err = omnia_cmd_read_u32(client, OMNIA_CMD_GET_FEATURES, ++ &mcu->features); ++ if (err) { ++ /* try read 16-bit features */ ++ u16 features16; ++ ++ err = omnia_cmd_read_u16(client, OMNIA_CMD_GET_FEATURES, ++ &features16); ++ if (err) ++ return err; ++ ++ mcu->features = features16; ++ } else { ++ if (mcu->features & OMNIA_FEAT_FROM_BIT_16_INVALID) ++ mcu->features &= GENMASK(15, 0); ++ } ++ } else { ++ dev_info(dev, ++ "Your board's MCU firmware does not support feature reading.\n"); ++ suggest_fw_upgrade = true; ++ } ++ ++ mcu->type = omnia_status_to_mcu_type(status); ++ dev_info(dev, "MCU type %s%s\n", mcu->type, ++ (mcu->features & OMNIA_FEAT_PERIPH_MCU) ? ++ ", with peripheral resets wired" : ""); ++ ++ omnia_mcu_print_version_hash(mcu, true); ++ ++ if (mcu->features & OMNIA_FEAT_BOOTLOADER) ++ dev_warn(dev, ++ "MCU is running bootloader firmware. Was firmware upgrade interrupted?\n"); ++ else ++ omnia_mcu_print_version_hash(mcu, false); ++ ++ for (unsigned int i = 0; i < ARRAY_SIZE(features); i++) { ++ if (mcu->features & features[i].mask) ++ continue; ++ ++ omnia_info_missing_feature(dev, features[i].name); ++ suggest_fw_upgrade = true; ++ } ++ ++ if (suggest_fw_upgrade) ++ dev_info(dev, ++ "Consider upgrading MCU firmware with the omnia-mcutool utility.\n"); ++ ++ return 0; ++} ++ ++static int omnia_mcu_read_board_info(struct omnia_mcu *mcu) ++{ ++ u8 reply[1 + OMNIA_BOARD_INFO_LEN]; ++ int err; ++ ++ err = omnia_cmd_read(mcu->client, OMNIA_CMD_BOARD_INFO_GET, reply, ++ sizeof(reply)); ++ if (err) ++ return err; ++ ++ if (reply[0] != OMNIA_BOARD_INFO_LEN) ++ return -EIO; ++ ++ mcu->board_serial_number = get_unaligned_le64(&reply[1]); ++ ++ /* we can't use ether_addr_copy() because reply is not u16-aligned */ ++ memcpy(mcu->board_first_mac, &reply[9], sizeof(mcu->board_first_mac)); ++ ++ mcu->board_revision = reply[15]; ++ ++ return 0; ++} ++ ++static int omnia_mcu_probe(struct i2c_client *client) ++{ ++ struct device *dev = &client->dev; ++ struct omnia_mcu *mcu; ++ int err; ++ ++ if (!client->irq) ++ return dev_err_probe(dev, -EINVAL, "IRQ resource not found\n"); ++ ++ mcu = devm_kzalloc(dev, sizeof(*mcu), GFP_KERNEL); ++ if (!mcu) ++ return -ENOMEM; ++ ++ mcu->client = client; ++ i2c_set_clientdata(client, mcu); ++ ++ err = omnia_mcu_read_features(mcu); ++ if (err) ++ return dev_err_probe(dev, err, ++ "Cannot determine MCU supported features\n"); ++ ++ if (mcu->features & OMNIA_FEAT_BOARD_INFO) { ++ err = omnia_mcu_read_board_info(mcu); ++ if (err) ++ return dev_err_probe(dev, err, ++ "Cannot read board info\n"); ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id of_omnia_mcu_match[] = { ++ { .compatible = "cznic,turris-omnia-mcu" }, ++ {} ++}; ++ ++static struct i2c_driver omnia_mcu_driver = { ++ .probe = omnia_mcu_probe, ++ .driver = { ++ .name = "turris-omnia-mcu", ++ .of_match_table = of_omnia_mcu_match, ++ .dev_groups = omnia_mcu_groups, ++ }, ++}; ++module_i2c_driver(omnia_mcu_driver); ++ ++MODULE_AUTHOR("Marek Behun "); ++MODULE_DESCRIPTION("CZ.NIC's Turris Omnia MCU"); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/drivers/platform/cznic/turris-omnia-mcu.h +@@ -0,0 +1,74 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * CZ.NIC's Turris Omnia MCU driver ++ * ++ * 2024 by Marek Behún ++ */ ++ ++#ifndef __TURRIS_OMNIA_MCU_H ++#define __TURRIS_OMNIA_MCU_H ++ ++#include ++#include ++#include ++ ++struct i2c_client; ++ ++struct omnia_mcu { ++ struct i2c_client *client; ++ const char *type; ++ u32 features; ++ ++ /* board information */ ++ u64 board_serial_number; ++ u8 board_first_mac[ETH_ALEN]; ++ u8 board_revision; ++}; ++ ++int omnia_cmd_write_read(const struct i2c_client *client, ++ void *cmd, unsigned int cmd_len, ++ void *reply, unsigned int reply_len); ++ ++static inline int omnia_cmd_read(const struct i2c_client *client, u8 cmd, ++ void *reply, unsigned int len) ++{ ++ return omnia_cmd_write_read(client, &cmd, 1, reply, len); ++} ++ ++static inline int omnia_cmd_read_u32(const struct i2c_client *client, u8 cmd, ++ u32 *dst) ++{ ++ __le32 reply; ++ int err; ++ ++ err = omnia_cmd_read(client, cmd, &reply, sizeof(reply)); ++ if (err) ++ return err; ++ ++ *dst = le32_to_cpu(reply); ++ ++ return 0; ++} ++ ++static inline int omnia_cmd_read_u16(const struct i2c_client *client, u8 cmd, ++ u16 *dst) ++{ ++ __le16 reply; ++ int err; ++ ++ err = omnia_cmd_read(client, cmd, &reply, sizeof(reply)); ++ if (err) ++ return err; ++ ++ *dst = le16_to_cpu(reply); ++ ++ return 0; ++} ++ ++static inline int omnia_cmd_read_u8(const struct i2c_client *client, u8 cmd, ++ u8 *reply) ++{ ++ return omnia_cmd_read(client, cmd, reply, sizeof(*reply)); ++} ++ ++#endif /* __TURRIS_OMNIA_MCU_H */ +--- /dev/null ++++ b/include/linux/turris-omnia-mcu-interface.h +@@ -0,0 +1,249 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * CZ.NIC's Turris Omnia MCU I2C interface commands definitions ++ * ++ * 2024 by Marek Behún ++ */ ++ ++#ifndef __TURRIS_OMNIA_MCU_INTERFACE_H ++#define __TURRIS_OMNIA_MCU_INTERFACE_H ++ ++#include ++#include ++ ++enum omnia_commands_e { ++ OMNIA_CMD_GET_STATUS_WORD = 0x01, /* slave sends status word back */ ++ OMNIA_CMD_GENERAL_CONTROL = 0x02, ++ OMNIA_CMD_LED_MODE = 0x03, /* default/user */ ++ OMNIA_CMD_LED_STATE = 0x04, /* LED on/off */ ++ OMNIA_CMD_LED_COLOR = 0x05, /* LED number + RED + GREEN + BLUE */ ++ OMNIA_CMD_USER_VOLTAGE = 0x06, ++ OMNIA_CMD_SET_BRIGHTNESS = 0x07, ++ OMNIA_CMD_GET_BRIGHTNESS = 0x08, ++ OMNIA_CMD_GET_RESET = 0x09, ++ OMNIA_CMD_GET_FW_VERSION_APP = 0x0A, /* 20B git hash number */ ++ OMNIA_CMD_SET_WATCHDOG_STATE = 0x0B, /* 0 - disable ++ * 1 - enable / ping ++ * after boot watchdog is started ++ * with 2 minutes timeout ++ */ ++ ++ /* OMNIA_CMD_WATCHDOG_STATUS = 0x0C, not implemented anymore */ ++ ++ OMNIA_CMD_GET_WATCHDOG_STATE = 0x0D, ++ OMNIA_CMD_GET_FW_VERSION_BOOT = 0x0E, /* 20B Git hash number */ ++ OMNIA_CMD_GET_FW_CHECKSUM = 0x0F, /* 4B length, 4B checksum */ ++ ++ /* available if FEATURES_SUPPORTED bit set in status word */ ++ OMNIA_CMD_GET_FEATURES = 0x10, ++ ++ /* available if EXT_CMD bit set in features */ ++ OMNIA_CMD_GET_EXT_STATUS_DWORD = 0x11, ++ OMNIA_CMD_EXT_CONTROL = 0x12, ++ OMNIA_CMD_GET_EXT_CONTROL_STATUS = 0x13, ++ ++ /* available if NEW_INT_API bit set in features */ ++ OMNIA_CMD_GET_INT_AND_CLEAR = 0x14, ++ OMNIA_CMD_GET_INT_MASK = 0x15, ++ OMNIA_CMD_SET_INT_MASK = 0x16, ++ ++ /* available if FLASHING bit set in features */ ++ OMNIA_CMD_FLASH = 0x19, ++ ++ /* available if WDT_PING bit set in features */ ++ OMNIA_CMD_SET_WDT_TIMEOUT = 0x20, ++ OMNIA_CMD_GET_WDT_TIMELEFT = 0x21, ++ ++ /* available if POWEROFF_WAKEUP bit set in features */ ++ OMNIA_CMD_SET_WAKEUP = 0x22, ++ OMNIA_CMD_GET_UPTIME_AND_WAKEUP = 0x23, ++ OMNIA_CMD_POWER_OFF = 0x24, ++ ++ /* available if USB_OVC_PROT_SETTING bit set in features */ ++ OMNIA_CMD_SET_USB_OVC_PROT = 0x25, ++ OMNIA_CMD_GET_USB_OVC_PROT = 0x26, ++ ++ /* available if TRNG bit set in features */ ++ OMNIA_CMD_TRNG_COLLECT_ENTROPY = 0x28, ++ ++ /* available if CRYPTO bit set in features */ ++ OMNIA_CMD_CRYPTO_GET_PUBLIC_KEY = 0x29, ++ OMNIA_CMD_CRYPTO_SIGN_MESSAGE = 0x2A, ++ OMNIA_CMD_CRYPTO_COLLECT_SIGNATURE = 0x2B, ++ ++ /* available if BOARD_INFO it set in features */ ++ OMNIA_CMD_BOARD_INFO_GET = 0x2C, ++ OMNIA_CMD_BOARD_INFO_BURN = 0x2D, ++ ++ /* available only at address 0x2b (LED-controller) */ ++ /* available only if LED_GAMMA_CORRECTION bit set in features */ ++ OMNIA_CMD_SET_GAMMA_CORRECTION = 0x30, ++ OMNIA_CMD_GET_GAMMA_CORRECTION = 0x31, ++ ++ /* available only at address 0x2b (LED-controller) */ ++ /* available only if PER_LED_CORRECTION bit set in features */ ++ /* available only if FROM_BIT_16_INVALID bit NOT set in features */ ++ OMNIA_CMD_SET_LED_CORRECTIONS = 0x32, ++ OMNIA_CMD_GET_LED_CORRECTIONS = 0x33, ++}; ++ ++enum omnia_flashing_commands_e { ++ OMNIA_FLASH_CMD_UNLOCK = 0x01, ++ OMNIA_FLASH_CMD_SIZE_AND_CSUM = 0x02, ++ OMNIA_FLASH_CMD_PROGRAM = 0x03, ++ OMNIA_FLASH_CMD_RESET = 0x04, ++}; ++ ++enum omnia_sts_word_e { ++ OMNIA_STS_MCU_TYPE_MASK = GENMASK(1, 0), ++ OMNIA_STS_MCU_TYPE_STM32 = FIELD_PREP_CONST(OMNIA_STS_MCU_TYPE_MASK, 0), ++ OMNIA_STS_MCU_TYPE_GD32 = FIELD_PREP_CONST(OMNIA_STS_MCU_TYPE_MASK, 1), ++ OMNIA_STS_MCU_TYPE_MKL = FIELD_PREP_CONST(OMNIA_STS_MCU_TYPE_MASK, 2), ++ OMNIA_STS_FEATURES_SUPPORTED = BIT(2), ++ OMNIA_STS_USER_REGULATOR_NOT_SUPPORTED = BIT(3), ++ OMNIA_STS_CARD_DET = BIT(4), ++ OMNIA_STS_MSATA_IND = BIT(5), ++ OMNIA_STS_USB30_OVC = BIT(6), ++ OMNIA_STS_USB31_OVC = BIT(7), ++ OMNIA_STS_USB30_PWRON = BIT(8), ++ OMNIA_STS_USB31_PWRON = BIT(9), ++ OMNIA_STS_ENABLE_4V5 = BIT(10), ++ OMNIA_STS_BUTTON_MODE = BIT(11), ++ OMNIA_STS_BUTTON_PRESSED = BIT(12), ++ OMNIA_STS_BUTTON_COUNTER_MASK = GENMASK(15, 13), ++}; ++ ++enum omnia_ctl_byte_e { ++ OMNIA_CTL_LIGHT_RST = BIT(0), ++ OMNIA_CTL_HARD_RST = BIT(1), ++ /* BIT(2) is currently reserved */ ++ OMNIA_CTL_USB30_PWRON = BIT(3), ++ OMNIA_CTL_USB31_PWRON = BIT(4), ++ OMNIA_CTL_ENABLE_4V5 = BIT(5), ++ OMNIA_CTL_BUTTON_MODE = BIT(6), ++ OMNIA_CTL_BOOTLOADER = BIT(7), ++}; ++ ++enum omnia_features_e { ++ OMNIA_FEAT_PERIPH_MCU = BIT(0), ++ OMNIA_FEAT_EXT_CMDS = BIT(1), ++ OMNIA_FEAT_WDT_PING = BIT(2), ++ OMNIA_FEAT_LED_STATE_EXT_MASK = GENMASK(4, 3), ++ OMNIA_FEAT_LED_STATE_EXT = FIELD_PREP_CONST(OMNIA_FEAT_LED_STATE_EXT_MASK, 1), ++ OMNIA_FEAT_LED_STATE_EXT_V32 = FIELD_PREP_CONST(OMNIA_FEAT_LED_STATE_EXT_MASK, 2), ++ OMNIA_FEAT_LED_GAMMA_CORRECTION = BIT(5), ++ OMNIA_FEAT_NEW_INT_API = BIT(6), ++ OMNIA_FEAT_BOOTLOADER = BIT(7), ++ OMNIA_FEAT_FLASHING = BIT(8), ++ OMNIA_FEAT_NEW_MESSAGE_API = BIT(9), ++ OMNIA_FEAT_BRIGHTNESS_INT = BIT(10), ++ OMNIA_FEAT_POWEROFF_WAKEUP = BIT(11), ++ OMNIA_FEAT_CAN_OLD_MESSAGE_API = BIT(12), ++ OMNIA_FEAT_TRNG = BIT(13), ++ OMNIA_FEAT_CRYPTO = BIT(14), ++ OMNIA_FEAT_BOARD_INFO = BIT(15), ++ ++ /* ++ * Orginally the features command replied only 16 bits. If more were ++ * read, either the I2C transaction failed or 0xff bytes were sent. ++ * Therefore to consider bits 16 - 31 valid, one bit (20) was reserved ++ * to be zero. ++ */ ++ ++ /* Bits 16 - 19 correspond to bits 0 - 3 of status word */ ++ OMNIA_FEAT_MCU_TYPE_MASK = GENMASK(17, 16), ++ OMNIA_FEAT_MCU_TYPE_STM32 = FIELD_PREP_CONST(OMNIA_FEAT_MCU_TYPE_MASK, 0), ++ OMNIA_FEAT_MCU_TYPE_GD32 = FIELD_PREP_CONST(OMNIA_FEAT_MCU_TYPE_MASK, 1), ++ OMNIA_FEAT_MCU_TYPE_MKL = FIELD_PREP_CONST(OMNIA_FEAT_MCU_TYPE_MASK, 2), ++ OMNIA_FEAT_FEATURES_SUPPORTED = BIT(18), ++ OMNIA_FEAT_USER_REGULATOR_NOT_SUPPORTED = BIT(19), ++ ++ /* must not be set */ ++ OMNIA_FEAT_FROM_BIT_16_INVALID = BIT(20), ++ ++ OMNIA_FEAT_PER_LED_CORRECTION = BIT(21), ++ OMNIA_FEAT_USB_OVC_PROT_SETTING = BIT(22), ++}; ++ ++enum omnia_ext_sts_dword_e { ++ OMNIA_EXT_STS_SFP_nDET = BIT(0), ++ OMNIA_EXT_STS_LED_STATES_MASK = GENMASK(31, 12), ++ OMNIA_EXT_STS_WLAN0_MSATA_LED = BIT(12), ++ OMNIA_EXT_STS_WLAN1_LED = BIT(13), ++ OMNIA_EXT_STS_WLAN2_LED = BIT(14), ++ OMNIA_EXT_STS_WPAN0_LED = BIT(15), ++ OMNIA_EXT_STS_WPAN1_LED = BIT(16), ++ OMNIA_EXT_STS_WPAN2_LED = BIT(17), ++ OMNIA_EXT_STS_WAN_LED0 = BIT(18), ++ OMNIA_EXT_STS_WAN_LED1 = BIT(19), ++ OMNIA_EXT_STS_LAN0_LED0 = BIT(20), ++ OMNIA_EXT_STS_LAN0_LED1 = BIT(21), ++ OMNIA_EXT_STS_LAN1_LED0 = BIT(22), ++ OMNIA_EXT_STS_LAN1_LED1 = BIT(23), ++ OMNIA_EXT_STS_LAN2_LED0 = BIT(24), ++ OMNIA_EXT_STS_LAN2_LED1 = BIT(25), ++ OMNIA_EXT_STS_LAN3_LED0 = BIT(26), ++ OMNIA_EXT_STS_LAN3_LED1 = BIT(27), ++ OMNIA_EXT_STS_LAN4_LED0 = BIT(28), ++ OMNIA_EXT_STS_LAN4_LED1 = BIT(29), ++ OMNIA_EXT_STS_LAN5_LED0 = BIT(30), ++ OMNIA_EXT_STS_LAN5_LED1 = BIT(31), ++}; ++ ++enum omnia_ext_ctl_e { ++ OMNIA_EXT_CTL_nRES_MMC = BIT(0), ++ OMNIA_EXT_CTL_nRES_LAN = BIT(1), ++ OMNIA_EXT_CTL_nRES_PHY = BIT(2), ++ OMNIA_EXT_CTL_nPERST0 = BIT(3), ++ OMNIA_EXT_CTL_nPERST1 = BIT(4), ++ OMNIA_EXT_CTL_nPERST2 = BIT(5), ++ OMNIA_EXT_CTL_PHY_SFP = BIT(6), ++ OMNIA_EXT_CTL_PHY_SFP_AUTO = BIT(7), ++ OMNIA_EXT_CTL_nVHV_CTRL = BIT(8), ++}; ++ ++enum omnia_int_e { ++ OMNIA_INT_CARD_DET = BIT(0), ++ OMNIA_INT_MSATA_IND = BIT(1), ++ OMNIA_INT_USB30_OVC = BIT(2), ++ OMNIA_INT_USB31_OVC = BIT(3), ++ OMNIA_INT_BUTTON_PRESSED = BIT(4), ++ OMNIA_INT_SFP_nDET = BIT(5), ++ OMNIA_INT_BRIGHTNESS_CHANGED = BIT(6), ++ OMNIA_INT_TRNG = BIT(7), ++ OMNIA_INT_MESSAGE_SIGNED = BIT(8), ++ ++ OMNIA_INT_LED_STATES_MASK = GENMASK(31, 12), ++ OMNIA_INT_WLAN0_MSATA_LED = BIT(12), ++ OMNIA_INT_WLAN1_LED = BIT(13), ++ OMNIA_INT_WLAN2_LED = BIT(14), ++ OMNIA_INT_WPAN0_LED = BIT(15), ++ OMNIA_INT_WPAN1_LED = BIT(16), ++ OMNIA_INT_WPAN2_LED = BIT(17), ++ OMNIA_INT_WAN_LED0 = BIT(18), ++ OMNIA_INT_WAN_LED1 = BIT(19), ++ OMNIA_INT_LAN0_LED0 = BIT(20), ++ OMNIA_INT_LAN0_LED1 = BIT(21), ++ OMNIA_INT_LAN1_LED0 = BIT(22), ++ OMNIA_INT_LAN1_LED1 = BIT(23), ++ OMNIA_INT_LAN2_LED0 = BIT(24), ++ OMNIA_INT_LAN2_LED1 = BIT(25), ++ OMNIA_INT_LAN3_LED0 = BIT(26), ++ OMNIA_INT_LAN3_LED1 = BIT(27), ++ OMNIA_INT_LAN4_LED0 = BIT(28), ++ OMNIA_INT_LAN4_LED1 = BIT(29), ++ OMNIA_INT_LAN5_LED0 = BIT(30), ++ OMNIA_INT_LAN5_LED1 = BIT(31), ++}; ++ ++enum omnia_cmd_poweroff_e { ++ OMNIA_CMD_POWER_OFF_POWERON_BUTTON = BIT(0), ++ OMNIA_CMD_POWER_OFF_MAGIC = 0xdead, ++}; ++ ++enum omnia_cmd_usb_ovc_prot_e { ++ OMNIA_CMD_xET_USB_OVC_PROT_PORT_MASK = GENMASK(3, 0), ++ OMNIA_CMD_xET_USB_OVC_PROT_ENABLE = BIT(4), ++}; ++ ++#endif /* __TURRIS_OMNIA_MCU_INTERFACE_H */ diff --git a/target/linux/mvebu/patches-6.6/820-v6.11-03-platform-cznic-turris-omnia-mcu-Add-support-for-MCU-.patch b/target/linux/mvebu/patches-6.6/820-v6.11-03-platform-cznic-turris-omnia-mcu-Add-support-for-MCU-.patch new file mode 100644 index 0000000000..3309a773a9 --- /dev/null +++ b/target/linux/mvebu/patches-6.6/820-v6.11-03-platform-cznic-turris-omnia-mcu-Add-support-for-MCU-.patch @@ -0,0 +1,1311 @@ +From 7f4f2744f9788312e12940b516b51a0a466b137e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 1 Jul 2024 13:30:05 +0200 +Subject: [PATCH 03/11] platform: cznic: turris-omnia-mcu: Add support for MCU + connected GPIOs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add support for GPIOs connected to the MCU on the Turris Omnia board. + +This includes: +- front button pin +- enable pins for USB regulators +- MiniPCIe / mSATA card presence pins in MiniPCIe port 0 +- LED output pins from WAN ethernet PHY, LAN switch and MiniPCIe ports +- on board revisions 32+ also various peripheral resets and another + voltage regulator enable pin + +Signed-off-by: Marek Behún +Acked-by: Bartosz Golaszewski +Link: https://lore.kernel.org/r/20240701113010.16447-4-kabel@kernel.org +Signed-off-by: Arnd Bergmann +--- + .../sysfs-bus-i2c-devices-turris-omnia-mcu | 16 + + drivers/platform/cznic/Kconfig | 15 + + drivers/platform/cznic/Makefile | 1 + + .../platform/cznic/turris-omnia-mcu-base.c | 3 +- + .../platform/cznic/turris-omnia-mcu-gpio.c | 1094 +++++++++++++++++ + drivers/platform/cznic/turris-omnia-mcu.h | 68 + + 6 files changed, 1196 insertions(+), 1 deletion(-) + create mode 100644 drivers/platform/cznic/turris-omnia-mcu-gpio.c + +--- a/Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu ++++ b/Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu +@@ -22,6 +22,22 @@ Description: (RO) Contains device first + + Format: %pM. + ++What: /sys/bus/i2c/devices//front_button_mode ++Date: September 2024 ++KernelVersion: 6.11 ++Contact: Marek Behún ++Description: (RW) The front button on the Turris Omnia router can be ++ configured either to change the intensity of all the LEDs on the ++ front panel, or to send the press event to the CPU as an ++ interrupt. ++ ++ This file switches between these two modes: ++ - "mcu" makes the button press event be handled by the MCU to ++ change the LEDs panel intensity. ++ - "cpu" makes the button press event be handled by the CPU. ++ ++ Format: %s. ++ + What: /sys/bus/i2c/devices//fw_features + Date: September 2024 + KernelVersion: 6.11 +--- a/drivers/platform/cznic/Kconfig ++++ b/drivers/platform/cznic/Kconfig +@@ -16,9 +16,24 @@ config TURRIS_OMNIA_MCU + tristate "Turris Omnia MCU driver" + depends on MACH_ARMADA_38X || COMPILE_TEST + depends on I2C ++ select GPIOLIB ++ select GPIOLIB_IRQCHIP + help + Say Y here to add support for the features implemented by the + microcontroller on the CZ.NIC's Turris Omnia SOHO router. ++ The features include: ++ - GPIO pins ++ - to get front button press events (the front button can be ++ configured either to generate press events to the CPU or to change ++ front LEDs panel brightness) ++ - to enable / disable USB port voltage regulators and to detect ++ USB overcurrent ++ - to detect MiniPCIe / mSATA card presence in MiniPCIe port 0 ++ - to configure resets of various peripherals on board revisions 32+ ++ - to enable / disable the VHV voltage regulator to the SOC in order ++ to be able to program SOC's OTP on board revisions 32+ ++ - to get input from the LED output pins of the WAN ethernet PHY, LAN ++ switch and MiniPCIe ports + To compile this driver as a module, choose M here; the module will be + called turris-omnia-mcu. + +--- a/drivers/platform/cznic/Makefile ++++ b/drivers/platform/cznic/Makefile +@@ -2,3 +2,4 @@ + + obj-$(CONFIG_TURRIS_OMNIA_MCU) += turris-omnia-mcu.o + turris-omnia-mcu-y := turris-omnia-mcu-base.o ++turris-omnia-mcu-y += turris-omnia-mcu-gpio.o +--- a/drivers/platform/cznic/turris-omnia-mcu-base.c ++++ b/drivers/platform/cznic/turris-omnia-mcu-base.c +@@ -196,6 +196,7 @@ static const struct attribute_group omni + + static const struct attribute_group *omnia_mcu_groups[] = { + &omnia_mcu_base_group, ++ &omnia_mcu_gpio_group, + NULL + }; + +@@ -370,7 +371,7 @@ static int omnia_mcu_probe(struct i2c_cl + "Cannot read board info\n"); + } + +- return 0; ++ return omnia_mcu_register_gpiochip(mcu); + } + + static const struct of_device_id of_omnia_mcu_match[] = { +--- /dev/null ++++ b/drivers/platform/cznic/turris-omnia-mcu-gpio.c +@@ -0,0 +1,1094 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * CZ.NIC's Turris Omnia MCU GPIO and IRQ driver ++ * ++ * 2024 by Marek Behún ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include "turris-omnia-mcu.h" ++ ++#define OMNIA_CMD_INT_ARG_LEN 8 ++#define FRONT_BUTTON_RELEASE_DELAY_MS 50 ++ ++static const char * const omnia_mcu_gpio_templates[64] = { ++ /* GPIOs with value read from the 16-bit wide status */ ++ [4] = "MiniPCIe0 Card Detect", ++ [5] = "MiniPCIe0 mSATA Indicator", ++ [6] = "Front USB3 port over-current", ++ [7] = "Rear USB3 port over-current", ++ [8] = "Front USB3 port power", ++ [9] = "Rear USB3 port power", ++ [12] = "Front Button", ++ ++ /* GPIOs with value read from the 32-bit wide extended status */ ++ [16] = "SFP nDET", ++ [28] = "MiniPCIe0 LED", ++ [29] = "MiniPCIe1 LED", ++ [30] = "MiniPCIe2 LED", ++ [31] = "MiniPCIe0 PAN LED", ++ [32] = "MiniPCIe1 PAN LED", ++ [33] = "MiniPCIe2 PAN LED", ++ [34] = "WAN PHY LED0", ++ [35] = "WAN PHY LED1", ++ [36] = "LAN switch p0 LED0", ++ [37] = "LAN switch p0 LED1", ++ [38] = "LAN switch p1 LED0", ++ [39] = "LAN switch p1 LED1", ++ [40] = "LAN switch p2 LED0", ++ [41] = "LAN switch p2 LED1", ++ [42] = "LAN switch p3 LED0", ++ [43] = "LAN switch p3 LED1", ++ [44] = "LAN switch p4 LED0", ++ [45] = "LAN switch p4 LED1", ++ [46] = "LAN switch p5 LED0", ++ [47] = "LAN switch p5 LED1", ++ ++ /* GPIOs with value read from the 16-bit wide extended control status */ ++ [48] = "eMMC nRESET", ++ [49] = "LAN switch nRESET", ++ [50] = "WAN PHY nRESET", ++ [51] = "MiniPCIe0 nPERST", ++ [52] = "MiniPCIe1 nPERST", ++ [53] = "MiniPCIe2 nPERST", ++ [54] = "WAN PHY SFP mux", ++ [56] = "VHV power disable", ++}; ++ ++struct omnia_gpio { ++ u8 cmd; ++ u8 ctl_cmd; ++ u8 bit; ++ u8 ctl_bit; ++ u8 int_bit; ++ u16 feat; ++ u16 feat_mask; ++}; ++ ++#define OMNIA_GPIO_INVALID_INT_BIT 0xff ++ ++#define _DEF_GPIO(_cmd, _ctl_cmd, _bit, _ctl_bit, _int_bit, _feat, _feat_mask) \ ++ { \ ++ .cmd = _cmd, \ ++ .ctl_cmd = _ctl_cmd, \ ++ .bit = _bit, \ ++ .ctl_bit = _ctl_bit, \ ++ .int_bit = (_int_bit) < 0 ? OMNIA_GPIO_INVALID_INT_BIT \ ++ : (_int_bit), \ ++ .feat = _feat, \ ++ .feat_mask = _feat_mask, \ ++ } ++ ++#define _DEF_GPIO_STS(_name) \ ++ _DEF_GPIO(OMNIA_CMD_GET_STATUS_WORD, 0, __bf_shf(OMNIA_STS_ ## _name), \ ++ 0, __bf_shf(OMNIA_INT_ ## _name), 0, 0) ++ ++#define _DEF_GPIO_CTL(_name) \ ++ _DEF_GPIO(OMNIA_CMD_GET_STATUS_WORD, OMNIA_CMD_GENERAL_CONTROL, \ ++ __bf_shf(OMNIA_STS_ ## _name), __bf_shf(OMNIA_CTL_ ## _name), \ ++ -1, 0, 0) ++ ++#define _DEF_GPIO_EXT_STS(_name, _feat) \ ++ _DEF_GPIO(OMNIA_CMD_GET_EXT_STATUS_DWORD, 0, \ ++ __bf_shf(OMNIA_EXT_STS_ ## _name), 0, \ ++ __bf_shf(OMNIA_INT_ ## _name), \ ++ OMNIA_FEAT_ ## _feat | OMNIA_FEAT_EXT_CMDS, \ ++ OMNIA_FEAT_ ## _feat | OMNIA_FEAT_EXT_CMDS) ++ ++#define _DEF_GPIO_EXT_STS_LED(_name, _ledext) \ ++ _DEF_GPIO(OMNIA_CMD_GET_EXT_STATUS_DWORD, 0, \ ++ __bf_shf(OMNIA_EXT_STS_ ## _name), 0, \ ++ __bf_shf(OMNIA_INT_ ## _name), \ ++ OMNIA_FEAT_LED_STATE_ ## _ledext, \ ++ OMNIA_FEAT_LED_STATE_EXT_MASK) ++ ++#define _DEF_GPIO_EXT_STS_LEDALL(_name) \ ++ _DEF_GPIO(OMNIA_CMD_GET_EXT_STATUS_DWORD, 0, \ ++ __bf_shf(OMNIA_EXT_STS_ ## _name), 0, \ ++ __bf_shf(OMNIA_INT_ ## _name), \ ++ OMNIA_FEAT_LED_STATE_EXT_MASK, 0) ++ ++#define _DEF_GPIO_EXT_CTL(_name, _feat) \ ++ _DEF_GPIO(OMNIA_CMD_GET_EXT_CONTROL_STATUS, OMNIA_CMD_EXT_CONTROL, \ ++ __bf_shf(OMNIA_EXT_CTL_ ## _name), \ ++ __bf_shf(OMNIA_EXT_CTL_ ## _name), -1, \ ++ OMNIA_FEAT_ ## _feat | OMNIA_FEAT_EXT_CMDS, \ ++ OMNIA_FEAT_ ## _feat | OMNIA_FEAT_EXT_CMDS) ++ ++#define _DEF_INT(_name) \ ++ _DEF_GPIO(0, 0, 0, 0, __bf_shf(OMNIA_INT_ ## _name), 0, 0) ++ ++static inline bool is_int_bit_valid(const struct omnia_gpio *gpio) ++{ ++ return gpio->int_bit != OMNIA_GPIO_INVALID_INT_BIT; ++} ++ ++static const struct omnia_gpio omnia_gpios[64] = { ++ /* GPIOs with value read from the 16-bit wide status */ ++ [4] = _DEF_GPIO_STS(CARD_DET), ++ [5] = _DEF_GPIO_STS(MSATA_IND), ++ [6] = _DEF_GPIO_STS(USB30_OVC), ++ [7] = _DEF_GPIO_STS(USB31_OVC), ++ [8] = _DEF_GPIO_CTL(USB30_PWRON), ++ [9] = _DEF_GPIO_CTL(USB31_PWRON), ++ ++ /* brightness changed interrupt, no GPIO */ ++ [11] = _DEF_INT(BRIGHTNESS_CHANGED), ++ ++ [12] = _DEF_GPIO_STS(BUTTON_PRESSED), ++ ++ /* TRNG interrupt, no GPIO */ ++ [13] = _DEF_INT(TRNG), ++ ++ /* MESSAGE_SIGNED interrupt, no GPIO */ ++ [14] = _DEF_INT(MESSAGE_SIGNED), ++ ++ /* GPIOs with value read from the 32-bit wide extended status */ ++ [16] = _DEF_GPIO_EXT_STS(SFP_nDET, PERIPH_MCU), ++ [28] = _DEF_GPIO_EXT_STS_LEDALL(WLAN0_MSATA_LED), ++ [29] = _DEF_GPIO_EXT_STS_LEDALL(WLAN1_LED), ++ [30] = _DEF_GPIO_EXT_STS_LEDALL(WLAN2_LED), ++ [31] = _DEF_GPIO_EXT_STS_LED(WPAN0_LED, EXT), ++ [32] = _DEF_GPIO_EXT_STS_LED(WPAN1_LED, EXT), ++ [33] = _DEF_GPIO_EXT_STS_LED(WPAN2_LED, EXT), ++ [34] = _DEF_GPIO_EXT_STS_LEDALL(WAN_LED0), ++ [35] = _DEF_GPIO_EXT_STS_LED(WAN_LED1, EXT_V32), ++ [36] = _DEF_GPIO_EXT_STS_LEDALL(LAN0_LED0), ++ [37] = _DEF_GPIO_EXT_STS_LEDALL(LAN0_LED1), ++ [38] = _DEF_GPIO_EXT_STS_LEDALL(LAN1_LED0), ++ [39] = _DEF_GPIO_EXT_STS_LEDALL(LAN1_LED1), ++ [40] = _DEF_GPIO_EXT_STS_LEDALL(LAN2_LED0), ++ [41] = _DEF_GPIO_EXT_STS_LEDALL(LAN2_LED1), ++ [42] = _DEF_GPIO_EXT_STS_LEDALL(LAN3_LED0), ++ [43] = _DEF_GPIO_EXT_STS_LEDALL(LAN3_LED1), ++ [44] = _DEF_GPIO_EXT_STS_LEDALL(LAN4_LED0), ++ [45] = _DEF_GPIO_EXT_STS_LEDALL(LAN4_LED1), ++ [46] = _DEF_GPIO_EXT_STS_LEDALL(LAN5_LED0), ++ [47] = _DEF_GPIO_EXT_STS_LEDALL(LAN5_LED1), ++ ++ /* GPIOs with value read from the 16-bit wide extended control status */ ++ [48] = _DEF_GPIO_EXT_CTL(nRES_MMC, PERIPH_MCU), ++ [49] = _DEF_GPIO_EXT_CTL(nRES_LAN, PERIPH_MCU), ++ [50] = _DEF_GPIO_EXT_CTL(nRES_PHY, PERIPH_MCU), ++ [51] = _DEF_GPIO_EXT_CTL(nPERST0, PERIPH_MCU), ++ [52] = _DEF_GPIO_EXT_CTL(nPERST1, PERIPH_MCU), ++ [53] = _DEF_GPIO_EXT_CTL(nPERST2, PERIPH_MCU), ++ [54] = _DEF_GPIO_EXT_CTL(PHY_SFP, PERIPH_MCU), ++ [56] = _DEF_GPIO_EXT_CTL(nVHV_CTRL, PERIPH_MCU), ++}; ++ ++/* mapping from interrupts to indexes of GPIOs in the omnia_gpios array */ ++static const u8 omnia_int_to_gpio_idx[32] = { ++ [__bf_shf(OMNIA_INT_CARD_DET)] = 4, ++ [__bf_shf(OMNIA_INT_MSATA_IND)] = 5, ++ [__bf_shf(OMNIA_INT_USB30_OVC)] = 6, ++ [__bf_shf(OMNIA_INT_USB31_OVC)] = 7, ++ [__bf_shf(OMNIA_INT_BUTTON_PRESSED)] = 12, ++ [__bf_shf(OMNIA_INT_TRNG)] = 13, ++ [__bf_shf(OMNIA_INT_MESSAGE_SIGNED)] = 14, ++ [__bf_shf(OMNIA_INT_SFP_nDET)] = 16, ++ [__bf_shf(OMNIA_INT_BRIGHTNESS_CHANGED)] = 11, ++ [__bf_shf(OMNIA_INT_WLAN0_MSATA_LED)] = 28, ++ [__bf_shf(OMNIA_INT_WLAN1_LED)] = 29, ++ [__bf_shf(OMNIA_INT_WLAN2_LED)] = 30, ++ [__bf_shf(OMNIA_INT_WPAN0_LED)] = 31, ++ [__bf_shf(OMNIA_INT_WPAN1_LED)] = 32, ++ [__bf_shf(OMNIA_INT_WPAN2_LED)] = 33, ++ [__bf_shf(OMNIA_INT_WAN_LED0)] = 34, ++ [__bf_shf(OMNIA_INT_WAN_LED1)] = 35, ++ [__bf_shf(OMNIA_INT_LAN0_LED0)] = 36, ++ [__bf_shf(OMNIA_INT_LAN0_LED1)] = 37, ++ [__bf_shf(OMNIA_INT_LAN1_LED0)] = 38, ++ [__bf_shf(OMNIA_INT_LAN1_LED1)] = 39, ++ [__bf_shf(OMNIA_INT_LAN2_LED0)] = 40, ++ [__bf_shf(OMNIA_INT_LAN2_LED1)] = 41, ++ [__bf_shf(OMNIA_INT_LAN3_LED0)] = 42, ++ [__bf_shf(OMNIA_INT_LAN3_LED1)] = 43, ++ [__bf_shf(OMNIA_INT_LAN4_LED0)] = 44, ++ [__bf_shf(OMNIA_INT_LAN4_LED1)] = 45, ++ [__bf_shf(OMNIA_INT_LAN5_LED0)] = 46, ++ [__bf_shf(OMNIA_INT_LAN5_LED1)] = 47, ++}; ++ ++/* index of PHY_SFP GPIO in the omnia_gpios array */ ++#define OMNIA_GPIO_PHY_SFP_OFFSET 54 ++ ++static int omnia_ctl_cmd_locked(struct omnia_mcu *mcu, u8 cmd, u16 val, u16 mask) ++{ ++ unsigned int len; ++ u8 buf[5]; ++ ++ buf[0] = cmd; ++ ++ switch (cmd) { ++ case OMNIA_CMD_GENERAL_CONTROL: ++ buf[1] = val; ++ buf[2] = mask; ++ len = 3; ++ break; ++ ++ case OMNIA_CMD_EXT_CONTROL: ++ put_unaligned_le16(val, &buf[1]); ++ put_unaligned_le16(mask, &buf[3]); ++ len = 5; ++ break; ++ ++ default: ++ BUG(); ++ } ++ ++ return omnia_cmd_write(mcu->client, buf, len); ++} ++ ++static int omnia_ctl_cmd(struct omnia_mcu *mcu, u8 cmd, u16 val, u16 mask) ++{ ++ guard(mutex)(&mcu->lock); ++ ++ return omnia_ctl_cmd_locked(mcu, cmd, val, mask); ++} ++ ++static int omnia_gpio_request(struct gpio_chip *gc, unsigned int offset) ++{ ++ if (!omnia_gpios[offset].cmd) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static int omnia_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) ++{ ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ ++ if (offset == OMNIA_GPIO_PHY_SFP_OFFSET) { ++ int val; ++ ++ scoped_guard(mutex, &mcu->lock) { ++ val = omnia_cmd_read_bit(mcu->client, ++ OMNIA_CMD_GET_EXT_CONTROL_STATUS, ++ OMNIA_EXT_CTL_PHY_SFP_AUTO); ++ if (val < 0) ++ return val; ++ } ++ ++ if (val) ++ return GPIO_LINE_DIRECTION_IN; ++ ++ return GPIO_LINE_DIRECTION_OUT; ++ } ++ ++ if (omnia_gpios[offset].ctl_cmd) ++ return GPIO_LINE_DIRECTION_OUT; ++ ++ return GPIO_LINE_DIRECTION_IN; ++} ++ ++static int omnia_gpio_direction_input(struct gpio_chip *gc, unsigned int offset) ++{ ++ const struct omnia_gpio *gpio = &omnia_gpios[offset]; ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ ++ if (offset == OMNIA_GPIO_PHY_SFP_OFFSET) ++ return omnia_ctl_cmd(mcu, OMNIA_CMD_EXT_CONTROL, ++ OMNIA_EXT_CTL_PHY_SFP_AUTO, ++ OMNIA_EXT_CTL_PHY_SFP_AUTO); ++ ++ if (gpio->ctl_cmd) ++ return -ENOTSUPP; ++ ++ return 0; ++} ++ ++static int omnia_gpio_direction_output(struct gpio_chip *gc, ++ unsigned int offset, int value) ++{ ++ const struct omnia_gpio *gpio = &omnia_gpios[offset]; ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ u16 val, mask; ++ ++ if (!gpio->ctl_cmd) ++ return -ENOTSUPP; ++ ++ mask = BIT(gpio->ctl_bit); ++ val = value ? mask : 0; ++ ++ if (offset == OMNIA_GPIO_PHY_SFP_OFFSET) ++ mask |= OMNIA_EXT_CTL_PHY_SFP_AUTO; ++ ++ return omnia_ctl_cmd(mcu, gpio->ctl_cmd, val, mask); ++} ++ ++static int omnia_gpio_get(struct gpio_chip *gc, unsigned int offset) ++{ ++ const struct omnia_gpio *gpio = &omnia_gpios[offset]; ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ ++ /* ++ * If firmware does not support the new interrupt API, we are informed ++ * of every change of the status word by an interrupt from MCU and save ++ * its value in the interrupt service routine. Simply return the saved ++ * value. ++ */ ++ if (gpio->cmd == OMNIA_CMD_GET_STATUS_WORD && ++ !(mcu->features & OMNIA_FEAT_NEW_INT_API)) ++ return test_bit(gpio->bit, &mcu->last_status); ++ ++ guard(mutex)(&mcu->lock); ++ ++ /* ++ * If firmware does support the new interrupt API, we may have cached ++ * the value of a GPIO in the interrupt service routine. If not, read ++ * the relevant bit now. ++ */ ++ if (is_int_bit_valid(gpio) && test_bit(gpio->int_bit, &mcu->is_cached)) ++ return test_bit(gpio->int_bit, &mcu->cached); ++ ++ return omnia_cmd_read_bit(mcu->client, gpio->cmd, BIT(gpio->bit)); ++} ++ ++static unsigned long * ++_relevant_field_for_sts_cmd(u8 cmd, unsigned long *sts, unsigned long *ext_sts, ++ unsigned long *ext_ctl) ++{ ++ switch (cmd) { ++ case OMNIA_CMD_GET_STATUS_WORD: ++ return sts; ++ case OMNIA_CMD_GET_EXT_STATUS_DWORD: ++ return ext_sts; ++ case OMNIA_CMD_GET_EXT_CONTROL_STATUS: ++ return ext_ctl; ++ default: ++ return NULL; ++ } ++} ++ ++static int omnia_gpio_get_multiple(struct gpio_chip *gc, unsigned long *mask, ++ unsigned long *bits) ++{ ++ unsigned long sts = 0, ext_sts = 0, ext_ctl = 0, *field; ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ struct i2c_client *client = mcu->client; ++ unsigned int i; ++ int err; ++ ++ /* determine which bits to read from the 3 possible commands */ ++ for_each_set_bit(i, mask, ARRAY_SIZE(omnia_gpios)) { ++ field = _relevant_field_for_sts_cmd(omnia_gpios[i].cmd, ++ &sts, &ext_sts, &ext_ctl); ++ if (!field) ++ continue; ++ ++ __set_bit(omnia_gpios[i].bit, field); ++ } ++ ++ guard(mutex)(&mcu->lock); ++ ++ if (mcu->features & OMNIA_FEAT_NEW_INT_API) { ++ /* read relevant bits from status */ ++ err = omnia_cmd_read_bits(client, OMNIA_CMD_GET_STATUS_WORD, ++ sts, &sts); ++ if (err) ++ return err; ++ } else { ++ /* ++ * Use status word value cached in the interrupt service routine ++ * if firmware does not support the new interrupt API. ++ */ ++ sts = mcu->last_status; ++ } ++ ++ /* read relevant bits from extended status */ ++ err = omnia_cmd_read_bits(client, OMNIA_CMD_GET_EXT_STATUS_DWORD, ++ ext_sts, &ext_sts); ++ if (err) ++ return err; ++ ++ /* read relevant bits from extended control */ ++ err = omnia_cmd_read_bits(client, OMNIA_CMD_GET_EXT_CONTROL_STATUS, ++ ext_ctl, &ext_ctl); ++ if (err) ++ return err; ++ ++ /* assign relevant bits in result */ ++ for_each_set_bit(i, mask, ARRAY_SIZE(omnia_gpios)) { ++ field = _relevant_field_for_sts_cmd(omnia_gpios[i].cmd, ++ &sts, &ext_sts, &ext_ctl); ++ if (!field) ++ continue; ++ ++ __assign_bit(i, bits, test_bit(omnia_gpios[i].bit, field)); ++ } ++ ++ return 0; ++} ++ ++static void omnia_gpio_set(struct gpio_chip *gc, unsigned int offset, int value) ++{ ++ const struct omnia_gpio *gpio = &omnia_gpios[offset]; ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ u16 val, mask; ++ ++ if (!gpio->ctl_cmd) ++ return; ++ ++ mask = BIT(gpio->ctl_bit); ++ val = value ? mask : 0; ++ ++ omnia_ctl_cmd(mcu, gpio->ctl_cmd, val, mask); ++} ++ ++static void omnia_gpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, ++ unsigned long *bits) ++{ ++ unsigned long ctl = 0, ctl_mask = 0, ext_ctl = 0, ext_ctl_mask = 0; ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ unsigned int i; ++ ++ for_each_set_bit(i, mask, ARRAY_SIZE(omnia_gpios)) { ++ unsigned long *field, *field_mask; ++ u8 bit = omnia_gpios[i].ctl_bit; ++ ++ switch (omnia_gpios[i].ctl_cmd) { ++ case OMNIA_CMD_GENERAL_CONTROL: ++ field = &ctl; ++ field_mask = &ctl_mask; ++ break; ++ case OMNIA_CMD_EXT_CONTROL: ++ field = &ext_ctl; ++ field_mask = &ext_ctl_mask; ++ break; ++ default: ++ field = field_mask = NULL; ++ break; ++ } ++ ++ if (!field) ++ continue; ++ ++ __set_bit(bit, field_mask); ++ __assign_bit(bit, field, test_bit(i, bits)); ++ } ++ ++ guard(mutex)(&mcu->lock); ++ ++ if (ctl_mask) ++ omnia_ctl_cmd_locked(mcu, OMNIA_CMD_GENERAL_CONTROL, ++ ctl, ctl_mask); ++ ++ if (ext_ctl_mask) ++ omnia_ctl_cmd_locked(mcu, OMNIA_CMD_EXT_CONTROL, ++ ext_ctl, ext_ctl_mask); ++} ++ ++static bool omnia_gpio_available(struct omnia_mcu *mcu, ++ const struct omnia_gpio *gpio) ++{ ++ if (gpio->feat_mask) ++ return (mcu->features & gpio->feat_mask) == gpio->feat; ++ ++ if (gpio->feat) ++ return mcu->features & gpio->feat; ++ ++ return true; ++} ++ ++static int omnia_gpio_init_valid_mask(struct gpio_chip *gc, ++ unsigned long *valid_mask, ++ unsigned int ngpios) ++{ ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ ++ for (unsigned int i = 0; i < ngpios; i++) { ++ const struct omnia_gpio *gpio = &omnia_gpios[i]; ++ ++ if (gpio->cmd || is_int_bit_valid(gpio)) ++ __assign_bit(i, valid_mask, ++ omnia_gpio_available(mcu, gpio)); ++ else ++ __clear_bit(i, valid_mask); ++ } ++ ++ return 0; ++} ++ ++static int omnia_gpio_of_xlate(struct gpio_chip *gc, ++ const struct of_phandle_args *gpiospec, ++ u32 *flags) ++{ ++ u32 bank, gpio; ++ ++ if (WARN_ON(gpiospec->args_count != 3)) ++ return -EINVAL; ++ ++ if (flags) ++ *flags = gpiospec->args[2]; ++ ++ bank = gpiospec->args[0]; ++ gpio = gpiospec->args[1]; ++ ++ switch (bank) { ++ case 0: ++ return gpio < 16 ? gpio : -EINVAL; ++ case 1: ++ return gpio < 32 ? 16 + gpio : -EINVAL; ++ case 2: ++ return gpio < 16 ? 48 + gpio : -EINVAL; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static void omnia_irq_shutdown(struct irq_data *d) ++{ ++ struct gpio_chip *gc = irq_data_get_irq_chip_data(d); ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ irq_hw_number_t hwirq = irqd_to_hwirq(d); ++ u8 bit = omnia_gpios[hwirq].int_bit; ++ ++ __clear_bit(bit, &mcu->rising); ++ __clear_bit(bit, &mcu->falling); ++} ++ ++static void omnia_irq_mask(struct irq_data *d) ++{ ++ struct gpio_chip *gc = irq_data_get_irq_chip_data(d); ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ irq_hw_number_t hwirq = irqd_to_hwirq(d); ++ u8 bit = omnia_gpios[hwirq].int_bit; ++ ++ if (!omnia_gpios[hwirq].cmd) ++ __clear_bit(bit, &mcu->rising); ++ __clear_bit(bit, &mcu->mask); ++ gpiochip_disable_irq(gc, hwirq); ++} ++ ++static void omnia_irq_unmask(struct irq_data *d) ++{ ++ struct gpio_chip *gc = irq_data_get_irq_chip_data(d); ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ irq_hw_number_t hwirq = irqd_to_hwirq(d); ++ u8 bit = omnia_gpios[hwirq].int_bit; ++ ++ gpiochip_enable_irq(gc, hwirq); ++ __set_bit(bit, &mcu->mask); ++ if (!omnia_gpios[hwirq].cmd) ++ __set_bit(bit, &mcu->rising); ++} ++ ++static int omnia_irq_set_type(struct irq_data *d, unsigned int type) ++{ ++ struct gpio_chip *gc = irq_data_get_irq_chip_data(d); ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ irq_hw_number_t hwirq = irqd_to_hwirq(d); ++ struct device *dev = &mcu->client->dev; ++ u8 bit = omnia_gpios[hwirq].int_bit; ++ ++ if (!(type & IRQ_TYPE_EDGE_BOTH)) { ++ dev_err(dev, "irq %u: unsupported type %u\n", d->irq, type); ++ return -EINVAL; ++ } ++ ++ __assign_bit(bit, &mcu->rising, type & IRQ_TYPE_EDGE_RISING); ++ __assign_bit(bit, &mcu->falling, type & IRQ_TYPE_EDGE_FALLING); ++ ++ return 0; ++} ++ ++static void omnia_irq_bus_lock(struct irq_data *d) ++{ ++ struct gpio_chip *gc = irq_data_get_irq_chip_data(d); ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ ++ /* nothing to do if MCU firmware does not support new interrupt API */ ++ if (!(mcu->features & OMNIA_FEAT_NEW_INT_API)) ++ return; ++ ++ mutex_lock(&mcu->lock); ++} ++ ++/** ++ * omnia_mask_interleave - Interleaves the bytes from @rising and @falling ++ * @dst: the destination u8 array of interleaved bytes ++ * @rising: rising mask ++ * @falling: falling mask ++ * ++ * Interleaves the little-endian bytes from @rising and @falling words. ++ * ++ * If @rising = (r0, r1, r2, r3) and @falling = (f0, f1, f2, f3), the result is ++ * @dst = (r0, f0, r1, f1, r2, f2, r3, f3). ++ * ++ * The MCU receives an interrupt mask and reports a pending interrupt bitmap in ++ * this interleaved format. The rationale behind this is that the low-indexed ++ * bits are more important - in many cases, the user will be interested only in ++ * interrupts with indexes 0 to 7, and so the system can stop reading after ++ * first 2 bytes (r0, f0), to save time on the slow I2C bus. ++ * ++ * Feel free to remove this function and its inverse, omnia_mask_deinterleave, ++ * and use an appropriate bitmap_*() function once such a function exists. ++ */ ++static void ++omnia_mask_interleave(u8 *dst, unsigned long rising, unsigned long falling) ++{ ++ for (unsigned int i = 0; i < sizeof(u32); i++) { ++ dst[2 * i] = rising >> (8 * i); ++ dst[2 * i + 1] = falling >> (8 * i); ++ } ++} ++ ++/** ++ * omnia_mask_deinterleave - Deinterleaves the bytes into @rising and @falling ++ * @src: the source u8 array containing the interleaved bytes ++ * @rising: pointer where to store the rising mask gathered from @src ++ * @falling: pointer where to store the falling mask gathered from @src ++ * ++ * This is the inverse function to omnia_mask_interleave. ++ */ ++static void omnia_mask_deinterleave(const u8 *src, unsigned long *rising, ++ unsigned long *falling) ++{ ++ *rising = *falling = 0; ++ ++ for (unsigned int i = 0; i < sizeof(u32); i++) { ++ *rising |= src[2 * i] << (8 * i); ++ *falling |= src[2 * i + 1] << (8 * i); ++ } ++} ++ ++static void omnia_irq_bus_sync_unlock(struct irq_data *d) ++{ ++ struct gpio_chip *gc = irq_data_get_irq_chip_data(d); ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ struct device *dev = &mcu->client->dev; ++ u8 cmd[1 + OMNIA_CMD_INT_ARG_LEN]; ++ unsigned long rising, falling; ++ int err; ++ ++ /* nothing to do if MCU firmware does not support new interrupt API */ ++ if (!(mcu->features & OMNIA_FEAT_NEW_INT_API)) ++ return; ++ ++ cmd[0] = OMNIA_CMD_SET_INT_MASK; ++ ++ rising = mcu->rising & mcu->mask; ++ falling = mcu->falling & mcu->mask; ++ ++ /* interleave the rising and falling bytes into the command arguments */ ++ omnia_mask_interleave(&cmd[1], rising, falling); ++ ++ dev_dbg(dev, "set int mask %8ph\n", &cmd[1]); ++ ++ err = omnia_cmd_write(mcu->client, cmd, sizeof(cmd)); ++ if (err) { ++ dev_err(dev, "Cannot set mask: %d\n", err); ++ goto unlock; ++ } ++ ++ /* ++ * Remember which GPIOs have both rising and falling interrupts enabled. ++ * For those we will cache their value so that .get() method is faster. ++ * We also need to forget cached values of GPIOs that aren't cached ++ * anymore. ++ */ ++ mcu->both = rising & falling; ++ mcu->is_cached &= mcu->both; ++ ++unlock: ++ mutex_unlock(&mcu->lock); ++} ++ ++static const struct irq_chip omnia_mcu_irq_chip = { ++ .name = "Turris Omnia MCU interrupts", ++ .irq_shutdown = omnia_irq_shutdown, ++ .irq_mask = omnia_irq_mask, ++ .irq_unmask = omnia_irq_unmask, ++ .irq_set_type = omnia_irq_set_type, ++ .irq_bus_lock = omnia_irq_bus_lock, ++ .irq_bus_sync_unlock = omnia_irq_bus_sync_unlock, ++ .flags = IRQCHIP_IMMUTABLE, ++ GPIOCHIP_IRQ_RESOURCE_HELPERS, ++}; ++ ++static void omnia_irq_init_valid_mask(struct gpio_chip *gc, ++ unsigned long *valid_mask, ++ unsigned int ngpios) ++{ ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ ++ for (unsigned int i = 0; i < ngpios; i++) { ++ const struct omnia_gpio *gpio = &omnia_gpios[i]; ++ ++ if (is_int_bit_valid(gpio)) ++ __assign_bit(i, valid_mask, ++ omnia_gpio_available(mcu, gpio)); ++ else ++ __clear_bit(i, valid_mask); ++ } ++} ++ ++static int omnia_irq_init_hw(struct gpio_chip *gc) ++{ ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ u8 cmd[1 + OMNIA_CMD_INT_ARG_LEN] = {}; ++ ++ cmd[0] = OMNIA_CMD_SET_INT_MASK; ++ ++ return omnia_cmd_write(mcu->client, cmd, sizeof(cmd)); ++} ++ ++/* ++ * Determine how many bytes we need to read from the reply to the ++ * OMNIA_CMD_GET_INT_AND_CLEAR command in order to retrieve all unmasked ++ * interrupts. ++ */ ++static unsigned int ++omnia_irq_compute_pending_length(unsigned long rising, unsigned long falling) ++{ ++ return max(omnia_compute_reply_length(rising, true, 0), ++ omnia_compute_reply_length(falling, true, 1)); ++} ++ ++static bool omnia_irq_read_pending_new(struct omnia_mcu *mcu, ++ unsigned long *pending) ++{ ++ struct device *dev = &mcu->client->dev; ++ u8 reply[OMNIA_CMD_INT_ARG_LEN] = {}; ++ unsigned long rising, falling; ++ unsigned int len; ++ int err; ++ ++ len = omnia_irq_compute_pending_length(mcu->rising & mcu->mask, ++ mcu->falling & mcu->mask); ++ if (!len) ++ return false; ++ ++ guard(mutex)(&mcu->lock); ++ ++ err = omnia_cmd_read(mcu->client, OMNIA_CMD_GET_INT_AND_CLEAR, reply, ++ len); ++ if (err) { ++ dev_err(dev, "Cannot read pending IRQs: %d\n", err); ++ return false; ++ } ++ ++ /* deinterleave the reply bytes into rising and falling */ ++ omnia_mask_deinterleave(reply, &rising, &falling); ++ ++ rising &= mcu->mask; ++ falling &= mcu->mask; ++ *pending = rising | falling; ++ ++ /* cache values for GPIOs that have both edges enabled */ ++ mcu->is_cached &= ~(rising & falling); ++ mcu->is_cached |= mcu->both & (rising ^ falling); ++ mcu->cached = (mcu->cached | rising) & ~falling; ++ ++ return true; ++} ++ ++static int omnia_read_status_word_old_fw(struct omnia_mcu *mcu, ++ unsigned long *status) ++{ ++ u16 raw_status; ++ int err; ++ ++ err = omnia_cmd_read_u16(mcu->client, OMNIA_CMD_GET_STATUS_WORD, ++ &raw_status); ++ if (err) ++ return err; ++ ++ /* ++ * Old firmware has a bug wherein it never resets the USB port ++ * overcurrent bits back to zero. Ignore them. ++ */ ++ *status = raw_status & ~(OMNIA_STS_USB30_OVC | OMNIA_STS_USB31_OVC); ++ ++ return 0; ++} ++ ++static void button_release_emul_fn(struct work_struct *work) ++{ ++ struct omnia_mcu *mcu = container_of(to_delayed_work(work), ++ struct omnia_mcu, ++ button_release_emul_work); ++ ++ mcu->button_pressed_emul = false; ++ generic_handle_irq_safe(mcu->client->irq); ++} ++ ++static void ++fill_int_from_sts(unsigned long *rising, unsigned long *falling, ++ unsigned long rising_sts, unsigned long falling_sts, ++ unsigned long sts_bit, unsigned long int_bit) ++{ ++ if (rising_sts & sts_bit) ++ *rising |= int_bit; ++ if (falling_sts & sts_bit) ++ *falling |= int_bit; ++} ++ ++static bool omnia_irq_read_pending_old(struct omnia_mcu *mcu, ++ unsigned long *pending) ++{ ++ unsigned long status, rising_sts, falling_sts, rising, falling; ++ struct device *dev = &mcu->client->dev; ++ int err; ++ ++ guard(mutex)(&mcu->lock); ++ ++ err = omnia_read_status_word_old_fw(mcu, &status); ++ if (err) { ++ dev_err(dev, "Cannot read pending IRQs: %d\n", err); ++ return false; ++ } ++ ++ /* ++ * The old firmware triggers an interrupt whenever status word changes, ++ * but does not inform about which bits rose or fell. We need to compute ++ * this here by comparing with the last status word value. ++ * ++ * The OMNIA_STS_BUTTON_PRESSED bit needs special handling, because the ++ * old firmware clears the OMNIA_STS_BUTTON_PRESSED bit on successful ++ * completion of the OMNIA_CMD_GET_STATUS_WORD command, resulting in ++ * another interrupt: ++ * - first we get an interrupt, we read the status word where ++ * OMNIA_STS_BUTTON_PRESSED is present, ++ * - MCU clears the OMNIA_STS_BUTTON_PRESSED bit because we read the ++ * status word, ++ * - we get another interrupt because the status word changed again ++ * (the OMNIA_STS_BUTTON_PRESSED bit was cleared). ++ * ++ * The gpiolib-cdev, gpiolib-sysfs and gpio-keys input driver all call ++ * the gpiochip's .get() method after an edge event on a requested GPIO ++ * occurs. ++ * ++ * We ensure that the .get() method reads 1 for the button GPIO for some ++ * time. ++ */ ++ ++ if (status & OMNIA_STS_BUTTON_PRESSED) { ++ mcu->button_pressed_emul = true; ++ mod_delayed_work(system_wq, &mcu->button_release_emul_work, ++ msecs_to_jiffies(FRONT_BUTTON_RELEASE_DELAY_MS)); ++ } else if (mcu->button_pressed_emul) { ++ status |= OMNIA_STS_BUTTON_PRESSED; ++ } ++ ++ rising_sts = ~mcu->last_status & status; ++ falling_sts = mcu->last_status & ~status; ++ ++ mcu->last_status = status; ++ ++ /* ++ * Fill in the relevant interrupt bits from status bits for CARD_DET, ++ * MSATA_IND and BUTTON_PRESSED. ++ */ ++ rising = 0; ++ falling = 0; ++ fill_int_from_sts(&rising, &falling, rising_sts, falling_sts, ++ OMNIA_STS_CARD_DET, OMNIA_INT_CARD_DET); ++ fill_int_from_sts(&rising, &falling, rising_sts, falling_sts, ++ OMNIA_STS_MSATA_IND, OMNIA_INT_MSATA_IND); ++ fill_int_from_sts(&rising, &falling, rising_sts, falling_sts, ++ OMNIA_STS_BUTTON_PRESSED, OMNIA_INT_BUTTON_PRESSED); ++ ++ /* Use only bits that are enabled */ ++ rising &= mcu->rising & mcu->mask; ++ falling &= mcu->falling & mcu->mask; ++ *pending = rising | falling; ++ ++ return true; ++} ++ ++static bool omnia_irq_read_pending(struct omnia_mcu *mcu, ++ unsigned long *pending) ++{ ++ if (mcu->features & OMNIA_FEAT_NEW_INT_API) ++ return omnia_irq_read_pending_new(mcu, pending); ++ else ++ return omnia_irq_read_pending_old(mcu, pending); ++} ++ ++static irqreturn_t omnia_irq_thread_handler(int irq, void *dev_id) ++{ ++ struct omnia_mcu *mcu = dev_id; ++ struct irq_domain *domain; ++ unsigned long pending; ++ unsigned int i; ++ ++ if (!omnia_irq_read_pending(mcu, &pending)) ++ return IRQ_NONE; ++ ++ domain = mcu->gc.irq.domain; ++ ++ for_each_set_bit(i, &pending, 32) { ++ unsigned int nested_irq; ++ ++ nested_irq = irq_find_mapping(domain, omnia_int_to_gpio_idx[i]); ++ ++ handle_nested_irq(nested_irq); ++ } ++ ++ return IRQ_RETVAL(pending); ++} ++ ++static const char * const front_button_modes[] = { "mcu", "cpu" }; ++ ++static ssize_t front_button_mode_show(struct device *dev, ++ struct device_attribute *a, char *buf) ++{ ++ struct omnia_mcu *mcu = dev_get_drvdata(dev); ++ int val; ++ ++ if (mcu->features & OMNIA_FEAT_NEW_INT_API) { ++ val = omnia_cmd_read_bit(mcu->client, OMNIA_CMD_GET_STATUS_WORD, ++ OMNIA_STS_BUTTON_MODE); ++ if (val < 0) ++ return val; ++ } else { ++ val = !!(mcu->last_status & OMNIA_STS_BUTTON_MODE); ++ } ++ ++ return sysfs_emit(buf, "%s\n", front_button_modes[val]); ++} ++ ++static ssize_t front_button_mode_store(struct device *dev, ++ struct device_attribute *a, ++ const char *buf, size_t count) ++{ ++ struct omnia_mcu *mcu = dev_get_drvdata(dev); ++ int err, i; ++ ++ i = sysfs_match_string(front_button_modes, buf); ++ if (i < 0) ++ return i; ++ ++ err = omnia_ctl_cmd_locked(mcu, OMNIA_CMD_GENERAL_CONTROL, ++ i ? OMNIA_CTL_BUTTON_MODE : 0, ++ OMNIA_CTL_BUTTON_MODE); ++ if (err) ++ return err; ++ ++ return count; ++} ++static DEVICE_ATTR_RW(front_button_mode); ++ ++static struct attribute *omnia_mcu_gpio_attrs[] = { ++ &dev_attr_front_button_mode.attr, ++ NULL ++}; ++ ++const struct attribute_group omnia_mcu_gpio_group = { ++ .attrs = omnia_mcu_gpio_attrs, ++}; ++ ++int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu) ++{ ++ bool new_api = mcu->features & OMNIA_FEAT_NEW_INT_API; ++ struct device *dev = &mcu->client->dev; ++ unsigned long irqflags; ++ int err; ++ ++ err = devm_mutex_init(dev, &mcu->lock); ++ if (err) ++ return err; ++ ++ mcu->gc.request = omnia_gpio_request; ++ mcu->gc.get_direction = omnia_gpio_get_direction; ++ mcu->gc.direction_input = omnia_gpio_direction_input; ++ mcu->gc.direction_output = omnia_gpio_direction_output; ++ mcu->gc.get = omnia_gpio_get; ++ mcu->gc.get_multiple = omnia_gpio_get_multiple; ++ mcu->gc.set = omnia_gpio_set; ++ mcu->gc.set_multiple = omnia_gpio_set_multiple; ++ mcu->gc.init_valid_mask = omnia_gpio_init_valid_mask; ++ mcu->gc.can_sleep = true; ++ mcu->gc.names = omnia_mcu_gpio_templates; ++ mcu->gc.base = -1; ++ mcu->gc.ngpio = ARRAY_SIZE(omnia_gpios); ++ mcu->gc.label = "Turris Omnia MCU GPIOs"; ++ mcu->gc.parent = dev; ++ mcu->gc.owner = THIS_MODULE; ++ mcu->gc.of_gpio_n_cells = 3; ++ mcu->gc.of_xlate = omnia_gpio_of_xlate; ++ ++ gpio_irq_chip_set_chip(&mcu->gc.irq, &omnia_mcu_irq_chip); ++ /* This will let us handle the parent IRQ in the driver */ ++ mcu->gc.irq.parent_handler = NULL; ++ mcu->gc.irq.num_parents = 0; ++ mcu->gc.irq.parents = NULL; ++ mcu->gc.irq.default_type = IRQ_TYPE_NONE; ++ mcu->gc.irq.handler = handle_bad_irq; ++ mcu->gc.irq.threaded = true; ++ if (new_api) ++ mcu->gc.irq.init_hw = omnia_irq_init_hw; ++ mcu->gc.irq.init_valid_mask = omnia_irq_init_valid_mask; ++ ++ err = devm_gpiochip_add_data(dev, &mcu->gc, mcu); ++ if (err) ++ return dev_err_probe(dev, err, "Cannot add GPIO chip\n"); ++ ++ /* ++ * Before requesting the interrupt, if firmware does not support the new ++ * interrupt API, we need to cache the value of the status word, so that ++ * when it changes, we may compare the new value with the cached one in ++ * the interrupt handler. ++ */ ++ if (!new_api) { ++ err = omnia_read_status_word_old_fw(mcu, &mcu->last_status); ++ if (err) ++ return dev_err_probe(dev, err, ++ "Cannot read status word\n"); ++ ++ INIT_DELAYED_WORK(&mcu->button_release_emul_work, ++ button_release_emul_fn); ++ } ++ ++ irqflags = IRQF_ONESHOT; ++ if (new_api) ++ irqflags |= IRQF_TRIGGER_LOW; ++ else ++ irqflags |= IRQF_TRIGGER_FALLING; ++ ++ err = devm_request_threaded_irq(dev, mcu->client->irq, NULL, ++ omnia_irq_thread_handler, irqflags, ++ "turris-omnia-mcu", mcu); ++ if (err) ++ return dev_err_probe(dev, err, "Cannot request IRQ\n"); ++ ++ if (!new_api) { ++ /* ++ * The button_release_emul_work has to be initialized before the ++ * thread is requested, and on driver remove it needs to be ++ * canceled before the thread is freed. Therefore we can't use ++ * devm_delayed_work_autocancel() directly, because the order ++ * devm_delayed_work_autocancel(); ++ * devm_request_threaded_irq(); ++ * would cause improper release order: ++ * free_irq(); ++ * cancel_delayed_work_sync(); ++ * Instead we first initialize the work above, and only now ++ * after IRQ is requested we add the work devm action. ++ */ ++ err = devm_add_action(dev, devm_delayed_work_drop, ++ &mcu->button_release_emul_work); ++ if (err) ++ return err; ++ } ++ ++ return 0; ++} +--- a/drivers/platform/cznic/turris-omnia-mcu.h ++++ b/drivers/platform/cznic/turris-omnia-mcu.h +@@ -8,8 +8,12 @@ + #ifndef __TURRIS_OMNIA_MCU_H + #define __TURRIS_OMNIA_MCU_H + ++#include ++#include + #include ++#include + #include ++#include + #include + + struct i2c_client; +@@ -23,18 +27,78 @@ struct omnia_mcu { + u64 board_serial_number; + u8 board_first_mac[ETH_ALEN]; + u8 board_revision; ++ ++ /* GPIO chip */ ++ struct gpio_chip gc; ++ struct mutex lock; ++ unsigned long mask, rising, falling, both, cached, is_cached; ++ /* Old MCU firmware handling needs the following */ ++ struct delayed_work button_release_emul_work; ++ unsigned long last_status; ++ bool button_pressed_emul; + }; + + int omnia_cmd_write_read(const struct i2c_client *client, + void *cmd, unsigned int cmd_len, + void *reply, unsigned int reply_len); + ++static inline int omnia_cmd_write(const struct i2c_client *client, void *cmd, ++ unsigned int len) ++{ ++ return omnia_cmd_write_read(client, cmd, len, NULL, 0); ++} ++ + static inline int omnia_cmd_read(const struct i2c_client *client, u8 cmd, + void *reply, unsigned int len) + { + return omnia_cmd_write_read(client, &cmd, 1, reply, len); + } + ++static inline unsigned int ++omnia_compute_reply_length(unsigned long mask, bool interleaved, ++ unsigned int offset) ++{ ++ if (!mask) ++ return 0; ++ ++ return ((__fls(mask) >> 3) << interleaved) + 1 + offset; ++} ++ ++/* Returns 0 on success */ ++static inline int omnia_cmd_read_bits(const struct i2c_client *client, u8 cmd, ++ unsigned long bits, unsigned long *dst) ++{ ++ __le32 reply; ++ int err; ++ ++ if (!bits) { ++ *dst = 0; ++ return 0; ++ } ++ ++ err = omnia_cmd_read(client, cmd, &reply, ++ omnia_compute_reply_length(bits, false, 0)); ++ if (err) ++ return err; ++ ++ *dst = le32_to_cpu(reply) & bits; ++ ++ return 0; ++} ++ ++static inline int omnia_cmd_read_bit(const struct i2c_client *client, u8 cmd, ++ unsigned long bit) ++{ ++ unsigned long reply; ++ int err; ++ ++ err = omnia_cmd_read_bits(client, cmd, bit, &reply); ++ if (err) ++ return err; ++ ++ return !!reply; ++} ++ + static inline int omnia_cmd_read_u32(const struct i2c_client *client, u8 cmd, + u32 *dst) + { +@@ -71,4 +135,8 @@ static inline int omnia_cmd_read_u8(cons + return omnia_cmd_read(client, cmd, reply, sizeof(*reply)); + } + ++extern const struct attribute_group omnia_mcu_gpio_group; ++ ++int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu); ++ + #endif /* __TURRIS_OMNIA_MCU_H */ diff --git a/target/linux/mvebu/patches-6.6/820-v6.11-04-platform-cznic-turris-omnia-mcu-Add-support-for-powe.patch b/target/linux/mvebu/patches-6.6/820-v6.11-04-platform-cznic-turris-omnia-mcu-Add-support-for-powe.patch new file mode 100644 index 0000000000..2ef6242d70 --- /dev/null +++ b/target/linux/mvebu/patches-6.6/820-v6.11-04-platform-cznic-turris-omnia-mcu-Add-support-for-powe.patch @@ -0,0 +1,415 @@ +From f69e0a731ab471f3a57c48258ad2d9990820c173 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 1 Jul 2024 13:30:06 +0200 +Subject: [PATCH 04/11] platform: cznic: turris-omnia-mcu: Add support for + poweroff and wakeup +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add support for true board poweroff (MCU can disable all unnecessary +voltage regulators) and wakeup at a specified time, implemented via a +RTC driver so that the rtcwake utility can be used to configure it. + +Signed-off-by: Marek Behún +Reviewed-by: Andy Shevchenko +Acked-by: Alexandre Belloni +Acked-by: Bartosz Golaszewski +Link: https://lore.kernel.org/r/20240701113010.16447-5-kabel@kernel.org +Signed-off-by: Arnd Bergmann +--- + .../sysfs-bus-i2c-devices-turris-omnia-mcu | 16 ++ + drivers/platform/cznic/Kconfig | 4 + + drivers/platform/cznic/Makefile | 1 + + .../platform/cznic/turris-omnia-mcu-base.c | 5 + + .../cznic/turris-omnia-mcu-sys-off-wakeup.c | 260 ++++++++++++++++++ + drivers/platform/cznic/turris-omnia-mcu.h | 20 ++ + 6 files changed, 306 insertions(+) + create mode 100644 drivers/platform/cznic/turris-omnia-mcu-sys-off-wakeup.c + +--- a/Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu ++++ b/Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu +@@ -38,6 +38,22 @@ Description: (RW) The front button on th + + Format: %s. + ++What: /sys/bus/i2c/devices//front_button_poweron ++Date: September 2024 ++KernelVersion: 6.11 ++Contact: Marek Behún ++Description: (RW) Newer versions of the microcontroller firmware of the ++ Turris Omnia router support powering off the router into true ++ low power mode. The router can be powered on by pressing the ++ front button. ++ ++ This file configures whether front button power on is enabled. ++ ++ This file is present only if the power off feature is supported ++ by the firmware. ++ ++ Format: %i. ++ + What: /sys/bus/i2c/devices//fw_features + Date: September 2024 + KernelVersion: 6.11 +--- a/drivers/platform/cznic/Kconfig ++++ b/drivers/platform/cznic/Kconfig +@@ -18,10 +18,14 @@ config TURRIS_OMNIA_MCU + depends on I2C + select GPIOLIB + select GPIOLIB_IRQCHIP ++ select RTC_CLASS + help + Say Y here to add support for the features implemented by the + microcontroller on the CZ.NIC's Turris Omnia SOHO router. + The features include: ++ - board poweroff into true low power mode (with voltage regulators ++ disabled) and the ability to configure wake up from this mode (via ++ rtcwake) + - GPIO pins + - to get front button press events (the front button can be + configured either to generate press events to the CPU or to change +--- a/drivers/platform/cznic/Makefile ++++ b/drivers/platform/cznic/Makefile +@@ -3,3 +3,4 @@ + obj-$(CONFIG_TURRIS_OMNIA_MCU) += turris-omnia-mcu.o + turris-omnia-mcu-y := turris-omnia-mcu-base.o + turris-omnia-mcu-y += turris-omnia-mcu-gpio.o ++turris-omnia-mcu-y += turris-omnia-mcu-sys-off-wakeup.o +--- a/drivers/platform/cznic/turris-omnia-mcu-base.c ++++ b/drivers/platform/cznic/turris-omnia-mcu-base.c +@@ -197,6 +197,7 @@ static const struct attribute_group omni + static const struct attribute_group *omnia_mcu_groups[] = { + &omnia_mcu_base_group, + &omnia_mcu_gpio_group, ++ &omnia_mcu_poweroff_group, + NULL + }; + +@@ -371,6 +372,10 @@ static int omnia_mcu_probe(struct i2c_cl + "Cannot read board info\n"); + } + ++ err = omnia_mcu_register_sys_off_and_wakeup(mcu); ++ if (err) ++ return err; ++ + return omnia_mcu_register_gpiochip(mcu); + } + +--- /dev/null ++++ b/drivers/platform/cznic/turris-omnia-mcu-sys-off-wakeup.c +@@ -0,0 +1,260 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * CZ.NIC's Turris Omnia MCU system off and RTC wakeup driver ++ * ++ * This is not a true RTC driver (in the sense that it does not provide a ++ * real-time clock), rather the MCU implements a wakeup from powered off state ++ * at a specified time relative to MCU boot, and we expose this feature via RTC ++ * alarm, so that it can be used via the rtcwake command, which is the standard ++ * Linux command for this. ++ * ++ * 2024 by Marek Behún ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include "turris-omnia-mcu.h" ++ ++static int omnia_get_uptime_wakeup(const struct i2c_client *client, u32 *uptime, ++ u32 *wakeup) ++{ ++ __le32 reply[2]; ++ int err; ++ ++ err = omnia_cmd_read(client, OMNIA_CMD_GET_UPTIME_AND_WAKEUP, reply, ++ sizeof(reply)); ++ if (err) ++ return err; ++ ++ if (uptime) ++ *uptime = le32_to_cpu(reply[0]); ++ ++ if (wakeup) ++ *wakeup = le32_to_cpu(reply[1]); ++ ++ return 0; ++} ++ ++static int omnia_read_time(struct device *dev, struct rtc_time *tm) ++{ ++ u32 uptime; ++ int err; ++ ++ err = omnia_get_uptime_wakeup(to_i2c_client(dev), &uptime, NULL); ++ if (err) ++ return err; ++ ++ rtc_time64_to_tm(uptime, tm); ++ ++ return 0; ++} ++ ++static int omnia_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct omnia_mcu *mcu = i2c_get_clientdata(client); ++ u32 wakeup; ++ int err; ++ ++ err = omnia_get_uptime_wakeup(client, NULL, &wakeup); ++ if (err) ++ return err; ++ ++ alrm->enabled = !!wakeup; ++ rtc_time64_to_tm(wakeup ?: mcu->rtc_alarm, &alrm->time); ++ ++ return 0; ++} ++ ++static int omnia_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct omnia_mcu *mcu = i2c_get_clientdata(client); ++ ++ mcu->rtc_alarm = rtc_tm_to_time64(&alrm->time); ++ ++ if (alrm->enabled) ++ return omnia_cmd_write_u32(client, OMNIA_CMD_SET_WAKEUP, ++ mcu->rtc_alarm); ++ ++ return 0; ++} ++ ++static int omnia_alarm_irq_enable(struct device *dev, unsigned int enabled) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct omnia_mcu *mcu = i2c_get_clientdata(client); ++ ++ return omnia_cmd_write_u32(client, OMNIA_CMD_SET_WAKEUP, ++ enabled ? mcu->rtc_alarm : 0); ++} ++ ++static const struct rtc_class_ops omnia_rtc_ops = { ++ .read_time = omnia_read_time, ++ .read_alarm = omnia_read_alarm, ++ .set_alarm = omnia_set_alarm, ++ .alarm_irq_enable = omnia_alarm_irq_enable, ++}; ++ ++static int omnia_power_off(struct sys_off_data *data) ++{ ++ struct omnia_mcu *mcu = data->cb_data; ++ __be32 tmp; ++ u8 cmd[9]; ++ u16 arg; ++ int err; ++ ++ if (mcu->front_button_poweron) ++ arg = OMNIA_CMD_POWER_OFF_POWERON_BUTTON; ++ else ++ arg = 0; ++ ++ cmd[0] = OMNIA_CMD_POWER_OFF; ++ put_unaligned_le16(OMNIA_CMD_POWER_OFF_MAGIC, &cmd[1]); ++ put_unaligned_le16(arg, &cmd[3]); ++ ++ /* ++ * Although all values from and to MCU are passed in little-endian, the ++ * MCU's CRC unit uses big-endian CRC32 polynomial (0x04c11db7), so we ++ * need to use crc32_be() here. ++ */ ++ tmp = cpu_to_be32(get_unaligned_le32(&cmd[1])); ++ put_unaligned_le32(crc32_be(~0, (void *)&tmp, sizeof(tmp)), &cmd[5]); ++ ++ err = omnia_cmd_write(mcu->client, cmd, sizeof(cmd)); ++ if (err) ++ dev_err(&mcu->client->dev, ++ "Unable to send the poweroff command: %d\n", err); ++ ++ return NOTIFY_DONE; ++} ++ ++static int omnia_restart(struct sys_off_data *data) ++{ ++ struct omnia_mcu *mcu = data->cb_data; ++ u8 cmd[3]; ++ int err; ++ ++ cmd[0] = OMNIA_CMD_GENERAL_CONTROL; ++ ++ if (reboot_mode == REBOOT_HARD) ++ cmd[1] = cmd[2] = OMNIA_CTL_HARD_RST; ++ else ++ cmd[1] = cmd[2] = OMNIA_CTL_LIGHT_RST; ++ ++ err = omnia_cmd_write(mcu->client, cmd, sizeof(cmd)); ++ if (err) ++ dev_err(&mcu->client->dev, ++ "Unable to send the restart command: %d\n", err); ++ ++ /* ++ * MCU needs a little bit to process the I2C command, otherwise it will ++ * do a light reset based on SOC SYSRES_OUT pin. ++ */ ++ mdelay(1); ++ ++ return NOTIFY_DONE; ++} ++ ++static ssize_t front_button_poweron_show(struct device *dev, ++ struct device_attribute *a, char *buf) ++{ ++ struct omnia_mcu *mcu = dev_get_drvdata(dev); ++ ++ return sysfs_emit(buf, "%d\n", mcu->front_button_poweron); ++} ++ ++static ssize_t front_button_poweron_store(struct device *dev, ++ struct device_attribute *a, ++ const char *buf, size_t count) ++{ ++ struct omnia_mcu *mcu = dev_get_drvdata(dev); ++ bool val; ++ int err; ++ ++ err = kstrtobool(buf, &val); ++ if (err) ++ return err; ++ ++ mcu->front_button_poweron = val; ++ ++ return count; ++} ++static DEVICE_ATTR_RW(front_button_poweron); ++ ++static struct attribute *omnia_mcu_poweroff_attrs[] = { ++ &dev_attr_front_button_poweron.attr, ++ NULL ++}; ++ ++static umode_t poweroff_attrs_visible(struct kobject *kobj, struct attribute *a, ++ int n) ++{ ++ struct device *dev = kobj_to_dev(kobj); ++ struct omnia_mcu *mcu = dev_get_drvdata(dev); ++ ++ if (mcu->features & OMNIA_FEAT_POWEROFF_WAKEUP) ++ return a->mode; ++ ++ return 0; ++} ++ ++const struct attribute_group omnia_mcu_poweroff_group = { ++ .attrs = omnia_mcu_poweroff_attrs, ++ .is_visible = poweroff_attrs_visible, ++}; ++ ++int omnia_mcu_register_sys_off_and_wakeup(struct omnia_mcu *mcu) ++{ ++ struct device *dev = &mcu->client->dev; ++ int err; ++ ++ /* MCU restart is always available */ ++ err = devm_register_sys_off_handler(dev, SYS_OFF_MODE_RESTART, ++ SYS_OFF_PRIO_FIRMWARE, ++ omnia_restart, mcu); ++ if (err) ++ return dev_err_probe(dev, err, ++ "Cannot register system restart handler\n"); ++ ++ /* ++ * Poweroff and wakeup are available only if POWEROFF_WAKEUP feature is ++ * present. ++ */ ++ if (!(mcu->features & OMNIA_FEAT_POWEROFF_WAKEUP)) ++ return 0; ++ ++ err = devm_register_sys_off_handler(dev, SYS_OFF_MODE_POWER_OFF, ++ SYS_OFF_PRIO_FIRMWARE, ++ omnia_power_off, mcu); ++ if (err) ++ return dev_err_probe(dev, err, ++ "Cannot register system power off handler\n"); ++ ++ mcu->rtcdev = devm_rtc_allocate_device(dev); ++ if (IS_ERR(mcu->rtcdev)) ++ return dev_err_probe(dev, PTR_ERR(mcu->rtcdev), ++ "Cannot allocate RTC device\n"); ++ ++ mcu->rtcdev->ops = &omnia_rtc_ops; ++ mcu->rtcdev->range_max = U32_MAX; ++ set_bit(RTC_FEATURE_ALARM_WAKEUP_ONLY, mcu->rtcdev->features); ++ ++ err = devm_rtc_register_device(mcu->rtcdev); ++ if (err) ++ return dev_err_probe(dev, err, "Cannot register RTC device\n"); ++ ++ mcu->front_button_poweron = true; ++ ++ return 0; ++} +--- a/drivers/platform/cznic/turris-omnia-mcu.h ++++ b/drivers/platform/cznic/turris-omnia-mcu.h +@@ -15,8 +15,10 @@ + #include + #include + #include ++#include + + struct i2c_client; ++struct rtc_device; + + struct omnia_mcu { + struct i2c_client *client; +@@ -36,6 +38,11 @@ struct omnia_mcu { + struct delayed_work button_release_emul_work; + unsigned long last_status; + bool button_pressed_emul; ++ ++ /* RTC device for configuring wake-up */ ++ struct rtc_device *rtcdev; ++ u32 rtc_alarm; ++ bool front_button_poweron; + }; + + int omnia_cmd_write_read(const struct i2c_client *client, +@@ -48,6 +55,17 @@ static inline int omnia_cmd_write(const + return omnia_cmd_write_read(client, cmd, len, NULL, 0); + } + ++static inline int omnia_cmd_write_u32(const struct i2c_client *client, u8 cmd, ++ u32 val) ++{ ++ u8 buf[5]; ++ ++ buf[0] = cmd; ++ put_unaligned_le32(val, &buf[1]); ++ ++ return omnia_cmd_write(client, buf, sizeof(buf)); ++} ++ + static inline int omnia_cmd_read(const struct i2c_client *client, u8 cmd, + void *reply, unsigned int len) + { +@@ -136,7 +154,9 @@ static inline int omnia_cmd_read_u8(cons + } + + extern const struct attribute_group omnia_mcu_gpio_group; ++extern const struct attribute_group omnia_mcu_poweroff_group; + + int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu); ++int omnia_mcu_register_sys_off_and_wakeup(struct omnia_mcu *mcu); + + #endif /* __TURRIS_OMNIA_MCU_H */ diff --git a/target/linux/mvebu/patches-6.6/820-v6.11-05-platform-cznic-turris-omnia-mcu-Add-support-for-MCU-.patch b/target/linux/mvebu/patches-6.6/820-v6.11-05-platform-cznic-turris-omnia-mcu-Add-support-for-MCU-.patch new file mode 100644 index 0000000000..cf3f88bfcf --- /dev/null +++ b/target/linux/mvebu/patches-6.6/820-v6.11-05-platform-cznic-turris-omnia-mcu-Add-support-for-MCU-.patch @@ -0,0 +1,250 @@ +From 33ae4e4c86bc6ff298489fb8b743e2743dd0af6d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 1 Jul 2024 13:30:07 +0200 +Subject: [PATCH 05/11] platform: cznic: turris-omnia-mcu: Add support for MCU + watchdog +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add support for the watchdog mechanism provided by the MCU. + +Signed-off-by: Marek Behún +Reviewed-by: Andy Shevchenko +Reviewed-by: Guenter Roeck +Acked-by: Bartosz Golaszewski +Link: https://lore.kernel.org/r/20240701113010.16447-6-kabel@kernel.org +Signed-off-by: Arnd Bergmann +--- + drivers/platform/cznic/Kconfig | 2 + + drivers/platform/cznic/Makefile | 1 + + .../platform/cznic/turris-omnia-mcu-base.c | 4 + + .../cznic/turris-omnia-mcu-watchdog.c | 130 ++++++++++++++++++ + drivers/platform/cznic/turris-omnia-mcu.h | 24 ++++ + 5 files changed, 161 insertions(+) + create mode 100644 drivers/platform/cznic/turris-omnia-mcu-watchdog.c + +--- a/drivers/platform/cznic/Kconfig ++++ b/drivers/platform/cznic/Kconfig +@@ -19,6 +19,7 @@ config TURRIS_OMNIA_MCU + select GPIOLIB + select GPIOLIB_IRQCHIP + select RTC_CLASS ++ select WATCHDOG_CORE + help + Say Y here to add support for the features implemented by the + microcontroller on the CZ.NIC's Turris Omnia SOHO router. +@@ -26,6 +27,7 @@ config TURRIS_OMNIA_MCU + - board poweroff into true low power mode (with voltage regulators + disabled) and the ability to configure wake up from this mode (via + rtcwake) ++ - MCU watchdog + - GPIO pins + - to get front button press events (the front button can be + configured either to generate press events to the CPU or to change +--- a/drivers/platform/cznic/Makefile ++++ b/drivers/platform/cznic/Makefile +@@ -4,3 +4,4 @@ obj-$(CONFIG_TURRIS_OMNIA_MCU) += turris + turris-omnia-mcu-y := turris-omnia-mcu-base.o + turris-omnia-mcu-y += turris-omnia-mcu-gpio.o + turris-omnia-mcu-y += turris-omnia-mcu-sys-off-wakeup.o ++turris-omnia-mcu-y += turris-omnia-mcu-watchdog.o +--- a/drivers/platform/cznic/turris-omnia-mcu-base.c ++++ b/drivers/platform/cznic/turris-omnia-mcu-base.c +@@ -376,6 +376,10 @@ static int omnia_mcu_probe(struct i2c_cl + if (err) + return err; + ++ err = omnia_mcu_register_watchdog(mcu); ++ if (err) ++ return err; ++ + return omnia_mcu_register_gpiochip(mcu); + } + +--- /dev/null ++++ b/drivers/platform/cznic/turris-omnia-mcu-watchdog.c +@@ -0,0 +1,130 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * CZ.NIC's Turris Omnia MCU watchdog driver ++ * ++ * 2024 by Marek Behún ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include "turris-omnia-mcu.h" ++ ++#define WATCHDOG_TIMEOUT 120 ++ ++static unsigned int timeout; ++module_param(timeout, int, 0); ++MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds"); ++ ++static bool nowayout = WATCHDOG_NOWAYOUT; ++module_param(nowayout, bool, 0); ++MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" ++ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); ++ ++static int omnia_wdt_start(struct watchdog_device *wdt) ++{ ++ struct omnia_mcu *mcu = watchdog_get_drvdata(wdt); ++ ++ return omnia_cmd_write_u8(mcu->client, OMNIA_CMD_SET_WATCHDOG_STATE, 1); ++} ++ ++static int omnia_wdt_stop(struct watchdog_device *wdt) ++{ ++ struct omnia_mcu *mcu = watchdog_get_drvdata(wdt); ++ ++ return omnia_cmd_write_u8(mcu->client, OMNIA_CMD_SET_WATCHDOG_STATE, 0); ++} ++ ++static int omnia_wdt_ping(struct watchdog_device *wdt) ++{ ++ struct omnia_mcu *mcu = watchdog_get_drvdata(wdt); ++ ++ return omnia_cmd_write_u8(mcu->client, OMNIA_CMD_SET_WATCHDOG_STATE, 1); ++} ++ ++static int omnia_wdt_set_timeout(struct watchdog_device *wdt, ++ unsigned int timeout) ++{ ++ struct omnia_mcu *mcu = watchdog_get_drvdata(wdt); ++ ++ return omnia_cmd_write_u16(mcu->client, OMNIA_CMD_SET_WDT_TIMEOUT, ++ timeout * DECI); ++} ++ ++static unsigned int omnia_wdt_get_timeleft(struct watchdog_device *wdt) ++{ ++ struct omnia_mcu *mcu = watchdog_get_drvdata(wdt); ++ u16 timeleft; ++ int err; ++ ++ err = omnia_cmd_read_u16(mcu->client, OMNIA_CMD_GET_WDT_TIMELEFT, ++ &timeleft); ++ if (err) { ++ dev_err(&mcu->client->dev, "Cannot get watchdog timeleft: %d\n", ++ err); ++ return 0; ++ } ++ ++ return timeleft / DECI; ++} ++ ++static const struct watchdog_info omnia_wdt_info = { ++ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, ++ .identity = "Turris Omnia MCU Watchdog", ++}; ++ ++static const struct watchdog_ops omnia_wdt_ops = { ++ .owner = THIS_MODULE, ++ .start = omnia_wdt_start, ++ .stop = omnia_wdt_stop, ++ .ping = omnia_wdt_ping, ++ .set_timeout = omnia_wdt_set_timeout, ++ .get_timeleft = omnia_wdt_get_timeleft, ++}; ++ ++int omnia_mcu_register_watchdog(struct omnia_mcu *mcu) ++{ ++ struct device *dev = &mcu->client->dev; ++ u8 state; ++ int err; ++ ++ if (!(mcu->features & OMNIA_FEAT_WDT_PING)) ++ return 0; ++ ++ mcu->wdt.info = &omnia_wdt_info; ++ mcu->wdt.ops = &omnia_wdt_ops; ++ mcu->wdt.parent = dev; ++ mcu->wdt.min_timeout = 1; ++ mcu->wdt.max_timeout = 65535 / DECI; ++ ++ mcu->wdt.timeout = WATCHDOG_TIMEOUT; ++ watchdog_init_timeout(&mcu->wdt, timeout, dev); ++ ++ watchdog_set_drvdata(&mcu->wdt, mcu); ++ ++ omnia_wdt_set_timeout(&mcu->wdt, mcu->wdt.timeout); ++ ++ err = omnia_cmd_read_u8(mcu->client, OMNIA_CMD_GET_WATCHDOG_STATE, ++ &state); ++ if (err) ++ return dev_err_probe(dev, err, ++ "Cannot get MCU watchdog state\n"); ++ ++ if (state) ++ set_bit(WDOG_HW_RUNNING, &mcu->wdt.status); ++ ++ watchdog_set_nowayout(&mcu->wdt, nowayout); ++ watchdog_stop_on_reboot(&mcu->wdt); ++ err = devm_watchdog_register_device(dev, &mcu->wdt); ++ if (err) ++ return dev_err_probe(dev, err, ++ "Cannot register MCU watchdog\n"); ++ ++ return 0; ++} +--- a/drivers/platform/cznic/turris-omnia-mcu.h ++++ b/drivers/platform/cznic/turris-omnia-mcu.h +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -43,6 +44,9 @@ struct omnia_mcu { + struct rtc_device *rtcdev; + u32 rtc_alarm; + bool front_button_poweron; ++ ++ /* MCU watchdog */ ++ struct watchdog_device wdt; + }; + + int omnia_cmd_write_read(const struct i2c_client *client, +@@ -55,6 +59,25 @@ static inline int omnia_cmd_write(const + return omnia_cmd_write_read(client, cmd, len, NULL, 0); + } + ++static inline int omnia_cmd_write_u8(const struct i2c_client *client, u8 cmd, ++ u8 val) ++{ ++ u8 buf[2] = { cmd, val }; ++ ++ return omnia_cmd_write(client, buf, sizeof(buf)); ++} ++ ++static inline int omnia_cmd_write_u16(const struct i2c_client *client, u8 cmd, ++ u16 val) ++{ ++ u8 buf[3]; ++ ++ buf[0] = cmd; ++ put_unaligned_le16(val, &buf[1]); ++ ++ return omnia_cmd_write(client, buf, sizeof(buf)); ++} ++ + static inline int omnia_cmd_write_u32(const struct i2c_client *client, u8 cmd, + u32 val) + { +@@ -158,5 +181,6 @@ extern const struct attribute_group omni + + int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu); + int omnia_mcu_register_sys_off_and_wakeup(struct omnia_mcu *mcu); ++int omnia_mcu_register_watchdog(struct omnia_mcu *mcu); + + #endif /* __TURRIS_OMNIA_MCU_H */ diff --git a/target/linux/mvebu/patches-6.6/820-v6.11-06-platform-cznic-turris-omnia-mcu-Add-support-for-MCU-.patch b/target/linux/mvebu/patches-6.6/820-v6.11-06-platform-cznic-turris-omnia-mcu-Add-support-for-MCU-.patch new file mode 100644 index 0000000000..35387e34c7 --- /dev/null +++ b/target/linux/mvebu/patches-6.6/820-v6.11-06-platform-cznic-turris-omnia-mcu-Add-support-for-MCU-.patch @@ -0,0 +1,225 @@ +From b3ed8645c45567b598bef0868dca166f8ed166a0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 1 Jul 2024 13:30:08 +0200 +Subject: [PATCH 06/11] platform: cznic: turris-omnia-mcu: Add support for MCU + provided TRNG +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add support for true random number generator provided by the MCU. +New Omnia boards come without the Atmel SHA204-A chip. Instead the +crypto functionality is provided by new microcontroller, which has +a TRNG peripheral. + +Signed-off-by: Marek Behún +Acked-by: Bartosz Golaszewski +Link: https://lore.kernel.org/r/20240701113010.16447-7-kabel@kernel.org +Signed-off-by: Arnd Bergmann +--- + drivers/platform/cznic/Kconfig | 2 + + drivers/platform/cznic/Makefile | 1 + + .../platform/cznic/turris-omnia-mcu-base.c | 6 +- + .../platform/cznic/turris-omnia-mcu-gpio.c | 2 +- + .../platform/cznic/turris-omnia-mcu-trng.c | 105 ++++++++++++++++++ + drivers/platform/cznic/turris-omnia-mcu.h | 8 ++ + 6 files changed, 122 insertions(+), 2 deletions(-) + create mode 100644 drivers/platform/cznic/turris-omnia-mcu-trng.c + +--- a/drivers/platform/cznic/Kconfig ++++ b/drivers/platform/cznic/Kconfig +@@ -18,6 +18,7 @@ config TURRIS_OMNIA_MCU + depends on I2C + select GPIOLIB + select GPIOLIB_IRQCHIP ++ select HW_RANDOM + select RTC_CLASS + select WATCHDOG_CORE + help +@@ -27,6 +28,7 @@ config TURRIS_OMNIA_MCU + - board poweroff into true low power mode (with voltage regulators + disabled) and the ability to configure wake up from this mode (via + rtcwake) ++ - true random number generator (if available on the MCU) + - MCU watchdog + - GPIO pins + - to get front button press events (the front button can be +--- a/drivers/platform/cznic/Makefile ++++ b/drivers/platform/cznic/Makefile +@@ -4,4 +4,5 @@ obj-$(CONFIG_TURRIS_OMNIA_MCU) += turris + turris-omnia-mcu-y := turris-omnia-mcu-base.o + turris-omnia-mcu-y += turris-omnia-mcu-gpio.o + turris-omnia-mcu-y += turris-omnia-mcu-sys-off-wakeup.o ++turris-omnia-mcu-y += turris-omnia-mcu-trng.o + turris-omnia-mcu-y += turris-omnia-mcu-watchdog.o +--- a/drivers/platform/cznic/turris-omnia-mcu-base.c ++++ b/drivers/platform/cznic/turris-omnia-mcu-base.c +@@ -380,7 +380,11 @@ static int omnia_mcu_probe(struct i2c_cl + if (err) + return err; + +- return omnia_mcu_register_gpiochip(mcu); ++ err = omnia_mcu_register_gpiochip(mcu); ++ if (err) ++ return err; ++ ++ return omnia_mcu_register_trng(mcu); + } + + static const struct of_device_id of_omnia_mcu_match[] = { +--- a/drivers/platform/cznic/turris-omnia-mcu-gpio.c ++++ b/drivers/platform/cznic/turris-omnia-mcu-gpio.c +@@ -194,7 +194,7 @@ static const struct omnia_gpio omnia_gpi + }; + + /* mapping from interrupts to indexes of GPIOs in the omnia_gpios array */ +-static const u8 omnia_int_to_gpio_idx[32] = { ++const u8 omnia_int_to_gpio_idx[32] = { + [__bf_shf(OMNIA_INT_CARD_DET)] = 4, + [__bf_shf(OMNIA_INT_MSATA_IND)] = 5, + [__bf_shf(OMNIA_INT_USB30_OVC)] = 6, +--- /dev/null ++++ b/drivers/platform/cznic/turris-omnia-mcu-trng.c +@@ -0,0 +1,105 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * CZ.NIC's Turris Omnia MCU TRNG driver ++ * ++ * 2024 by Marek Behún ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "../../gpio/gpiolib.h" ++ ++#include ++#include "turris-omnia-mcu.h" ++ ++#define OMNIA_CMD_TRNG_MAX_ENTROPY_LEN 64 ++ ++static irqreturn_t omnia_trng_irq_handler(int irq, void *dev_id) ++{ ++ struct omnia_mcu *mcu = dev_id; ++ ++ complete(&mcu->trng_entropy_ready); ++ ++ return IRQ_HANDLED; ++} ++ ++static int omnia_trng_read(struct hwrng *rng, void *data, size_t max, bool wait) ++{ ++ struct omnia_mcu *mcu = container_of(rng, struct omnia_mcu, trng); ++ u8 reply[1 + OMNIA_CMD_TRNG_MAX_ENTROPY_LEN]; ++ int err, bytes; ++ ++ if (!wait && !completion_done(&mcu->trng_entropy_ready)) ++ return 0; ++ ++ do { ++ if (wait_for_completion_interruptible(&mcu->trng_entropy_ready)) ++ return -ERESTARTSYS; ++ ++ err = omnia_cmd_read(mcu->client, ++ OMNIA_CMD_TRNG_COLLECT_ENTROPY, ++ reply, sizeof(reply)); ++ if (err) ++ return err; ++ ++ bytes = min3(reply[0], max, OMNIA_CMD_TRNG_MAX_ENTROPY_LEN); ++ } while (wait && !bytes); ++ ++ memcpy(data, &reply[1], bytes); ++ ++ return bytes; ++} ++ ++int omnia_mcu_register_trng(struct omnia_mcu *mcu) ++{ ++ struct device *dev = &mcu->client->dev; ++ u8 irq_idx, dummy; ++ int irq, err; ++ ++ if (!(mcu->features & OMNIA_FEAT_TRNG)) ++ return 0; ++ ++ irq_idx = omnia_int_to_gpio_idx[__bf_shf(OMNIA_INT_TRNG)]; ++ irq = gpiod_to_irq(gpiochip_get_desc(&mcu->gc, irq_idx)); ++ if (!irq) ++ return dev_err_probe(dev, -ENXIO, "Cannot get TRNG IRQ\n"); ++ ++ /* ++ * If someone else cleared the TRNG interrupt but did not read the ++ * entropy, a new interrupt won't be generated, and entropy collection ++ * will be stuck. Ensure an interrupt will be generated by executing ++ * the collect entropy command (and discarding the result). ++ */ ++ err = omnia_cmd_read(mcu->client, OMNIA_CMD_TRNG_COLLECT_ENTROPY, ++ &dummy, 1); ++ if (err) ++ return err; ++ ++ init_completion(&mcu->trng_entropy_ready); ++ ++ err = devm_request_threaded_irq(dev, irq, NULL, omnia_trng_irq_handler, ++ IRQF_ONESHOT, "turris-omnia-mcu-trng", ++ mcu); ++ if (err) ++ return dev_err_probe(dev, err, "Cannot request TRNG IRQ\n"); ++ ++ mcu->trng.name = "turris-omnia-mcu-trng"; ++ mcu->trng.read = omnia_trng_read; ++ ++ err = devm_hwrng_register(dev, &mcu->trng); ++ if (err) ++ return dev_err_probe(dev, err, "Cannot register TRNG\n"); ++ ++ return 0; ++} +--- a/drivers/platform/cznic/turris-omnia-mcu.h ++++ b/drivers/platform/cznic/turris-omnia-mcu.h +@@ -9,7 +9,9 @@ + #define __TURRIS_OMNIA_MCU_H + + #include ++#include + #include ++#include + #include + #include + #include +@@ -47,6 +49,10 @@ struct omnia_mcu { + + /* MCU watchdog */ + struct watchdog_device wdt; ++ ++ /* true random number generator */ ++ struct hwrng trng; ++ struct completion trng_entropy_ready; + }; + + int omnia_cmd_write_read(const struct i2c_client *client, +@@ -176,11 +182,13 @@ static inline int omnia_cmd_read_u8(cons + return omnia_cmd_read(client, cmd, reply, sizeof(*reply)); + } + ++extern const u8 omnia_int_to_gpio_idx[32]; + extern const struct attribute_group omnia_mcu_gpio_group; + extern const struct attribute_group omnia_mcu_poweroff_group; + + int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu); + int omnia_mcu_register_sys_off_and_wakeup(struct omnia_mcu *mcu); ++int omnia_mcu_register_trng(struct omnia_mcu *mcu); + int omnia_mcu_register_watchdog(struct omnia_mcu *mcu); + + #endif /* __TURRIS_OMNIA_MCU_H */ diff --git a/target/linux/mvebu/patches-6.6/820-v6.11-07-ARM-dts-turris-omnia-Add-MCU-system-controller-node.patch b/target/linux/mvebu/patches-6.6/820-v6.11-07-ARM-dts-turris-omnia-Add-MCU-system-controller-node.patch new file mode 100644 index 0000000000..ad65de2f52 --- /dev/null +++ b/target/linux/mvebu/patches-6.6/820-v6.11-07-ARM-dts-turris-omnia-Add-MCU-system-controller-node.patch @@ -0,0 +1,69 @@ +From 4f11095a4ae00b2fe4cebb21e36ee37cc62f5e1a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 1 Jul 2024 13:30:09 +0200 +Subject: [PATCH 07/11] ARM: dts: turris-omnia: Add MCU system-controller node +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Turris Omnia's MCU provides various features that can be configured over +I2C at address 0x2a. Add device-tree node. + +This does not carry a Fixes tag - we do not want this to get backported +to stable kernels for the following reason: U-Boot since v2022.10 +inserts a phy-reset-gpio property into the WAN ethernet node pointing to +the MCU node if it finds the MCU node with a cznic,turris-omnia-mcu +compatible. Thus if this change got backported to a stable kernel, the +WAN interface driver would defer probe indefinitely (since it would wait +for the turris-omnia-mcu driver which would not be present). + +Signed-off-by: Marek Behún +Reviewed-by: Andrew Lunn +Reviewed-by: Andy Shevchenko +Reviewed-by: Conor Dooley +Acked-by: Bartosz Golaszewski +Acked-by: Alexandre Belloni +Link: https://lore.kernel.org/r/20240701113010.16447-8-kabel@kernel.org +Signed-off-by: Arnd Bergmann +--- + .../dts/marvell/armada-385-turris-omnia.dts | 22 ++++++++++++++++++- + 1 file changed, 21 insertions(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/marvell/armada-385-turris-omnia.dts ++++ b/arch/arm/boot/dts/marvell/armada-385-turris-omnia.dts +@@ -218,7 +218,22 @@ + #size-cells = <0>; + reg = <0>; + +- /* STM32F0 command interface at address 0x2a */ ++ mcu: system-controller@2a { ++ compatible = "cznic,turris-omnia-mcu"; ++ reg = <0x2a>; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mcu_pins>; ++ ++ interrupt-parent = <&gpio1>; ++ interrupts = <11 IRQ_TYPE_NONE>; ++ ++ gpio-controller; ++ #gpio-cells = <3>; ++ ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ }; + + led-controller@2b { + compatible = "cznic,turris-omnia-leds"; +@@ -503,6 +518,11 @@ + }; + + &pinctrl { ++ mcu_pins: mcu-pins { ++ marvell,pins = "mpp43"; ++ marvell,function = "gpio"; ++ }; ++ + pcawan_pins: pcawan-pins { + marvell,pins = "mpp46"; + marvell,function = "gpio"; diff --git a/target/linux/mvebu/patches-6.6/820-v6.11-08-ARM-dts-turris-omnia-Add-GPIO-key-node-for-front-but.patch b/target/linux/mvebu/patches-6.6/820-v6.11-08-ARM-dts-turris-omnia-Add-GPIO-key-node-for-front-but.patch new file mode 100644 index 0000000000..4b36167d66 --- /dev/null +++ b/target/linux/mvebu/patches-6.6/820-v6.11-08-ARM-dts-turris-omnia-Add-GPIO-key-node-for-front-but.patch @@ -0,0 +1,46 @@ +From c3eeabe0b8d22d7c869278cc0cb35b83512fbed5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 1 Jul 2024 13:30:10 +0200 +Subject: [PATCH 08/11] ARM: dts: turris-omnia: Add GPIO key node for front + button +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Now that we have the MCU device-tree node, which acts as a GPIO +controller, add GPIO key node for the front button. + +Signed-off-by: Marek Behún +Reviewed-by: Andrew Lunn +Reviewed-by: Andy Shevchenko +Reviewed-by: Conor Dooley +Acked-by: Bartosz Golaszewski +Acked-by: Alexandre Belloni +Link: https://lore.kernel.org/r/20240701113010.16447-9-kabel@kernel.org +Signed-off-by: Arnd Bergmann +--- + .../boot/dts/marvell/armada-385-turris-omnia.dts | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/arch/arm/boot/dts/marvell/armada-385-turris-omnia.dts ++++ b/arch/arm/boot/dts/marvell/armada-385-turris-omnia.dts +@@ -112,6 +112,19 @@ + status = "disabled"; + }; + ++ gpio-keys { ++ compatible = "gpio-keys"; ++ ++ front-button { ++ label = "Front Button"; ++ linux,code = ; ++ linux,can-disable; ++ gpios = <&mcu 0 12 GPIO_ACTIVE_HIGH>; ++ /* debouncing is done by the microcontroller */ ++ debounce-interval = <0>; ++ }; ++ }; ++ + sound { + compatible = "simple-audio-card"; + simple-audio-card,name = "SPDIF"; diff --git a/target/linux/mvebu/patches-6.6/820-v6.11-09-platform-cznic-turris-omnia-mcu-Depend-on-OF.patch b/target/linux/mvebu/patches-6.6/820-v6.11-09-platform-cznic-turris-omnia-mcu-Depend-on-OF.patch new file mode 100644 index 0000000000..80c9e1a3cc --- /dev/null +++ b/target/linux/mvebu/patches-6.6/820-v6.11-09-platform-cznic-turris-omnia-mcu-Depend-on-OF.patch @@ -0,0 +1,32 @@ +From 08838657bbc35494276c7ba4ef53f30a9816f8c9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 8 Jul 2024 13:40:01 +0200 +Subject: [PATCH 09/11] platform: cznic: turris-omnia-mcu: Depend on OF +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add depend on OF, otherwise the compilation fails with + error: no member named 'of_gpio_n_cells' in 'struct gpio_chip' + error: no member named 'of_xlate' in 'struct gpio_chip' + +Fixes: dfa556e45ae9 ("platform: cznic: turris-omnia-mcu: Add support for MCU connected GPIOs") +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202407031646.trNSwajF-lkp@intel.com/ +Signed-off-by: Marek Behún +Link: https://lore.kernel.org/r/20240708114002.4285-2-kabel@kernel.org +Signed-off-by: Arnd Bergmann +--- + drivers/platform/cznic/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/platform/cznic/Kconfig ++++ b/drivers/platform/cznic/Kconfig +@@ -16,6 +16,7 @@ config TURRIS_OMNIA_MCU + tristate "Turris Omnia MCU driver" + depends on MACH_ARMADA_38X || COMPILE_TEST + depends on I2C ++ depends on OF + select GPIOLIB + select GPIOLIB_IRQCHIP + select HW_RANDOM diff --git a/target/linux/mvebu/patches-6.6/820-v6.11-10-platform-cznic-turris-omnia-mcu-Depend-on-WATCHDOG.patch b/target/linux/mvebu/patches-6.6/820-v6.11-10-platform-cznic-turris-omnia-mcu-Depend-on-WATCHDOG.patch new file mode 100644 index 0000000000..50e028752a --- /dev/null +++ b/target/linux/mvebu/patches-6.6/820-v6.11-10-platform-cznic-turris-omnia-mcu-Depend-on-WATCHDOG.patch @@ -0,0 +1,32 @@ +From 5e425e6eca155c162da58d4e58e896ed4109c7fd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 8 Jul 2024 13:40:02 +0200 +Subject: [PATCH 10/11] platform: cznic: turris-omnia-mcu: Depend on WATCHDOG +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add depend on WATCHDOG, otherwise modpost fails with + ERROR: modpost: "watchdog_init_timeout" [drivers/platform/cznic/turris-omnia-mcu.ko] undefined! + ERROR: modpost: "devm_watchdog_register_device" [drivers/platform/cznic/turris-omnia-mcu.ko] undefined! + +Fixes: ab89fb5fb92c ("platform: cznic: turris-omnia-mcu: Add support for MCU watchdog") +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202407040711.g19y3cWq-lkp@intel.com/ +Signed-off-by: Marek Behún +Link: https://lore.kernel.org/r/20240708114002.4285-3-kabel@kernel.org +Signed-off-by: Arnd Bergmann +--- + drivers/platform/cznic/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/platform/cznic/Kconfig ++++ b/drivers/platform/cznic/Kconfig +@@ -17,6 +17,7 @@ config TURRIS_OMNIA_MCU + depends on MACH_ARMADA_38X || COMPILE_TEST + depends on I2C + depends on OF ++ depends on WATCHDOG + select GPIOLIB + select GPIOLIB_IRQCHIP + select HW_RANDOM diff --git a/target/linux/mvebu/patches-6.6/820-v6.11-11-platform-cznic-turris-omnia-mcu-fix-Kconfig-dependen.patch b/target/linux/mvebu/patches-6.6/820-v6.11-11-platform-cznic-turris-omnia-mcu-fix-Kconfig-dependen.patch new file mode 100644 index 0000000000..30a476586e --- /dev/null +++ b/target/linux/mvebu/patches-6.6/820-v6.11-11-platform-cznic-turris-omnia-mcu-fix-Kconfig-dependen.patch @@ -0,0 +1,45 @@ +From 24c68c2525de5fcd0f3b16b2ad1028fb13b53393 Mon Sep 17 00:00:00 2001 +From: Arnd Bergmann +Date: Mon, 15 Jul 2024 08:02:30 +0200 +Subject: [PATCH 11/11] platform: cznic: turris-omnia-mcu: fix Kconfig + dependencies + +The newly added driver causes a Kconfig warning: + +WARNING: unmet direct dependencies detected for RTC_CLASS + Depends on [n]: !S390 [=y] + Selected by [m]: + - TURRIS_OMNIA_MCU [=m] && CZNIC_PLATFORMS [=y] && (MACH_ARMADA_38X || COMPILE_TEST [=y]) && I2C [=m] && OF [=y] && WATCHDOG [=y] + +The problem here is that it selects entire subsystems, which normal +device drivers should not do. Changes all of these to 'depends on' +instead. + +Fixes: dfa556e45ae9e ("platform: cznic: turris-omnia-mcu: Add support for MCU connected GPIOs") +Fixes: 90e700fd12b61 ("platform: cznic: turris-omnia-mcu: Add support for poweroff and wakeup") +Fixes: ab89fb5fb92c7 ("platform: cznic: turris-omnia-mcu: Add support for MCU watchdog") +Fixes: 41bb142a40289 ("platform: cznic: turris-omnia-mcu: Add support for MCU provided TRNG") +Reported-by: Nathan Chancellor +Signed-off-by: Arnd Bergmann +--- + drivers/platform/cznic/Kconfig | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/platform/cznic/Kconfig ++++ b/drivers/platform/cznic/Kconfig +@@ -18,11 +18,11 @@ config TURRIS_OMNIA_MCU + depends on I2C + depends on OF + depends on WATCHDOG +- select GPIOLIB ++ depends on GPIOLIB ++ depends on HW_RANDOM ++ depends on RTC_CLASS ++ depends on WATCHDOG_CORE + select GPIOLIB_IRQCHIP +- select HW_RANDOM +- select RTC_CLASS +- select WATCHDOG_CORE + help + Say Y here to add support for the features implemented by the + microcontroller on the CZ.NIC's Turris Omnia SOHO router. diff --git a/target/linux/mvebu/patches-6.6/907-MAINTAINERS-Add-an-entry-for-the-IEI-WT61P803-PUZZLE.patch b/target/linux/mvebu/patches-6.6/907-MAINTAINERS-Add-an-entry-for-the-IEI-WT61P803-PUZZLE.patch index 2a8397d0b5..dad8c16be1 100644 --- a/target/linux/mvebu/patches-6.6/907-MAINTAINERS-Add-an-entry-for-the-IEI-WT61P803-PUZZLE.patch +++ b/target/linux/mvebu/patches-6.6/907-MAINTAINERS-Add-an-entry-for-the-IEI-WT61P803-PUZZLE.patch @@ -16,7 +16,7 @@ Cc: Robert Marko --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -10138,6 +10138,22 @@ IFCVF VIRTIO DATA PATH ACCELERATOR +@@ -10142,6 +10142,22 @@ IFCVF VIRTIO DATA PATH ACCELERATOR R: Zhu Lingshan F: drivers/vdpa/ifcvf/ diff --git a/target/linux/ramips/dts/mt7620a_iodata_wn-ac733gr3.dts b/target/linux/ramips/dts/mt7620a_iodata_wn-ac733gr3.dts index d95a4ad99d..19b1538241 100644 --- a/target/linux/ramips/dts/mt7620a_iodata_wn-ac733gr3.dts +++ b/target/linux/ramips/dts/mt7620a_iodata_wn-ac733gr3.dts @@ -77,7 +77,7 @@ compatible = "realtek,rtl8367b"; gpio-sda = <&gpio0 22 GPIO_ACTIVE_HIGH>; gpio-sck = <&gpio0 23 GPIO_ACTIVE_HIGH>; - realtek,extif1 = <1 0 1 1 1 1 1 1 2>; + realtek,extif = <6 1 0 1 1 1 1 1 1 2>; }; }; diff --git a/target/linux/ramips/dts/mt7620a_tplink_archer-c2-v1.dts b/target/linux/ramips/dts/mt7620a_tplink_archer-c2-v1.dts index 06f3eba37b..feb619a0c0 100644 --- a/target/linux/ramips/dts/mt7620a_tplink_archer-c2-v1.dts +++ b/target/linux/ramips/dts/mt7620a_tplink_archer-c2-v1.dts @@ -55,7 +55,7 @@ rtl8367rb { compatible = "realtek,rtl8367b"; - realtek,extif1 = <1 0 1 1 1 1 1 1 2>; + realtek,extif = <6 1 0 1 1 1 1 1 1 2>; mii-bus = <&mdio0>; }; }; diff --git a/target/linux/ramips/dts/mt7620a_tplink_archer-c5-v4.dts b/target/linux/ramips/dts/mt7620a_tplink_archer-c5-v4.dts index 855e06e9f6..91b3a255c1 100644 --- a/target/linux/ramips/dts/mt7620a_tplink_archer-c5-v4.dts +++ b/target/linux/ramips/dts/mt7620a_tplink_archer-c5-v4.dts @@ -74,7 +74,7 @@ rtl8367s { compatible = "realtek,rtl8367b"; - realtek,extif2 = <1 0 1 1 1 1 1 1 2>; + realtek,extif = <7 1 0 1 1 1 1 1 1 2>; mii-bus = <&mdio0>; phy-id = <29>; }; diff --git a/target/linux/ramips/dts/mt7620a_tplink_ec220-g5-v2.dts b/target/linux/ramips/dts/mt7620a_tplink_ec220-g5-v2.dts index 7fc075aedd..a39455cf29 100644 --- a/target/linux/ramips/dts/mt7620a_tplink_ec220-g5-v2.dts +++ b/target/linux/ramips/dts/mt7620a_tplink_ec220-g5-v2.dts @@ -82,7 +82,7 @@ rtl8367s { compatible = "realtek,rtl8367b"; - realtek,extif2 = <1 0 1 1 1 1 1 1 2>; + realtek,extif = <7 1 0 1 1 1 1 1 1 2>; mii-bus = <&mdio0>; phy-id = <29>; }; diff --git a/target/linux/ramips/dts/mt7620a_zyxel_keenetic-viva.dts b/target/linux/ramips/dts/mt7620a_zyxel_keenetic-viva.dts index 0630e8a160..d095b45630 100644 --- a/target/linux/ramips/dts/mt7620a_zyxel_keenetic-viva.dts +++ b/target/linux/ramips/dts/mt7620a_zyxel_keenetic-viva.dts @@ -85,7 +85,7 @@ rtl8367rb { compatible = "realtek,rtl8367b"; - realtek,extif2 = <1 0 1 1 1 1 1 1 2>; + realtek,extif = <7 1 0 1 1 1 1 1 1 2>; mii-bus = <&mdio0>; }; }; diff --git a/target/linux/ramips/dts/rt3662_asus_rt-n56u.dts b/target/linux/ramips/dts/rt3662_asus_rt-n56u.dts index 391076cee9..c381aa3e03 100644 --- a/target/linux/ramips/dts/rt3662_asus_rt-n56u.dts +++ b/target/linux/ramips/dts/rt3662_asus_rt-n56u.dts @@ -73,7 +73,7 @@ compatible = "realtek,rtl8367"; gpio-sda = <&gpio0 1 GPIO_ACTIVE_HIGH>; gpio-sck = <&gpio0 2 GPIO_ACTIVE_HIGH>; - realtek,extif1 = <1 0 1 1 1 1 1 1 2>; + realtek,extif = <8 1 0 1 1 1 1 1 1 2>; }; keys { diff --git a/target/linux/ramips/dts/rt3662_dlink_dir-645.dts b/target/linux/ramips/dts/rt3662_dlink_dir-645.dts index 3d6479f44f..8cfa48e195 100644 --- a/target/linux/ramips/dts/rt3662_dlink_dir-645.dts +++ b/target/linux/ramips/dts/rt3662_dlink_dir-645.dts @@ -19,7 +19,7 @@ compatible = "realtek,rtl8367b"; gpio-sda = <&gpio0 1 GPIO_ACTIVE_HIGH>; gpio-sck = <&gpio0 2 GPIO_ACTIVE_HIGH>; - realtek,extif1 = <1 0 1 1 1 1 1 1 2>; + realtek,extif = <6 1 0 1 1 1 1 1 1 2>; }; keys { diff --git a/target/linux/ramips/dts/rt3662_edimax_br-6475nd.dts b/target/linux/ramips/dts/rt3662_edimax_br-6475nd.dts index 051e28da8f..fbc795b24f 100644 --- a/target/linux/ramips/dts/rt3662_edimax_br-6475nd.dts +++ b/target/linux/ramips/dts/rt3662_edimax_br-6475nd.dts @@ -127,7 +127,7 @@ compatible = "realtek,rtl8367"; gpio-sda = <&gpio0 5 GPIO_ACTIVE_HIGH>; gpio-sck = <&gpio0 4 GPIO_ACTIVE_HIGH>; - realtek,extif0 = <1 0 1 1 1 1 1 1 2>; + realtek,extif = <9 1 0 1 1 1 1 1 1 2>; }; /* diff --git a/target/linux/ramips/dts/rt3662_samsung_cy-swr1100.dts b/target/linux/ramips/dts/rt3662_samsung_cy-swr1100.dts index 9964fcf600..bcc215c17a 100644 --- a/target/linux/ramips/dts/rt3662_samsung_cy-swr1100.dts +++ b/target/linux/ramips/dts/rt3662_samsung_cy-swr1100.dts @@ -81,7 +81,7 @@ compatible = "realtek,rtl8367"; gpio-sda = <&gpio0 1 GPIO_ACTIVE_HIGH>; gpio-sck = <&gpio0 2 GPIO_ACTIVE_HIGH>; - realtek,extif0 = <1 0 1 1 1 1 1 1 2>; + realtek,extif = <9 1 0 1 1 1 1 1 1 2>; }; keys { diff --git a/target/linux/ramips/dts/rt3883_belkin_f9k110x.dtsi b/target/linux/ramips/dts/rt3883_belkin_f9k110x.dtsi index a2d1906b89..4d60bb3c05 100644 --- a/target/linux/ramips/dts/rt3883_belkin_f9k110x.dtsi +++ b/target/linux/ramips/dts/rt3883_belkin_f9k110x.dtsi @@ -12,7 +12,7 @@ compatible = "realtek,rtl8367b"; gpio-sda = <&gpio0 1 GPIO_ACTIVE_HIGH>; gpio-sck = <&gpio0 2 GPIO_ACTIVE_HIGH>; - realtek,extif1 = <1 0 1 1 1 1 1 1 2>; + realtek,extif = <5 1 0 1 1 1 1 1 1 2>; }; }; diff --git a/target/linux/ramips/patches-6.6/410-mtd-rawnand-add-driver-support-for-MT7621-nand-flash.patch b/target/linux/ramips/patches-6.6/410-mtd-rawnand-add-driver-support-for-MT7621-nand-flash.patch index 51f1a5ec5e..f87edd3e67 100644 --- a/target/linux/ramips/patches-6.6/410-mtd-rawnand-add-driver-support-for-MT7621-nand-flash.patch +++ b/target/linux/ramips/patches-6.6/410-mtd-rawnand-add-driver-support-for-MT7621-nand-flash.patch @@ -20,7 +20,7 @@ Signed-off-by: Weijie Gao --- a/drivers/mtd/nand/raw/Kconfig +++ b/drivers/mtd/nand/raw/Kconfig -@@ -338,6 +338,14 @@ config MTD_NAND_QCOM +@@ -337,6 +337,14 @@ config MTD_NAND_QCOM Enables support for NAND flash chips on SoCs containing the EBI2 NAND controller. This controller is found on IPQ806x SoC. diff --git a/target/linux/ramips/patches-6.6/810-uvc-add-iPassion-iP2970-support.patch b/target/linux/ramips/patches-6.6/810-uvc-add-iPassion-iP2970-support.patch index b58cb786ad..7e04c9b1bc 100644 --- a/target/linux/ramips/patches-6.6/810-uvc-add-iPassion-iP2970-support.patch +++ b/target/linux/ramips/patches-6.6/810-uvc-add-iPassion-iP2970-support.patch @@ -13,7 +13,7 @@ Signed-off-by: John Crispin --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c -@@ -3151,6 +3151,18 @@ static const struct usb_device_id uvc_id +@@ -3173,6 +3173,18 @@ static const struct usb_device_id uvc_id .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) }, @@ -64,7 +64,7 @@ Signed-off-by: John Crispin #include -@@ -1235,9 +1240,149 @@ static void uvc_video_decode_data(struct +@@ -1246,9 +1251,149 @@ static void uvc_video_decode_data(struct uvc_urb->async_operations++; } @@ -214,7 +214,7 @@ Signed-off-by: John Crispin /* Mark the buffer as done if the EOF marker is set. */ if (data[1] & UVC_STREAM_EOF && buf->bytesused != 0) { uvc_dbg(stream->dev, FRAME, "Frame complete (EOF found)\n"); -@@ -1819,6 +1964,8 @@ static int uvc_init_video_isoc(struct uv +@@ -1830,6 +1975,8 @@ static int uvc_init_video_isoc(struct uv if (npackets == 0) return -ENOMEM; @@ -225,16 +225,16 @@ Signed-off-by: John Crispin for_each_uvc_urb(uvc_urb, stream) { --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h -@@ -74,6 +74,8 @@ - #define UVC_QUIRK_FORCE_BPP 0x00001000 - #define UVC_QUIRK_WAKE_AUTOSUSPEND 0x00002000 +@@ -76,6 +76,8 @@ #define UVC_QUIRK_NO_RESET_RESUME 0x00004000 -+#define UVC_QUIRK_MOTION 0x00008000 -+#define UVC_QUIRK_SINGLE_ISO 0x00010000 + #define UVC_QUIRK_DISABLE_AUTOSUSPEND 0x00008000 + #define UVC_QUIRK_INVALID_DEVICE_SOF 0x00010000 ++#define UVC_QUIRK_MOTION 0x00020000 ++#define UVC_QUIRK_SINGLE_ISO 0x00040000 /* Format flags */ #define UVC_FMT_FLAG_COMPRESSED 0x00000001 -@@ -583,6 +585,7 @@ struct uvc_device { +@@ -585,6 +587,7 @@ struct uvc_device { struct input_dev *input; char input_phys[64]; diff --git a/target/linux/rockchip/patches-6.6/002-v6.7-arm64-dts-rockchip-Add-missing-sdmmc2-SDR-rates-to-rock-3.patch b/target/linux/rockchip/patches-6.6/002-v6.7-arm64-dts-rockchip-Add-missing-sdmmc2-SDR-rates-to-rock-3.patch index 0dc7bf24b8..f70ba3c081 100644 --- a/target/linux/rockchip/patches-6.6/002-v6.7-arm64-dts-rockchip-Add-missing-sdmmc2-SDR-rates-to-rock-3.patch +++ b/target/linux/rockchip/patches-6.6/002-v6.7-arm64-dts-rockchip-Add-missing-sdmmc2-SDR-rates-to-rock-3.patch @@ -27,7 +27,7 @@ Signed-off-by: Heiko Stuebner }; chosen: chosen { -@@ -747,6 +748,9 @@ +@@ -743,6 +744,9 @@ non-removable; pinctrl-names = "default"; pinctrl-0 = <&sdmmc2m0_bus4 &sdmmc2m0_cmd &sdmmc2m0_clk>; diff --git a/target/linux/rockchip/patches-6.6/005-01-v6.8-arm64-dts-rockchip-add-gpio-line-names-to-rk3308-roc.patch b/target/linux/rockchip/patches-6.6/005-01-v6.8-arm64-dts-rockchip-add-gpio-line-names-to-rk3308-roc.patch index 28e3b276ba..83ebe67789 100644 --- a/target/linux/rockchip/patches-6.6/005-01-v6.8-arm64-dts-rockchip-add-gpio-line-names-to-rk3308-roc.patch +++ b/target/linux/rockchip/patches-6.6/005-01-v6.8-arm64-dts-rockchip-add-gpio-line-names-to-rk3308-roc.patch @@ -20,7 +20,7 @@ Signed-off-by: Heiko Stuebner --- a/arch/arm64/boot/dts/rockchip/rk3308-rock-pi-s.dts +++ b/arch/arm64/boot/dts/rockchip/rk3308-rock-pi-s.dts -@@ -258,3 +258,61 @@ +@@ -315,3 +315,61 @@ &wdt { status = "okay"; }; diff --git a/target/linux/rockchip/patches-6.6/005-02-v6.8-arm64-dts-rockchip-rk3308-rock-pi-s-gpio-line-names-.patch b/target/linux/rockchip/patches-6.6/005-02-v6.8-arm64-dts-rockchip-rk3308-rock-pi-s-gpio-line-names-.patch index 3d006c00fe..994644e142 100644 --- a/target/linux/rockchip/patches-6.6/005-02-v6.8-arm64-dts-rockchip-rk3308-rock-pi-s-gpio-line-names-.patch +++ b/target/linux/rockchip/patches-6.6/005-02-v6.8-arm64-dts-rockchip-rk3308-rock-pi-s-gpio-line-names-.patch @@ -19,8 +19,8 @@ Signed-off-by: Heiko Stuebner --- a/arch/arm64/boot/dts/rockchip/rk3308-rock-pi-s.dts +++ b/arch/arm64/boot/dts/rockchip/rk3308-rock-pi-s.dts -@@ -151,6 +151,68 @@ - status = "okay"; +@@ -166,6 +166,68 @@ + }; }; +&gpio0 { @@ -88,7 +88,7 @@ Signed-off-by: Heiko Stuebner &i2c1 { status = "okay"; }; -@@ -258,61 +320,3 @@ +@@ -315,61 +377,3 @@ &wdt { status = "okay"; }; diff --git a/target/linux/rockchip/patches-6.6/005-03-v6.11-arm64-dts-rockchip-Add-sdmmc-related-properties-on-r.patch b/target/linux/rockchip/patches-6.6/005-03-v6.11-arm64-dts-rockchip-Add-sdmmc-related-properties-on-r.patch deleted file mode 100644 index d9e69def19..0000000000 --- a/target/linux/rockchip/patches-6.6/005-03-v6.11-arm64-dts-rockchip-Add-sdmmc-related-properties-on-r.patch +++ /dev/null @@ -1,32 +0,0 @@ -From fc0daeccc384233eadfa9d5ddbd00159653c6bdc Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Tue, 21 May 2024 21:10:07 +0000 -Subject: [PATCH] arm64: dts: rockchip: Add sdmmc related properties on - rk3308-rock-pi-s - -Add cap-mmc-highspeed to allow use of high speed MMC mode using an eMMC -to uSD board. Use disable-wp to signal that no physical write-protect -line is present. Also add vcc_io used for card and IO line power as -vmmc-supply. - -Fixes: 2e04c25b1320 ("arm64: dts: rockchip: add ROCK Pi S DTS support") -Signed-off-by: Jonas Karlman -Link: https://lore.kernel.org/r/20240521211029.1236094-5-jonas@kwiboo.se -Signed-off-by: Heiko Stuebner ---- - arch/arm64/boot/dts/rockchip/rk3308-rock-pi-s.dts | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/arch/arm64/boot/dts/rockchip/rk3308-rock-pi-s.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3308-rock-pi-s.dts -@@ -272,7 +272,10 @@ - }; - - &sdmmc { -+ cap-mmc-highspeed; - cap-sd-highspeed; -+ disable-wp; -+ vmmc-supply = <&vcc_io>; - status = "okay"; - }; - diff --git a/target/linux/rockchip/patches-6.6/005-04-v6.11-arm64-dts-rockchip-Add-pinctrl-for-UART0-to-rk3308-r.patch b/target/linux/rockchip/patches-6.6/005-04-v6.11-arm64-dts-rockchip-Add-pinctrl-for-UART0-to-rk3308-r.patch deleted file mode 100644 index a1ada4de25..0000000000 --- a/target/linux/rockchip/patches-6.6/005-04-v6.11-arm64-dts-rockchip-Add-pinctrl-for-UART0-to-rk3308-r.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 7affb86ef62581e3475ce3e0a7640da1f2ee29f8 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Tue, 21 May 2024 21:10:08 +0000 -Subject: [PATCH] arm64: dts: rockchip: Add pinctrl for UART0 to - rk3308-rock-pi-s - -UAR0 CTS/RTS is not wired to any pin and is not used for the default -serial console use of UART0 on ROCK Pi S. - -Override the SoC defined pinctrl props to limit configuration of the -two xfer pins wired to one of the GPIO pin headers. - -Fixes: 2e04c25b1320 ("arm64: dts: rockchip: add ROCK Pi S DTS support") -Signed-off-by: Jonas Karlman -Link: https://lore.kernel.org/r/20240521211029.1236094-6-jonas@kwiboo.se -Signed-off-by: Heiko Stuebner ---- - arch/arm64/boot/dts/rockchip/rk3308-rock-pi-s.dts | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/arch/arm64/boot/dts/rockchip/rk3308-rock-pi-s.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3308-rock-pi-s.dts -@@ -294,6 +294,8 @@ - }; - - &uart0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&uart0_xfer>; - status = "okay"; - }; - diff --git a/target/linux/rockchip/patches-6.6/005-05-v6.11-arm64-dts-rockchip-Add-mdio-and-ethernet-phy-nodes-t.patch b/target/linux/rockchip/patches-6.6/005-05-v6.11-arm64-dts-rockchip-Add-mdio-and-ethernet-phy-nodes-t.patch deleted file mode 100644 index 2120974ec9..0000000000 --- a/target/linux/rockchip/patches-6.6/005-05-v6.11-arm64-dts-rockchip-Add-mdio-and-ethernet-phy-nodes-t.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 4b64ed510ed946a4e4ca6d51d6512bf5361f6a04 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Tue, 21 May 2024 21:10:10 +0000 -Subject: [PATCH] arm64: dts: rockchip: Add mdio and ethernet-phy nodes to - rk3308-rock-pi-s - -Be explicit about the Ethernet port and define mdio and ethernet-phy -nodes in the device tree for ROCK Pi S. - -Fixes: bc3753aed81f ("arm64: dts: rockchip: rock-pi-s add more peripherals") -Signed-off-by: Jonas Karlman -Link: https://lore.kernel.org/r/20240521211029.1236094-8-jonas@kwiboo.se -Signed-off-by: Heiko Stuebner ---- - .../boot/dts/rockchip/rk3308-rock-pi-s.dts | 26 ++++++++++++++++--- - 1 file changed, 23 insertions(+), 3 deletions(-) - ---- a/arch/arm64/boot/dts/rockchip/rk3308-rock-pi-s.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3308-rock-pi-s.dts -@@ -144,11 +144,25 @@ - - &gmac { - clock_in_out = "output"; -+ phy-handle = <&rtl8201f>; - phy-supply = <&vcc_io>; -- snps,reset-gpio = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>; -- snps,reset-active-low; -- snps,reset-delays-us = <0 50000 50000>; - status = "okay"; -+ -+ mdio { -+ compatible = "snps,dwmac-mdio"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ rtl8201f: ethernet-phy@1 { -+ compatible = "ethernet-phy-ieee802.3-c22"; -+ reg = <1>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&mac_rst>; -+ reset-assert-us = <20000>; -+ reset-deassert-us = <50000>; -+ reset-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>; -+ }; -+ }; - }; - - &gpio0 { -@@ -221,6 +235,12 @@ - pinctrl-names = "default"; - pinctrl-0 = <&rtc_32k>; - -+ gmac { -+ mac_rst: mac-rst { -+ rockchip,pins = <0 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+ - leds { - green_led: green-led { - rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; diff --git a/target/linux/rockchip/patches-6.6/007-01-v6.11-arm64-dts-rockchip-Add-io-domains-to-rk3308-rock-pi-.patch b/target/linux/rockchip/patches-6.6/007-01-v6.11-arm64-dts-rockchip-Add-io-domains-to-rk3308-rock-pi-.patch index 149cadf863..ad746df3b0 100644 --- a/target/linux/rockchip/patches-6.6/007-01-v6.11-arm64-dts-rockchip-Add-io-domains-to-rk3308-rock-pi-.patch +++ b/target/linux/rockchip/patches-6.6/007-01-v6.11-arm64-dts-rockchip-Add-io-domains-to-rk3308-rock-pi-.patch @@ -16,7 +16,7 @@ Signed-off-by: Heiko Stuebner --- a/arch/arm64/boot/dts/rockchip/rk3308-rock-pi-s.dts +++ b/arch/arm64/boot/dts/rockchip/rk3308-rock-pi-s.dts -@@ -231,6 +231,16 @@ +@@ -232,6 +232,16 @@ status = "okay"; }; diff --git a/target/linux/rockchip/patches-6.6/007-02-v6.11-arm64-dts-rockchip-Update-WIFi-BT-related-nodes-on-r.patch b/target/linux/rockchip/patches-6.6/007-02-v6.11-arm64-dts-rockchip-Update-WIFi-BT-related-nodes-on-r.patch deleted file mode 100644 index 976e5f4cdf..0000000000 --- a/target/linux/rockchip/patches-6.6/007-02-v6.11-arm64-dts-rockchip-Update-WIFi-BT-related-nodes-on-r.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 12c3ec878cbe3709782e85b88124abecc3bb8617 Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Tue, 21 May 2024 21:10:16 +0000 -Subject: [PATCH] arm64: dts: rockchip: Update WIFi/BT related nodes on - rk3308-rock-pi-s - -Update WiFi SDIO and BT UART related props to better reflect details -about the optional onboard RTL8723DS WiFi/BT module. - -Also correct the compatible used for bluetooth to match the WiFi/BT -module used on the board. - -Fixes: bc3753aed81f ("arm64: dts: rockchip: rock-pi-s add more peripherals") -Signed-off-by: Jonas Karlman -Link: https://lore.kernel.org/r/20240521211029.1236094-14-jonas@kwiboo.se -Signed-off-by: Heiko Stuebner ---- - .../boot/dts/rockchip/rk3308-rock-pi-s.dts | 40 +++++++++++++++++-- - 1 file changed, 36 insertions(+), 4 deletions(-) - ---- a/arch/arm64/boot/dts/rockchip/rk3308-rock-pi-s.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3308-rock-pi-s.dts -@@ -17,6 +17,7 @@ - ethernet0 = &gmac; - mmc0 = &emmc; - mmc1 = &sdmmc; -+ mmc2 = &sdio; - }; - - chosen { -@@ -245,6 +246,20 @@ - pinctrl-names = "default"; - pinctrl-0 = <&rtc_32k>; - -+ bluetooth { -+ bt_reg_on: bt-reg-on { -+ rockchip,pins = <4 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ -+ bt_wake_host: bt-wake-host { -+ rockchip,pins = <4 RK_PB4 RK_FUNC_GPIO &pcfg_pull_down>; -+ }; -+ -+ host_wake_bt: host-wake-bt { -+ rockchip,pins = <4 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+ - gmac { - mac_rst: mac-rst { - rockchip,pins = <0 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>; -@@ -294,11 +309,24 @@ - cap-sd-highspeed; - cap-sdio-irq; - keep-power-in-suspend; -- max-frequency = <1000000>; -+ max-frequency = <100000000>; - mmc-pwrseq = <&sdio_pwrseq>; -+ no-mmc; -+ no-sd; - non-removable; -- sd-uhs-sdr104; -+ sd-uhs-sdr50; -+ vmmc-supply = <&vcc_io>; -+ vqmmc-supply = <&vcc_1v8>; - status = "okay"; -+ -+ rtl8723ds: wifi@1 { -+ reg = <1>; -+ interrupt-parent = <&gpio0>; -+ interrupts = ; -+ interrupt-names = "host-wake"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&wifi_host_wake>; -+ }; - }; - - &sdmmc { -@@ -330,12 +358,16 @@ - }; - - &uart4 { -+ uart-has-rtscts; - status = "okay"; - - bluetooth { -- compatible = "realtek,rtl8723bs-bt"; -- device-wake-gpios = <&gpio4 RK_PB3 GPIO_ACTIVE_HIGH>; -+ compatible = "realtek,rtl8723ds-bt"; -+ device-wake-gpios = <&gpio4 RK_PB2 GPIO_ACTIVE_HIGH>; -+ enable-gpios = <&gpio4 RK_PB3 GPIO_ACTIVE_HIGH>; - host-wake-gpios = <&gpio4 RK_PB4 GPIO_ACTIVE_HIGH>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&bt_reg_on &bt_wake_host &host_wake_bt>; - }; - }; - diff --git a/target/linux/rockchip/patches-6.6/034-20-v6.7-drm-sched-Convert-the-GPU-scheduler-to-variable-number-of.patch b/target/linux/rockchip/patches-6.6/034-20-v6.7-drm-sched-Convert-the-GPU-scheduler-to-variable-number-of.patch index 5539118d67..6ae0e54f5e 100644 --- a/target/linux/rockchip/patches-6.6/034-20-v6.7-drm-sched-Convert-the-GPU-scheduler-to-variable-number-of.patch +++ b/target/linux/rockchip/patches-6.6/034-20-v6.7-drm-sched-Convert-the-GPU-scheduler-to-variable-number-of.patch @@ -76,7 +76,7 @@ Link: https://lore.kernel.org/r/20231023032251.164775-1-luben.tuikov@amd.com while ((s_job = to_drm_sched_job(spsc_queue_pop(&s_entity->job_queue)))) { --- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c -@@ -135,6 +135,7 @@ int etnaviv_sched_init(struct etnaviv_gp +@@ -134,6 +134,7 @@ int etnaviv_sched_init(struct etnaviv_gp int ret; ret = drm_sched_init(&gpu->sched, &etnaviv_sched_ops, diff --git a/target/linux/rockchip/patches-6.6/034-22-v6.8-drm-sched-Convert-drm-scheduler-to-use-a-work-queue-rathe.patch b/target/linux/rockchip/patches-6.6/034-22-v6.8-drm-sched-Convert-drm-scheduler-to-use-a-work-queue-rathe.patch index 4d231f3928..348b20d0d6 100644 --- a/target/linux/rockchip/patches-6.6/034-22-v6.8-drm-sched-Convert-drm-scheduler-to-use-a-work-queue-rathe.patch +++ b/target/linux/rockchip/patches-6.6/034-22-v6.8-drm-sched-Convert-drm-scheduler-to-use-a-work-queue-rathe.patch @@ -75,7 +75,7 @@ Signed-off-by: Luben Tuikov timeout, adev->reset_domain->wq, --- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c -@@ -134,7 +134,7 @@ int etnaviv_sched_init(struct etnaviv_gp +@@ -133,7 +133,7 @@ int etnaviv_sched_init(struct etnaviv_gp { int ret; diff --git a/target/linux/rockchip/patches-6.6/113-02-nvmem-rockchip-otp-Set-type-to-OTP.patch b/target/linux/rockchip/patches-6.6/036-01-v6.11-nvmem-rockchip-otp-Set-type-to-OTP.patch similarity index 52% rename from target/linux/rockchip/patches-6.6/113-02-nvmem-rockchip-otp-Set-type-to-OTP.patch rename to target/linux/rockchip/patches-6.6/036-01-v6.11-nvmem-rockchip-otp-Set-type-to-OTP.patch index 11d9858353..8491eb3c9c 100644 --- a/target/linux/rockchip/patches-6.6/113-02-nvmem-rockchip-otp-Set-type-to-OTP.patch +++ b/target/linux/rockchip/patches-6.6/036-01-v6.11-nvmem-rockchip-otp-Set-type-to-OTP.patch @@ -1,19 +1,14 @@ -From: Heiko Stuebner -To: srinivas.kandagatla@linaro.org -Cc: heiko@sntech.de, linux-arm-kernel@lists.infradead.org, - linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org, - quentin.schulz@cherry.de, - Heiko Stuebner -Subject: [PATCH 2/3] nvmem: rockchip-otp: Set type to OTP -Date: Tue, 7 May 2024 14:22:55 +0200 [thread overview] -Message-ID: <20240507122256.3765362-3-heiko@sntech.de> (raw) -In-Reply-To: <20240507122256.3765362-1-heiko@sntech.de> - +From 39f95600d8c53355b212a117e91a6ba15e0cac47 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner +Date: Fri, 5 Jul 2024 08:48:42 +0100 +Subject: [PATCH] nvmem: rockchip-otp: Set type to OTP The Rockchip OTP is obviously an OTP memory, so document this fact. Signed-off-by: Heiko Stuebner +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20240705074852.423202-6-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/rockchip-otp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target/linux/rockchip/patches-6.6/113-03-nvmem-rockchip-efuse-set-type-to-OTP.patch b/target/linux/rockchip/patches-6.6/036-02-v6.11-nvmem-rockchip-efuse-set-type-to-OTP.patch similarity index 55% rename from target/linux/rockchip/patches-6.6/113-03-nvmem-rockchip-efuse-set-type-to-OTP.patch rename to target/linux/rockchip/patches-6.6/036-02-v6.11-nvmem-rockchip-efuse-set-type-to-OTP.patch index c216aaa3f0..260b03eb03 100644 --- a/target/linux/rockchip/patches-6.6/113-03-nvmem-rockchip-efuse-set-type-to-OTP.patch +++ b/target/linux/rockchip/patches-6.6/036-02-v6.11-nvmem-rockchip-efuse-set-type-to-OTP.patch @@ -1,20 +1,15 @@ -From: Heiko Stuebner -To: srinivas.kandagatla@linaro.org -Cc: heiko@sntech.de, linux-arm-kernel@lists.infradead.org, - linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org, - quentin.schulz@cherry.de, - Heiko Stuebner -Subject: [PATCH 3/3] nvmem: rockchip-efuse: set type to OTP -Date: Tue, 7 May 2024 14:22:56 +0200 [thread overview] -Message-ID: <20240507122256.3765362-4-heiko@sntech.de> (raw) -In-Reply-To: <20240507122256.3765362-1-heiko@sntech.de> - +From ba64a04474d2989f397982c48e405cfd785e2dd5 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner +Date: Fri, 5 Jul 2024 08:48:43 +0100 +Subject: [PATCH] nvmem: rockchip-efuse: set type to OTP This device currently reports an "Unknown" type in sysfs. Since it is an eFuse hardware device, set its type to OTP. Signed-off-by: Heiko Stuebner +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20240705074852.423202-7-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/rockchip-efuse.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target/linux/rockchip/patches-6.6/113-01-nvmem-rockchip-otp-set-add_legacy_fixed_of_cells-config-o.patch b/target/linux/rockchip/patches-6.6/113-01-nvmem-rockchip-otp-set-add_legacy_fixed_of_cells-config-o.patch deleted file mode 100644 index eaa1958f80..0000000000 --- a/target/linux/rockchip/patches-6.6/113-01-nvmem-rockchip-otp-set-add_legacy_fixed_of_cells-config-o.patch +++ /dev/null @@ -1,32 +0,0 @@ -From: Heiko Stuebner -To: srinivas.kandagatla@linaro.org -Cc: heiko@sntech.de, linux-arm-kernel@lists.infradead.org, - linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org, - quentin.schulz@cherry.de, - Heiko Stuebner -Subject: [PATCH 1/3] nvmem: rockchip-otp: set add_legacy_fixed_of_cells config option -Date: Tue, 7 May 2024 14:22:54 +0200 [thread overview] -Message-ID: <20240507122256.3765362-2-heiko@sntech.de> (raw) -In-Reply-To: <20240507122256.3765362-1-heiko@sntech.de> - -From: Heiko Stuebner - -The Rockchip OTP describes its layout via devicetree subnodes, -so set the appropriate property. - -Fixes: 2cc3b37f5b6d ("nvmem: add explicit config option to read old syntax fixed OF cells") -Signed-off-by: Heiko Stuebner ---- - drivers/nvmem/rockchip-otp.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/nvmem/rockchip-otp.c -+++ b/drivers/nvmem/rockchip-otp.c -@@ -255,6 +255,7 @@ static int rockchip_otp_read(void *conte - static struct nvmem_config otp_config = { - .name = "rockchip-otp", - .owner = THIS_MODULE, -+ .add_legacy_fixed_of_cells = true, - .read_only = true, - .stride = 1, - .word_size = 1, diff --git a/target/linux/rockchip/patches-6.6/114-PCI-dw-rockchip-Fix-initial-PERST-GPIO-value.patch b/target/linux/rockchip/patches-6.6/114-PCI-dw-rockchip-Fix-initial-PERST-GPIO-value.patch deleted file mode 100644 index c56547da2f..0000000000 --- a/target/linux/rockchip/patches-6.6/114-PCI-dw-rockchip-Fix-initial-PERST-GPIO-value.patch +++ /dev/null @@ -1,76 +0,0 @@ -From c335ab00b0cd70707291efaf9ff48ebb69dcf667 Mon Sep 17 00:00:00 2001 -From: Niklas Cassel -Date: Wed, 17 Apr 2024 18:42:26 +0200 -Subject: [PATCH] PCI: dw-rockchip: Fix initial PERST# GPIO value -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -PERST# is active low according to the PCIe specification. - -However, the existing pcie-dw-rockchip.c driver does: - - gpiod_set_value(..., 0); msleep(100); gpiod_set_value(..., 1); - -when asserting + deasserting PERST#. - -This is of course wrong, but because all the device trees for this -compatible string have also incorrectly marked this GPIO as ACTIVE_HIGH: - - $ git grep -B 10 reset-gpios arch/arm64/boot/dts/rockchip/rk3568* - $ git grep -B 10 reset-gpios arch/arm64/boot/dts/rockchip/rk3588* - -The actual toggling of PERST# is correct, and we cannot change it anyway, -since that would break device tree compatibility. - -However, this driver does request the GPIO to be initialized as -GPIOD_OUT_HIGH, which does cause a silly sequence where PERST# gets -toggled back and forth for no good reason. - -Fix this by requesting the GPIO to be initialized as GPIOD_OUT_LOW (which -for this driver means PERST# asserted). - -This will avoid an unnecessary signal change where PERST# gets deasserted -(by devm_gpiod_get_optional()) and then gets asserted (by -rockchip_pcie_start_link()) just a few instructions later. - -Before patch, debug prints on EP side, when booting RC: - - [ 845.606810] pci: PERST# asserted by host! - [ 852.483985] pci: PERST# de-asserted by host! - [ 852.503041] pci: PERST# asserted by host! - [ 852.610318] pci: PERST# de-asserted by host! - -After patch, debug prints on EP side, when booting RC: - - [ 125.107921] pci: PERST# asserted by host! - [ 132.111429] pci: PERST# de-asserted by host! - -This extra, very short, PERST# assertion + deassertion has been reported to -cause issues with certain WLAN controllers, e.g. RTL8822CE. - -Fixes: 0e898eb8df4e ("PCI: rockchip-dwc: Add Rockchip RK356X host controller driver") -Link: https://lore.kernel.org/linux-pci/20240417164227.398901-1-cassel@kernel.org -Tested-by: Heiko Stuebner -Tested-by: Jianfeng Liu -Signed-off-by: Niklas Cassel -Signed-off-by: Krzysztof Wilczyński -Signed-off-by: Bjorn Helgaas -Reviewed-by: Heiko Stuebner -Reviewed-by: Manivannan Sadhasivam -Cc: stable@vger.kernel.org # v5.15+ ---- - drivers/pci/controller/dwc/pcie-dw-rockchip.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c -+++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c -@@ -240,7 +240,7 @@ static int rockchip_pcie_resource_get(st - return PTR_ERR(rockchip->apb_base); - - rockchip->rst_gpio = devm_gpiod_get_optional(&pdev->dev, "reset", -- GPIOD_OUT_HIGH); -+ GPIOD_OUT_LOW); - if (IS_ERR(rockchip->rst_gpio)) - return PTR_ERR(rockchip->rst_gpio); - diff --git a/target/linux/rockchip/patches-6.6/301-arm64-dts-rockchip-rk3568-Add-otp-device-node.patch b/target/linux/rockchip/patches-6.6/301-arm64-dts-rockchip-rk3568-Add-otp-device-node.patch index ffef9bcbcf..43f69ad8b7 100644 --- a/target/linux/rockchip/patches-6.6/301-arm64-dts-rockchip-rk3568-Add-otp-device-node.patch +++ b/target/linux/rockchip/patches-6.6/301-arm64-dts-rockchip-rk3568-Add-otp-device-node.patch @@ -11,7 +11,7 @@ Change-Id: I4ec51ba8d4e1381f787c0137cb475a21e546789d --- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi -@@ -881,6 +881,47 @@ +@@ -882,6 +882,47 @@ }; }; diff --git a/target/linux/rockchip/patches-6.6/910-mmc-allow-probe-to-defer-if-clock-is-not-ready.patch b/target/linux/rockchip/patches-6.6/502-mmc-allow-probe-to-defer-if-clock-is-not-ready.patch similarity index 100% rename from target/linux/rockchip/patches-6.6/910-mmc-allow-probe-to-defer-if-clock-is-not-ready.patch rename to target/linux/rockchip/patches-6.6/502-mmc-allow-probe-to-defer-if-clock-is-not-ready.patch diff --git a/target/linux/rockchip/patches-6.6/610-arm64-rockchip-add-OF-node-for-eth.patch b/target/linux/rockchip/patches-6.6/610-arm64-rockchip-add-OF-node-for-eth.patch index defcbe1a86..6ab0e051a5 100644 --- a/target/linux/rockchip/patches-6.6/610-arm64-rockchip-add-OF-node-for-eth.patch +++ b/target/linux/rockchip/patches-6.6/610-arm64-rockchip-add-OF-node-for-eth.patch @@ -104,7 +104,7 @@ Signed-off-by: David Bauer &pinctrl { --- a/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r66s.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3568-fastrhino-r66s.dtsi -@@ -373,6 +373,19 @@ +@@ -369,6 +369,19 @@ reset-gpios = <&gpio0 RK_PC3 GPIO_ACTIVE_HIGH>; vpcie3v3-supply = <&vcc3v3_pcie>; status = "okay"; @@ -124,7 +124,7 @@ Signed-off-by: David Bauer }; &pcie3x2 { -@@ -380,6 +393,19 @@ +@@ -376,6 +389,19 @@ reset-gpios = <&gpio0 RK_PC6 GPIO_ACTIVE_HIGH>; vpcie3v3-supply = <&vcc3v3_pcie>; status = "okay"; @@ -163,7 +163,7 @@ Signed-off-by: David Bauer phy-mode = "rgmii-id"; pinctrl-names = "default"; @@ -76,6 +78,7 @@ - reg = <0>; + reg = <0x1>; pinctrl-0 = <ð_phy0_reset_pin>; pinctrl-names = "default"; + realtek,led-data = <0x6d60>; @@ -171,15 +171,15 @@ Signed-off-by: David Bauer }; @@ -85,6 +88,7 @@ - reg = <0>; + reg = <0x1>; pinctrl-0 = <ð_phy1_reset_pin>; pinctrl-names = "default"; + realtek,led-data = <0x6d60>; }; }; -@@ -102,6 +106,14 @@ - }; +@@ -106,6 +110,14 @@ + vccio3-supply = <&vcc_3v3>; }; +&rtl8125_1 { @@ -298,7 +298,7 @@ Signed-off-by: David Bauer status = "okay"; }; -@@ -592,9 +596,7 @@ +@@ -588,9 +592,7 @@ reg = <0x0>; pinctrl-names = "default"; pinctrl-0 = <ð_phy_rst>; diff --git a/target/linux/rockchip/patches-6.6/703-arm64-rk3568-update-gicv3-its-and-pci-msi-map.patch b/target/linux/rockchip/patches-6.6/703-arm64-rk3568-update-gicv3-its-and-pci-msi-map.patch index 9110283241..0be02ed746 100644 --- a/target/linux/rockchip/patches-6.6/703-arm64-rk3568-update-gicv3-its-and-pci-msi-map.patch +++ b/target/linux/rockchip/patches-6.6/703-arm64-rk3568-update-gicv3-its-and-pci-msi-map.patch @@ -66,7 +66,7 @@ }; usb_host0_ehci: usb@fd800000 { -@@ -1077,7 +1084,7 @@ +@@ -1078,7 +1085,7 @@ num-ib-windows = <6>; num-ob-windows = <2>; max-link-speed = <2>; diff --git a/target/linux/rockchip/patches-6.6/801-04-arm64-dts-rockchip-rk356x-add-rng-node.patch b/target/linux/rockchip/patches-6.6/801-04-arm64-dts-rockchip-rk356x-add-rng-node.patch index d223247aec..4b7ca8b1ec 100644 --- a/target/linux/rockchip/patches-6.6/801-04-arm64-dts-rockchip-rk356x-add-rng-node.patch +++ b/target/linux/rockchip/patches-6.6/801-04-arm64-dts-rockchip-rk356x-add-rng-node.patch @@ -24,7 +24,7 @@ Signed-off-by: Lin Jinhan phy-names = "usb2-phy", "usb3-phy"; --- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi -@@ -1122,6 +1122,16 @@ +@@ -1123,6 +1123,16 @@ }; }; diff --git a/target/linux/sunxi/patches-6.6/410-sunxi-add-bananapi-p2-zero.patch b/target/linux/sunxi/patches-6.6/410-sunxi-add-bananapi-p2-zero.patch index 350d7f0403..f605292dcd 100644 --- a/target/linux/sunxi/patches-6.6/410-sunxi-add-bananapi-p2-zero.patch +++ b/target/linux/sunxi/patches-6.6/410-sunxi-add-bananapi-p2-zero.patch @@ -1,6 +1,6 @@ --- a/arch/arm/boot/dts/allwinner/Makefile +++ b/arch/arm/boot/dts/allwinner/Makefile -@@ -280,6 +280,7 @@ dtb-$(CONFIG_MACH_SUN8I) += \ +@@ -219,6 +219,7 @@ dtb-$(CONFIG_MACH_SUN8I) += \ sun8i-a83t-cubietruck-plus.dtb \ sun8i-a83t-tbs-a711.dtb \ sun8i-h2-plus-bananapi-m2-zero.dtb \ diff --git a/target/linux/zynq/Makefile b/target/linux/zynq/Makefile index 29995e43bf..c570fae73b 100644 --- a/target/linux/zynq/Makefile +++ b/target/linux/zynq/Makefile @@ -18,8 +18,7 @@ define Target/Description Build firmware image for Zynq 7000 SoC devices. endef -KERNEL_PATCHVER:=6.1 -KERNEL_TESTING_PATCHVER:=6.6 +KERNEL_PATCHVER:=6.6 include $(INCLUDE_DIR)/target.mk diff --git a/target/linux/zynq/config-6.1 b/target/linux/zynq/config-6.1 deleted file mode 100644 index b6318a776c..0000000000 --- a/target/linux/zynq/config-6.1 +++ /dev/null @@ -1,566 +0,0 @@ -CONFIG_ALIGNMENT_TRAP=y -# CONFIG_ALTERA_FREEZE_BRIDGE is not set -# CONFIG_ALTERA_PR_IP_CORE is not set -CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y -CONFIG_ARCH_MULTIPLATFORM=y -CONFIG_ARCH_MULTI_V6_V7=y -CONFIG_ARCH_MULTI_V7=y -CONFIG_ARCH_NR_GPIO=1024 -CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y -CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y -CONFIG_ARCH_SELECT_MEMORY_MODEL=y -CONFIG_ARCH_SPARSEMEM_ENABLE=y -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ARCH_VEXPRESS=y -CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA=y -# CONFIG_ARCH_VEXPRESS_SPC is not set -CONFIG_ARCH_ZYNQ=y -CONFIG_ARM=y -CONFIG_ARM_AMBA=y -CONFIG_ARM_CPU_SUSPEND=y -CONFIG_ARM_ERRATA_643719=y -CONFIG_ARM_ERRATA_720789=y -CONFIG_ARM_ERRATA_754322=y -CONFIG_ARM_ERRATA_754327=y -CONFIG_ARM_ERRATA_764369=y -CONFIG_ARM_ERRATA_775420=y -CONFIG_ARM_GIC=y -CONFIG_ARM_GLOBAL_TIMER=y -CONFIG_ARM_GT_INITIAL_PRESCALER_VAL=2 -CONFIG_ARM_HAS_GROUP_RELOCS=y -CONFIG_ARM_HEAVY_MB=y -CONFIG_ARM_L1_CACHE_SHIFT=6 -CONFIG_ARM_L1_CACHE_SHIFT_6=y -CONFIG_ARM_PATCH_IDIV=y -CONFIG_ARM_PATCH_PHYS_VIRT=y -# CONFIG_ARM_PL172_MPMC is not set -# CONFIG_ARM_SMMU is not set -CONFIG_ARM_THUMB=y -CONFIG_ARM_TIMER_SP804=y -CONFIG_ARM_UNWIND=y -CONFIG_ARM_VIRT_EXT=y -CONFIG_ARM_ZYNQ_CPUIDLE=y -CONFIG_ATAGS=y -CONFIG_AUTO_ZRELADDR=y -# CONFIG_AXI_DMAC is not set -CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK=y -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=16384 -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_PM=y -CONFIG_BOUNCE=y -CONFIG_CACHE_L2X0=y -CONFIG_CADENCE_TTC_TIMER=y -CONFIG_CADENCE_WATCHDOG=y -CONFIG_CC_HAVE_STACKPROTECTOR_TLS=y -CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5" -CONFIG_CC_NO_ARRAY_BOUNDS=y -CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK=y -CONFIG_CLKSRC_MMIO=y -CONFIG_CLKSRC_VERSATILE=y -CONFIG_CLK_ICST=y -CONFIG_CLK_SP810=y -CONFIG_CLK_VEXPRESS_OSC=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_CMA=y -CONFIG_CMA_ALIGNMENT=8 -CONFIG_CMA_AREAS=7 -# CONFIG_CMA_DEBUG is not set -# CONFIG_CMA_DEBUGFS is not set -CONFIG_CMA_SIZE_MBYTES=16 -# CONFIG_CMA_SIZE_SEL_MAX is not set -CONFIG_CMA_SIZE_SEL_MBYTES=y -# CONFIG_CMA_SIZE_SEL_MIN is not set -# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set -# CONFIG_CMA_SYSFS is not set -CONFIG_COMMON_CLK=y -CONFIG_COMMON_CLK_SI570=y -CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_CONNECTOR=y -CONFIG_CONSOLE_TRANSLATIONS=y -CONFIG_CONTEXT_TRACKING=y -CONFIG_CONTEXT_TRACKING_IDLE=y -CONFIG_CONTIG_ALLOC=y -CONFIG_COREDUMP=y -# CONFIG_CPUFREQ_DT is not set -CONFIG_CPU_32v6K=y -CONFIG_CPU_32v7=y -CONFIG_CPU_ABRT_EV7=y -CONFIG_CPU_CACHE_V7=y -CONFIG_CPU_CACHE_VIPT=y -CONFIG_CPU_COPY_V6=y -CONFIG_CPU_CP15=y -CONFIG_CPU_CP15_MMU=y -CONFIG_CPU_FREQ=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y -CONFIG_CPU_FREQ_GOV_ATTR_SET=y -CONFIG_CPU_FREQ_GOV_COMMON=y -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -CONFIG_CPU_FREQ_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_CPU_FREQ_STAT=y -CONFIG_CPU_HAS_ASID=y -CONFIG_CPU_IDLE=y -CONFIG_CPU_IDLE_GOV_LADDER=y -CONFIG_CPU_IDLE_GOV_MENU=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_CPU_PABRT_V7=y -CONFIG_CPU_PM=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_SPECTRE=y -CONFIG_CPU_THERMAL=y -CONFIG_CPU_THUMB_CAPABLE=y -CONFIG_CPU_TLB_V7=y -CONFIG_CPU_V7=y -CONFIG_CRC16=y -# CONFIG_CRC32_SARWATE is not set -CONFIG_CRC32_SLICEBY8=y -CONFIG_CROSS_MEMORY_ATTACH=y -CONFIG_CRYPTO_CRC32=y -CONFIG_CRYPTO_CRC32C=y -CONFIG_CRYPTO_HW=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_SHA1=y -CONFIG_CRYPTO_LIB_UTILS=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CURRENT_POINTER_IN_TPIDRURO=y -CONFIG_DCACHE_WORD_ACCESS=y -CONFIG_DEBUG_INFO=y -CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" -CONFIG_DMADEVICES=y -CONFIG_DMA_CMA=y -CONFIG_DMA_ENGINE=y -CONFIG_DMA_OF=y -CONFIG_DMA_OPS=y -CONFIG_DMA_SHARED_BUFFER=y -CONFIG_DRM=y -CONFIG_DRM_BRIDGE=y -CONFIG_DRM_NOMODESET=y -CONFIG_DRM_PANEL=y -CONFIG_DRM_PANEL_BRIDGE=y -CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y -CONFIG_DTC=y -CONFIG_DUMMY_CONSOLE=y -CONFIG_E1000E=y -CONFIG_EDAC=y -CONFIG_EDAC_ATOMIC_SCRUB=y -# CONFIG_EDAC_DEBUG is not set -CONFIG_EDAC_LEGACY_SYSFS=y -CONFIG_EDAC_SUPPORT=y -# CONFIG_EDAC_SYNOPSYS is not set -CONFIG_EEPROM_AT24=y -CONFIG_EEPROM_AT25=y -CONFIG_ELF_CORE=y -CONFIG_EXCLUSIVE_SYSTEM_RAM=y -CONFIG_EXT4_FS=y -CONFIG_EXTCON=y -CONFIG_F2FS_FS=y -CONFIG_FB=y -CONFIG_FB_CMDLINE=y -# CONFIG_FB_XILINX is not set -CONFIG_FHANDLE=y -CONFIG_FIXED_PHY=y -CONFIG_FIX_EARLYCON_MEM=y -CONFIG_FPGA=y -CONFIG_FPGA_BRIDGE=y -# CONFIG_FPGA_DFL is not set -# CONFIG_FPGA_MGR_ALTERA_CVP is not set -# CONFIG_FPGA_MGR_ALTERA_PS_SPI is not set -# CONFIG_FPGA_MGR_ICE40_SPI is not set -# CONFIG_FPGA_MGR_MACHXO2_SPI is not set -# CONFIG_FPGA_MGR_MICROCHIP_SPI is not set -# CONFIG_FPGA_MGR_XILINX_SPI is not set -CONFIG_FPGA_MGR_ZYNQ_FPGA=y -CONFIG_FPGA_REGION=y -CONFIG_FREEZER=y -CONFIG_FS_IOMAP=y -CONFIG_FS_MBCACHE=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_CACHE=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_FW_LOADER_SYSFS=y -CONFIG_GCC10_NO_ARRAY_BOUNDS=y -CONFIG_GCC_ASM_GOTO_OUTPUT_WORKAROUND=y -CONFIG_GENERIC_ALLOCATOR=y -CONFIG_GENERIC_ARCH_TOPOLOGY=y -CONFIG_GENERIC_BUG=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_CPU_VULNERABILITIES=y -CONFIG_GENERIC_EARLY_IOREMAP=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IDLE_POLL_SETUP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_MIGRATION=y -CONFIG_GENERIC_IRQ_MULTI_HANDLER=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_IRQ_SHOW_LEVEL=y -CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y -CONFIG_GENERIC_MSI_IRQ=y -CONFIG_GENERIC_MSI_IRQ_DOMAIN=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_STRNCPY_FROM_USER=y -CONFIG_GENERIC_STRNLEN_USER=y -CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_GENERIC_VDSO_32=y -CONFIG_GLOB=y -CONFIG_GPIOLIB_IRQCHIP=y -CONFIG_GPIO_CDEV=y -CONFIG_GPIO_GENERIC=y -CONFIG_GPIO_GENERIC_PLATFORM=y -CONFIG_GPIO_ZYNQ=y -CONFIG_HARDEN_BRANCH_PREDICTOR=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAVE_SMP=y -CONFIG_HDMI=y -CONFIG_HID=y -CONFIG_HID_GENERIC=y -CONFIG_HID_MICROSOFT=y -CONFIG_HIGHMEM=y -CONFIG_HIGHPTE=y -CONFIG_HOTPLUG_CPU=y -CONFIG_HWMON=y -CONFIG_HW_CONSOLE=y -CONFIG_HZ_FIXED=0 -CONFIG_I2C=y -CONFIG_I2C_ALGOBIT=y -CONFIG_I2C_BOARDINFO=y -CONFIG_I2C_CADENCE=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_COMPAT=y -CONFIG_I2C_HELPER_AUTO=y -CONFIG_I2C_MUX=y -CONFIG_I2C_MUX_PCA954x=y -CONFIG_IIO=y -CONFIG_IIO_BUFFER=y -CONFIG_IIO_KFIFO_BUF=y -CONFIG_IIO_TRIGGER=y -CONFIG_IIO_TRIGGERED_BUFFER=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_INPUT=y -CONFIG_INPUT_EVDEV=y -CONFIG_INPUT_FF_MEMLESS=y -CONFIG_INPUT_KEYBOARD=y -CONFIG_INPUT_MOUSE=y -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_SPARSEKMAP=y -CONFIG_INPUT_VIVALDIFMAP=y -# CONFIG_IOMMU_DEBUGFS is not set -# CONFIG_IOMMU_IO_PGTABLE_ARMV7S is not set -# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set -CONFIG_IOMMU_SUPPORT=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_BOOTP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_RARP=y -CONFIG_IRQCHIP=y -CONFIG_IRQSTACKS=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_DOMAIN_HIERARCHY=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_WORK=y -# CONFIG_ISDN is not set -CONFIG_JBD2=y -# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set -CONFIG_JFFS2_ZLIB=y -CONFIG_KCMP=y -CONFIG_KERNEL_GZIP=y -# CONFIG_KERNEL_XZ is not set -CONFIG_KEYBOARD_ATKBD=y -CONFIG_KEYBOARD_GPIO=y -CONFIG_KEYBOARD_GPIO_POLLED=y -CONFIG_KMAP_LOCAL=y -CONFIG_KMAP_LOCAL_NON_LINEAR_PTE_ARRAY=y -CONFIG_LEDS_GPIO=y -CONFIG_LEDS_TRIGGER_BACKLIGHT=y -CONFIG_LEDS_TRIGGER_CAMERA=y -CONFIG_LEDS_TRIGGER_CPU=y -CONFIG_LEDS_TRIGGER_GPIO=y -CONFIG_LEDS_TRIGGER_ONESHOT=y -CONFIG_LEDS_TRIGGER_TRANSIENT=y -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LOCK_SPIN_ON_OWNER=y -CONFIG_MACB=y -# CONFIG_MACB_PCI is not set -CONFIG_MACB_USE_HWSTAMP=y -CONFIG_MARVELL_PHY=y -CONFIG_MDIO_BITBANG=y -CONFIG_MDIO_BUS=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -# CONFIG_MDIO_GPIO is not set -CONFIG_MEMFD_CREATE=y -CONFIG_MEMORY=y -CONFIG_MEMORY_ISOLATION=y -CONFIG_MFD_CORE=y -CONFIG_MFD_SYSCON=y -CONFIG_MFD_VEXPRESS_SYSREG=y -CONFIG_MIGHT_HAVE_CACHE_L2X0=y -CONFIG_MIGRATION=y -CONFIG_MMC=y -CONFIG_MMC_BLOCK=y -CONFIG_MMC_CQHCI=y -CONFIG_MMC_SDHCI=y -CONFIG_MMC_SDHCI_OF_ARASAN=y -# CONFIG_MMC_SDHCI_PCI is not set -CONFIG_MMC_SDHCI_PLTFM=y -CONFIG_MODULES_USE_ELF_REL=y -CONFIG_MODULE_FORCE_UNLOAD=y -# CONFIG_MODULE_STRIPPED is not set -# CONFIG_MOUSE_BCM5974 is not set -# CONFIG_MOUSE_CYAPA is not set -CONFIG_MOUSE_PS2=y -CONFIG_MOUSE_PS2_ALPS=y -CONFIG_MOUSE_PS2_BYD=y -CONFIG_MOUSE_PS2_CYPRESS=y -# CONFIG_MOUSE_PS2_ELANTECH is not set -CONFIG_MOUSE_PS2_FOCALTECH=y -CONFIG_MOUSE_PS2_LOGIPS2PP=y -CONFIG_MOUSE_PS2_SMBUS=y -CONFIG_MOUSE_PS2_SYNAPTICS=y -CONFIG_MOUSE_PS2_SYNAPTICS_SMBUS=y -# CONFIG_MOUSE_PS2_TOUCHKIT is not set -CONFIG_MOUSE_PS2_TRACKPOINT=y -# CONFIG_MOUSE_SERIAL is not set -# CONFIG_MOUSE_VSXXXAA is not set -# CONFIG_MTD_CFI_INTELEXT is not set -CONFIG_MTD_CMDLINE_PARTS=y -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y -CONFIG_MTD_SPLIT_FIRMWARE=y -# CONFIG_MTD_SPLIT_SQUASHFS_ROOT is not set -CONFIG_MUTEX_SPIN_ON_OWNER=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NEON=y -CONFIG_NET_FLOW_LIMIT=y -CONFIG_NET_PTP_CLASSIFY=y -CONFIG_NET_SELFTESTS=y -# CONFIG_NET_VENDOR_CIRRUS is not set -# CONFIG_NET_VENDOR_FARADAY is not set -# CONFIG_NET_VENDOR_MARVELL is not set -# CONFIG_NET_VENDOR_MICREL is not set -# CONFIG_NET_VENDOR_MICROCHIP is not set -# CONFIG_NET_VENDOR_NATSEMI is not set -# CONFIG_NET_VENDOR_SEEQ is not set -# CONFIG_NET_VENDOR_SMSC is not set -# CONFIG_NET_VENDOR_STMICRO is not set -# CONFIG_NET_VENDOR_VIA is not set -CONFIG_NLS=y -CONFIG_NLS_ASCII=y -CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_ISO8859_1=y -CONFIG_NOP_USB_XCEIV=y -CONFIG_NO_HZ=y -CONFIG_NO_HZ_COMMON=y -CONFIG_NO_HZ_IDLE=y -CONFIG_NO_IOPORT_MAP=y -CONFIG_NR_CPUS=4 -CONFIG_NVMEM=y -CONFIG_NVMEM_LAYOUTS=y -CONFIG_NVMEM_SYSFS=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -# CONFIG_OF_FPGA_REGION is not set -CONFIG_OF_GPIO=y -CONFIG_OF_IRQ=y -CONFIG_OF_KOBJ=y -CONFIG_OF_MDIO=y -CONFIG_OLD_SIGACTION=y -CONFIG_OLD_SIGSUSPEND3=y -CONFIG_OUTER_CACHE=y -CONFIG_OUTER_CACHE_SYNC=y -CONFIG_PADATA=y -CONFIG_PAGE_OFFSET=0xC0000000 -CONFIG_PAGE_POOL=y -CONFIG_PAGE_SIZE_LESS_THAN_256KB=y -CONFIG_PAGE_SIZE_LESS_THAN_64KB=y -CONFIG_PAHOLE_HAS_LANG_EXCLUDE=y -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_PCI=y -CONFIG_PCIE_XILINX=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DOMAINS_GENERIC=y -CONFIG_PCI_MSI=y -CONFIG_PCI_MSI_IRQ_DOMAIN=y -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PGTABLE_LEVELS=2 -CONFIG_PHYLIB=y -CONFIG_PHYLIB_LEDS=y -CONFIG_PHYLINK=y -CONFIG_PINCTRL=y -# CONFIG_PINCTRL_SINGLE is not set -CONFIG_PINCTRL_ZYNQ=y -CONFIG_PL310_ERRATA_588369=y -CONFIG_PL310_ERRATA_727915=y -CONFIG_PL310_ERRATA_753970=y -CONFIG_PL310_ERRATA_769419=y -CONFIG_PL330_DMA=y -# CONFIG_PL353_SMC is not set -CONFIG_PLAT_VERSATILE=y -CONFIG_PM=y -CONFIG_PMBUS=y -CONFIG_PM_CLK=y -CONFIG_PM_SLEEP=y -CONFIG_PM_SLEEP_SMP=y -CONFIG_POWER_RESET=y -CONFIG_POWER_RESET_VEXPRESS=y -CONFIG_POWER_SUPPLY=y -CONFIG_PPS=y -CONFIG_PREEMPT_NONE_BUILD=y -CONFIG_PROC_EVENTS=y -CONFIG_PTP_1588_CLOCK=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_R8169=y -CONFIG_RANDSTRUCT_NONE=y -CONFIG_RAS=y -CONFIG_RATIONAL=y -CONFIG_REALTEK_PHY=y -CONFIG_REGMAP=y -CONFIG_REGMAP_I2C=y -CONFIG_REGMAP_MMIO=y -CONFIG_REGULATOR=y -CONFIG_REGULATOR_FIXED_VOLTAGE=y -# CONFIG_REGULATOR_VEXPRESS is not set -CONFIG_RESET_CONTROLLER=y -CONFIG_RESET_ZYNQ=y -CONFIG_RFS_ACCEL=y -CONFIG_RPS=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_PCF8563=y -CONFIG_RTC_I2C_AND_SPI=y -CONFIG_RTC_MC146818_LIB=y -CONFIG_RWSEM_SPIN_ON_OWNER=y -# CONFIG_SCHED_CORE is not set -CONFIG_SCHED_MC=y -CONFIG_SCHED_SMT=y -CONFIG_SENSORS_PMBUS=y -CONFIG_SENSORS_UCD9000=y -CONFIG_SENSORS_UCD9200=y -# CONFIG_SERIAL_8250 is not set -CONFIG_SERIAL_XILINX_PS_UART=y -CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y -CONFIG_SERIO=y -CONFIG_SERIO_LIBPS2=y -CONFIG_SERIO_SERPORT=y -CONFIG_SMP=y -CONFIG_SMP_ON_UP=y -CONFIG_SOCK_RX_QUEUE_MAPPING=y -CONFIG_SOC_BUS=y -CONFIG_SOFTIRQ_ON_OWN_STACK=y -CONFIG_SPARSE_IRQ=y -CONFIG_SPI=y -CONFIG_SPI_BITBANG=y -CONFIG_SPI_CADENCE=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -CONFIG_SPI_XILINX=y -CONFIG_SPI_ZYNQ_QSPI=y -CONFIG_SRAM=y -CONFIG_SRAM_EXEC=y -CONFIG_SRCU=y -# CONFIG_STRIP_ASM_SYMS is not set -CONFIG_SUSPEND=y -CONFIG_SUSPEND_FREEZER=y -CONFIG_SWPHY=y -CONFIG_SWP_EMULATE=y -CONFIG_SYNC_FILE=y -CONFIG_SYSFS_SYSCALL=y -CONFIG_SYS_SUPPORTS_APM_EMULATION=y -# CONFIG_TEXTSEARCH is not set -CONFIG_THERMAL=y -CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y -CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 -CONFIG_THERMAL_GOV_STEP_WISE=y -CONFIG_THERMAL_HWMON=y -CONFIG_THERMAL_OF=y -CONFIG_THREAD_INFO_IN_TASK=y -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TIMER_OF=y -CONFIG_TIMER_PROBE=y -CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y -CONFIG_UIO=y -# CONFIG_UIO_AEC is not set -# CONFIG_UIO_CIF is not set -# CONFIG_UIO_DMEM_GENIRQ is not set -# CONFIG_UIO_MF624 is not set -# CONFIG_UIO_NETX is not set -# CONFIG_UIO_PCI_GENERIC is not set -CONFIG_UIO_PDRV_GENIRQ=y -# CONFIG_UIO_PRUSS is not set -# CONFIG_UIO_SERCOS3 is not set -CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" -CONFIG_UNWINDER_ARM=y -CONFIG_USB=y -CONFIG_USB_CHIPIDEA=y -CONFIG_USB_CHIPIDEA_HOST=y -CONFIG_USB_CHIPIDEA_UDC=y -CONFIG_USB_COMMON=y -CONFIG_USB_EHCI_HCD=y -# CONFIG_USB_EHCI_HCD_PLATFORM is not set -# CONFIG_USB_EHCI_TT_NEWSCHED is not set -CONFIG_USB_GADGET=y -CONFIG_USB_GADGET_XILINX=y -CONFIG_USB_HID=y -CONFIG_USB_NET_DRIVERS=y -CONFIG_USB_OTG=y -CONFIG_USB_OTG_FSM=y -CONFIG_USB_PHY=y -CONFIG_USB_ROLE_SWITCH=y -CONFIG_USB_SUPPORT=y -CONFIG_USB_ULPI=y -CONFIG_USB_ULPI_BUS=y -CONFIG_USB_ULPI_VIEWPORT=y -CONFIG_USE_OF=y -CONFIG_VEXPRESS_CONFIG=y -CONFIG_VFP=y -CONFIG_VFPv3=y -CONFIG_VGA_ARB=y -CONFIG_VGA_ARB_MAX_GPUS=16 -CONFIG_VITESSE_PHY=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_VT_CONSOLE_SLEEP=y -# CONFIG_VT_HW_CONSOLE_BINDING is not set -CONFIG_WATCHDOG_CORE=y -# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set -CONFIG_XILINX_EMACLITE=y -# CONFIG_XILINX_PR_DECOUPLER is not set -CONFIG_XILINX_WATCHDOG=y -CONFIG_XILINX_XADC=y -CONFIG_XPS=y -CONFIG_XZ_DEC_ARM=y -CONFIG_XZ_DEC_ARMTHUMB=y -CONFIG_XZ_DEC_BCJ=y -CONFIG_XZ_DEC_IA64=y -CONFIG_XZ_DEC_POWERPC=y -CONFIG_XZ_DEC_SPARC=y -CONFIG_XZ_DEC_X86=y -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZLIB_DEFLATE=y -CONFIG_ZLIB_INFLATE=y diff --git a/target/linux/zynq/image/Makefile b/target/linux/zynq/image/Makefile index 50301cf2a8..4a9c2f047d 100644 --- a/target/linux/zynq/image/Makefile +++ b/target/linux/zynq/image/Makefile @@ -29,9 +29,7 @@ endef define Device/Default PROFILES := Default -ifdef CONFIG_LINUX_6_6 DTS_DIR := $(DTS_DIR)/xilinx -endif DEVICE_DTS := $(lastword $(subst _, ,$(1))) KERNEL_DEPENDS = $$(wildcard $(DTS_DIR)/$$(DEVICE_DTS).dts) KERNEL_LOADADDR := 0x8000