From d3d3a2d645502e69874531fc45b0e866f2230c1a Mon Sep 17 00:00:00 2001 From: Josef Schlehofer <josef.schlehofer@nic.cz> Date: Mon, 25 Jul 2022 16:33:07 +0200 Subject: [PATCH] patches/openwrt/5.15: backport OpenWrt patches for mvebu --- .../0016-Add-OpenWrt-patches-for-mvebu.patch | 4630 +++++++++++++++++ 1 file changed, 4630 insertions(+) create mode 100644 patches/openwrt/5.15-kernel-configuration/0016-Add-OpenWrt-patches-for-mvebu.patch diff --git a/patches/openwrt/5.15-kernel-configuration/0016-Add-OpenWrt-patches-for-mvebu.patch b/patches/openwrt/5.15-kernel-configuration/0016-Add-OpenWrt-patches-for-mvebu.patch new file mode 100644 index 000000000..8b782aeec --- /dev/null +++ b/patches/openwrt/5.15-kernel-configuration/0016-Add-OpenWrt-patches-for-mvebu.patch @@ -0,0 +1,4630 @@ +From 5be155a8a411e9086432ebdbfbaa8957abb2d51e Mon Sep 17 00:00:00 2001 +From: Josef Schlehofer <pepe.schlehofer@gmail.com> +Date: Mon, 25 Jul 2022 16:32:14 +0200 +Subject: [PATCH] Add OpenWrt patches for mvebu + +--- + ...Mangle-bootloader-s-kernel-arguments.patch | 208 ++++ + ...-mvebu-armada-38x-enable-libata-leds.patch | 10 + + .../patches-5.15/302-add_powertables.patch | 770 ++++++++++++ + .../patches-5.15/304-revert_i2c_delay.patch | 15 + + .../305-armada-385-rd-mtd-partitions.patch | 19 + + .../306-ARM-mvebu-385-ap-Add-partitions.patch | 35 + + ...-armada-xp-linksys-mamba-broken-idle.patch | 10 + + .../308-armada-xp-linksys-mamba-wan.patch | 11 + + .../patches-5.15/309-linksys-status-led.patch | 50 + + .../310-linksys-use-eth0-as-cpu-port.patch | 25 + + .../311-adjust-compatible-for-linksys.patch | 68 ++ + ...da388-clearfog-emmc-on-clearfog-base.patch | 87 ++ + .../313-helios4-dts-status-led-alias.patch | 28 + + ...rmada-xp-linksys-mamba-resize-kernel.patch | 37 + + ...316-armada-370-dts-fix-crypto-engine.patch | 29 + + .../patches-5.15/400-find_active_root.patch | 60 + + .../700-mvneta-tx-queue-workaround.patch | 38 + + ...ethernet-marvell-mvnetaMQPrioOffload.patch | 66 ++ + ...xt-ethernet-marvell-mvnetaMQPrioFlag.patch | 30 + + ...t-ethernet-marvell-mvnetaMQPrioQueue.patch | 97 ++ + ...hernet-marvell-mvnetaMQPrioTCOffload.patch | 182 +++ + ...dicate-failure-to-enter-deeper-sleep.patch | 40 + + ...-pci-mvebu-time-out-reset-on-link-up.patch | 60 + + ...IEI-vendor-prefix-and-IEI-WT61P803-P.patch | 218 ++++ + ...a-driver-for-IEI-WT61P803-PUZZLE-MCU.patch | 1034 +++++++++++++++++ + ...d-the-IEI-WT61P803-PUZZLE-HWMON-driv.patch | 469 ++++++++ + ...d-the-IEI-WT61P803-PUZZLE-LED-driver.patch | 207 ++++ + ...I-Add-iei-wt61p803-puzzle-driver-sys.patch | 82 ++ + ...mon-Add-iei-wt61p803-puzzle-hwmon-dr.patch | 74 ++ + ...an-entry-for-the-IEI-WT61P803-PUZZLE.patch | 41 + + ...rs-leds-wt61p803-puzzle-improvements.patch | 271 +++++ + 31 files changed, 4371 insertions(+) + create mode 100644 target/linux/mvebu/patches-5.15/300-mvebu-Mangle-bootloader-s-kernel-arguments.patch + create mode 100644 target/linux/mvebu/patches-5.15/301-mvebu-armada-38x-enable-libata-leds.patch + create mode 100644 target/linux/mvebu/patches-5.15/302-add_powertables.patch + create mode 100644 target/linux/mvebu/patches-5.15/304-revert_i2c_delay.patch + create mode 100644 target/linux/mvebu/patches-5.15/305-armada-385-rd-mtd-partitions.patch + create mode 100644 target/linux/mvebu/patches-5.15/306-ARM-mvebu-385-ap-Add-partitions.patch + create mode 100644 target/linux/mvebu/patches-5.15/307-armada-xp-linksys-mamba-broken-idle.patch + create mode 100644 target/linux/mvebu/patches-5.15/308-armada-xp-linksys-mamba-wan.patch + create mode 100644 target/linux/mvebu/patches-5.15/309-linksys-status-led.patch + create mode 100644 target/linux/mvebu/patches-5.15/310-linksys-use-eth0-as-cpu-port.patch + create mode 100644 target/linux/mvebu/patches-5.15/311-adjust-compatible-for-linksys.patch + create mode 100644 target/linux/mvebu/patches-5.15/312-ARM-dts-armada388-clearfog-emmc-on-clearfog-base.patch + create mode 100644 target/linux/mvebu/patches-5.15/313-helios4-dts-status-led-alias.patch + create mode 100644 target/linux/mvebu/patches-5.15/315-armada-xp-linksys-mamba-resize-kernel.patch + create mode 100644 target/linux/mvebu/patches-5.15/316-armada-370-dts-fix-crypto-engine.patch + create mode 100644 target/linux/mvebu/patches-5.15/400-find_active_root.patch + create mode 100644 target/linux/mvebu/patches-5.15/700-mvneta-tx-queue-workaround.patch + create mode 100644 target/linux/mvebu/patches-5.15/702-net-next-ethernet-marvell-mvnetaMQPrioOffload.patch + create mode 100644 target/linux/mvebu/patches-5.15/703-net-next-ethernet-marvell-mvnetaMQPrioFlag.patch + create mode 100644 target/linux/mvebu/patches-5.15/704-net-next-ethernet-marvell-mvnetaMQPrioQueue.patch + create mode 100644 target/linux/mvebu/patches-5.15/705-net-next-ethernet-marvell-mvnetaMQPrioTCOffload.patch + create mode 100644 target/linux/mvebu/patches-5.15/800-cpuidle-mvebu-indicate-failure-to-enter-deeper-sleep.patch + create mode 100644 target/linux/mvebu/patches-5.15/801-pci-mvebu-time-out-reset-on-link-up.patch + create mode 100644 target/linux/mvebu/patches-5.15/901-dt-bindings-Add-IEI-vendor-prefix-and-IEI-WT61P803-P.patch + create mode 100644 target/linux/mvebu/patches-5.15/902-drivers-mfd-Add-a-driver-for-IEI-WT61P803-PUZZLE-MCU.patch + create mode 100644 target/linux/mvebu/patches-5.15/903-drivers-hwmon-Add-the-IEI-WT61P803-PUZZLE-HWMON-driv.patch + create mode 100644 target/linux/mvebu/patches-5.15/904-drivers-leds-Add-the-IEI-WT61P803-PUZZLE-LED-driver.patch + create mode 100644 target/linux/mvebu/patches-5.15/905-Documentation-ABI-Add-iei-wt61p803-puzzle-driver-sys.patch + create mode 100644 target/linux/mvebu/patches-5.15/906-Documentation-hwmon-Add-iei-wt61p803-puzzle-hwmon-dr.patch + create mode 100644 target/linux/mvebu/patches-5.15/907-MAINTAINERS-Add-an-entry-for-the-IEI-WT61P803-PUZZLE.patch + create mode 100644 target/linux/mvebu/patches-5.15/910-drivers-leds-wt61p803-puzzle-improvements.patch + +diff --git a/target/linux/mvebu/patches-5.15/300-mvebu-Mangle-bootloader-s-kernel-arguments.patch b/target/linux/mvebu/patches-5.15/300-mvebu-Mangle-bootloader-s-kernel-arguments.patch +new file mode 100644 +index 0000000000..071ea6742d +--- /dev/null ++++ b/target/linux/mvebu/patches-5.15/300-mvebu-Mangle-bootloader-s-kernel-arguments.patch +@@ -0,0 +1,208 @@ ++From 71270226b14733a4b1f2cde58ea9265caa50b38d Mon Sep 17 00:00:00 2001 ++From: Adrian Panella <ianchi74@outlook.com> ++Date: Thu, 9 Mar 2017 09:37:17 +0100 ++Subject: [PATCH 67/69] generic: Mangle bootloader's kernel arguments ++ ++The command-line arguments provided by the boot loader will be ++appended to a new device tree property: bootloader-args. ++If there is a property "append-rootblock" in DT under /chosen ++and a root= option in bootloaders command line it will be parsed ++and added to DT bootargs with the form: <append-rootblock>XX. ++Only command line ATAG will be processed, the rest of the ATAGs ++sent by bootloader will be ignored. ++This is usefull in dual boot systems, to get the current root partition ++without afecting the rest of the system. ++ ++Signed-off-by: Adrian Panella <ianchi74@outlook.com> ++ ++This patch has been modified to be mvebu specific. The original patch ++did not pass the bootloader cmdline on if no append-rootblock stanza ++was found, resulting in blank cmdline and failure to boot. ++ ++Signed-off-by: Michael Gray <michael.gray@lantisproject.com> ++--- ++ arch/arm/Kconfig | 11 ++++ ++ arch/arm/boot/compressed/atags_to_fdt.c | 85 ++++++++++++++++++++++++- ++ init/main.c | 16 +++++ ++ 3 files changed, 111 insertions(+), 1 deletion(-) ++ ++--- a/arch/arm/Kconfig +++++ b/arch/arm/Kconfig ++@@ -1727,6 +1727,17 @@ config ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEN ++ The command-line arguments provided by the boot loader will be ++ appended to the the device tree bootargs property. ++ +++config ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE +++ bool "Append rootblock parsing bootloader's kernel arguments" +++ help +++ The command-line arguments provided by the boot loader will be +++ appended to a new device tree property: bootloader-args. +++ If there is a property "append-rootblock" in DT under /chosen +++ and a root= option in bootloaders command line it will be parsed +++ and added to DT bootargs with the form: <append-rootblock>XX. +++ Only command line ATAG will be processed, the rest of the ATAGs +++ sent by bootloader will be ignored. +++ ++ endchoice ++ ++ config CMDLINE ++--- a/arch/arm/boot/compressed/atags_to_fdt.c +++++ b/arch/arm/boot/compressed/atags_to_fdt.c ++@@ -5,6 +5,8 @@ ++ ++ #if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND) ++ #define do_extend_cmdline 1 +++#elif defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) +++#define do_extend_cmdline 1 ++ #else ++ #define do_extend_cmdline 0 ++ #endif ++@@ -69,6 +71,72 @@ static uint32_t get_cell_size(const void ++ return cell_size; ++ } ++ +++#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) +++ +++static char *append_rootblock(char *dest, const char *str, int len, void *fdt) +++{ +++ char *ptr, *end; +++ char *root="root="; +++ int i, l; +++ const char *rootblock; +++ +++ //ARM doesn't have __HAVE_ARCH_STRSTR, so search manually +++ ptr = str - 1; +++ +++ do { +++ //first find an 'r' at the begining or after a space +++ do { +++ ptr++; +++ ptr = strchr(ptr, 'r'); +++ if (!ptr) +++ goto no_append; +++ +++ } while (ptr != str && *(ptr-1) != ' '); +++ +++ //then check for the rest +++ for(i = 1; i <= 4; i++) +++ if(*(ptr+i) != *(root+i)) break; +++ +++ } while (i != 5); +++ +++ end = strchr(ptr, ' '); +++ end = end ? (end - 1) : (strchr(ptr, 0) - 1); +++ +++ //find partition number (assumes format root=/dev/mtdXX | /dev/mtdblockXX | yy:XX ) +++ for( i = 0; end >= ptr && *end >= '0' && *end <= '9'; end--, i++); +++ ptr = end + 1; +++ +++ /* if append-rootblock property is set use it to append to command line */ +++ rootblock = getprop(fdt, "/chosen", "append-rootblock", &l); +++ if (rootblock == NULL) +++ goto no_append; +++ +++ if (*dest != ' ') { +++ *dest = ' '; +++ dest++; +++ len++; +++ } +++ +++ if (len + l + i <= COMMAND_LINE_SIZE) { +++ memcpy(dest, rootblock, l); +++ dest += l - 1; +++ memcpy(dest, ptr, i); +++ dest += i; +++ } +++ +++ return dest; +++ +++no_append: +++ len = strlen(str); +++ if (len + 1 < COMMAND_LINE_SIZE) { +++ memcpy(dest, str, len); +++ dest += len; +++ } +++ +++ return dest; +++} +++#endif +++ ++ static void merge_fdt_bootargs(void *fdt, const char *fdt_cmdline) ++ { ++ char cmdline[COMMAND_LINE_SIZE]; ++@@ -88,12 +156,21 @@ static void merge_fdt_bootargs(void *fdt ++ ++ /* and append the ATAG_CMDLINE */ ++ if (fdt_cmdline) { +++ +++#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) +++ //save original bootloader args +++ //and append ubi.mtd with root partition number to current cmdline +++ setprop_string(fdt, "/chosen", "bootloader-args", fdt_cmdline); +++ ptr = append_rootblock(ptr, fdt_cmdline, len, fdt); +++ +++#else ++ len = strlen(fdt_cmdline); ++ if (ptr - cmdline + len + 2 < COMMAND_LINE_SIZE) { ++ *ptr++ = ' '; ++ memcpy(ptr, fdt_cmdline, len); ++ ptr += len; ++ } +++#endif ++ } ++ *ptr = '\0'; ++ ++@@ -168,7 +245,9 @@ int atags_to_fdt(void *atag_list, void * ++ else ++ setprop_string(fdt, "/chosen", "bootargs", ++ atag->u.cmdline.cmdline); ++- } else if (atag->hdr.tag == ATAG_MEM) { +++ } +++#ifndef CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE +++ else if (atag->hdr.tag == ATAG_MEM) { ++ if (memcount >= sizeof(mem_reg_property)/4) ++ continue; ++ if (!atag->u.mem.size) ++@@ -212,6 +291,10 @@ int atags_to_fdt(void *atag_list, void * ++ setprop(fdt, "/memory", "reg", mem_reg_property, ++ 4 * memcount * memsize); ++ } +++#else +++ +++ } +++#endif ++ ++ return fdt_pack(fdt); ++ } ++--- a/init/main.c +++++ b/init/main.c ++@@ -113,6 +113,10 @@ ++ ++ #include <kunit/test.h> ++ +++#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) +++#include <linux/of.h> +++#endif +++ ++ static int kernel_init(void *); ++ ++ extern void init_IRQ(void); ++@@ -990,6 +994,18 @@ asmlinkage __visible void __init __no_sa ++ page_alloc_init(); ++ ++ pr_notice("Kernel command line: %s\n", saved_command_line); +++ +++#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) +++ //Show bootloader's original command line for reference +++ if(of_chosen) { +++ const char *prop = of_get_property(of_chosen, "bootloader-args", NULL); +++ if(prop) +++ pr_notice("Bootloader command line (ignored): %s\n", prop); +++ else +++ pr_notice("Bootloader command line not present\n"); +++ } +++#endif +++ ++ /* parameters may set static keys */ ++ jump_label_init(); ++ parse_early_param(); +diff --git a/target/linux/mvebu/patches-5.15/301-mvebu-armada-38x-enable-libata-leds.patch b/target/linux/mvebu/patches-5.15/301-mvebu-armada-38x-enable-libata-leds.patch +new file mode 100644 +index 0000000000..615caac24f +--- /dev/null ++++ b/target/linux/mvebu/patches-5.15/301-mvebu-armada-38x-enable-libata-leds.patch +@@ -0,0 +1,10 @@ ++--- a/arch/arm/mach-mvebu/Kconfig +++++ b/arch/arm/mach-mvebu/Kconfig ++@@ -67,6 +67,7 @@ config MACH_ARMADA_38X ++ select HAVE_ARM_TWD if SMP ++ select MACH_MVEBU_V7 ++ select PINCTRL_ARMADA_38X +++ select ARCH_WANT_LIBATA_LEDS ++ help ++ Say 'Y' here if you want your kernel to support boards based ++ on the Marvell Armada 380/385 SoC with device tree. +diff --git a/target/linux/mvebu/patches-5.15/302-add_powertables.patch b/target/linux/mvebu/patches-5.15/302-add_powertables.patch +new file mode 100644 +index 0000000000..93ad5de2cc +--- /dev/null ++++ b/target/linux/mvebu/patches-5.15/302-add_powertables.patch +@@ -0,0 +1,770 @@ ++--- a/arch/arm/boot/dts/armada-385-linksys.dtsi +++++ b/arch/arm/boot/dts/armada-385-linksys.dtsi ++@@ -214,11 +214,19 @@ ++ &pcie1 { ++ /* Marvell 88W8864, 5GHz-only */ ++ status = "okay"; +++ +++ mwlwifi { +++ marvell,2ghz = <0>; +++ }; ++ }; ++ ++ &pcie2 { ++ /* Marvell 88W8864, 2GHz-only */ ++ status = "okay"; +++ +++ mwlwifi { +++ marvell,5ghz = <0>; +++ }; ++ }; ++ ++ &pinctrl { ++--- a/arch/arm/boot/dts/armada-385-linksys-caiman.dts +++++ b/arch/arm/boot/dts/armada-385-linksys-caiman.dts ++@@ -142,3 +142,205 @@ ++ }; ++ }; ++ }; +++ +++&pcie1 { +++ mwlwifi { +++ marvell,chainmask = <2 2>; +++ marvell,powertable { +++ AU = +++ <36 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <40 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <44 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <48 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <52 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <56 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <60 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <64 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <100 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, +++ <104 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, +++ <108 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, +++ <112 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, +++ <116 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, +++ <120 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, +++ <124 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, +++ <128 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, +++ <132 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, +++ <136 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, +++ <140 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, +++ <149 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x1a 0x1a 0x17 0x14 0 0xf>, +++ <153 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x1a 0x1a 0x17 0x14 0 0xf>, +++ <157 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x1a 0x1a 0x17 0x14 0 0xf>, +++ <161 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x1a 0x1a 0x17 0x14 0 0xf>, +++ <165 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x1a 0x1a 0x17 0x14 0 0xf>; +++ CA = +++ <36 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0 0xf>, +++ <40 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0 0xf>, +++ <44 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0 0xf>, +++ <48 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0 0xf>, +++ <52 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <56 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <60 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <64 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <100 0 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <104 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <108 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <112 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <116 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <120 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <124 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <128 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <132 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <136 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <140 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <149 0 0x1a 0x1a 0x18 0x17 0x19 0x19 0x17 0x15 0x18 0x18 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, +++ <153 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, +++ <157 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, +++ <161 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, +++ <165 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>; +++ CN = +++ <36 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <40 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <44 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <48 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <52 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <56 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <60 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <64 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <100 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <104 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <108 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <112 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <116 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <120 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <124 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <128 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <132 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <136 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <140 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <149 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x11 0x11 0x11 0x11 0 0xf>, +++ <153 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0 0xf>, +++ <157 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0 0xf>, +++ <161 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0 0xf>, +++ <165 0 0x15 0x15 0x15 0x15 0x16 0x16 0x16 0x15 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0 0xf>; +++ ETSI = +++ <36 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <40 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <44 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <48 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <52 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <56 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <60 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <64 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <100 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <104 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <108 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <112 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <116 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <120 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <124 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <128 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <132 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <136 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <140 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, +++ <149 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>; +++ FCC = +++ <36 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <40 0 0x19 0x19 0x18 0x17 0x19 0x19 0x17 0x15 0x17 0x17 0x17 0x14 0x10 0x10 0x10 0x10 0 0xf>, +++ <44 0 0x19 0x19 0x18 0x17 0x19 0x19 0x17 0x15 0x17 0x17 0x17 0x14 0x10 0x10 0x10 0x10 0 0xf>, +++ <48 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x17 0x17 0x17 0x14 0x10 0x10 0x10 0x10 0 0xf>, +++ <52 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <56 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <60 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <64 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <100 0 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <104 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <108 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <112 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <116 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <120 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <124 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <128 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <132 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <136 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <140 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <149 0 0x1a 0x1a 0x18 0x17 0x19 0x19 0x17 0x15 0x18 0x18 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, +++ <153 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, +++ <157 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, +++ <161 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, +++ <165 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>; +++ }; +++ }; +++}; +++ +++&pcie2 { +++ mwlwifi { +++ marvell,chainmask = <2 2>; +++ marvell,powertable { +++ AU = +++ <1 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <2 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <3 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <4 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <5 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <6 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <7 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <8 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <9 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <10 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <11 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>; +++ CA = +++ <1 0 0x19 0x14 0x14 0x14 0x13 0x13 0x13 0x13 0x10 0x10 0x10 0x10 0x00 0x00 0x00 0x00 0 0xf>, +++ <2 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, +++ <3 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, +++ <4 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, +++ <5 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, +++ <6 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, +++ <7 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, +++ <8 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, +++ <9 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, +++ <10 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, +++ <11 0 0x19 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x13 0x13 0x13 0x13 0x00 0x00 0x00 0x00 0 0xf>; +++ CN = +++ <1 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <2 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <3 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <4 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <5 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <6 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <7 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <8 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <9 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <10 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <11 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <12 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <13 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <14 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>; +++ ETSI = +++ <1 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <2 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <3 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <4 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <5 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <6 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <7 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <8 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <9 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <10 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <11 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <12 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, +++ <13 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>; +++ FCC = +++ <1 0 0x19 0x14 0x14 0x14 0x13 0x13 0x13 0x13 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, +++ <2 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, +++ <3 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, +++ <4 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, +++ <5 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, +++ <6 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, +++ <7 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, +++ <8 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, +++ <9 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, +++ <10 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, +++ <11 0 0x19 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x13 0x13 0x13 0x13 0x0 0x0 0x0 0x0 0 0xf>; +++ }; +++ }; +++}; ++--- a/arch/arm/boot/dts/armada-385-linksys-cobra.dts +++++ b/arch/arm/boot/dts/armada-385-linksys-cobra.dts ++@@ -142,3 +142,205 @@ ++ }; ++ }; ++ }; +++ +++&pcie1 { +++ mwlwifi { +++ marvell,chainmask = <4 4>; +++ marvell,powertable { +++ AU = +++ <36 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <40 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <44 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <48 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <52 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <56 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <60 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <64 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <100 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <104 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <108 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <112 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <116 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <120 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <124 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <128 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <132 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <136 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <140 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <149 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, +++ <153 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, +++ <157 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, +++ <161 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, +++ <165 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>; +++ CA = +++ <36 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, +++ <40 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, +++ <44 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, +++ <48 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, +++ <52 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <56 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <60 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <64 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <100 0 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <104 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <108 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <112 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <116 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <120 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <124 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <128 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <132 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <136 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <140 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <149 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, +++ <153 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, +++ <157 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, +++ <161 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, +++ <165 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>; +++ CN = +++ <36 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <40 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <44 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <48 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <52 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <56 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <60 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <64 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <100 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <104 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <108 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <112 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <116 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <120 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <124 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <128 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <132 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <136 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <140 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <149 0 0x14 0x14 0x14 0x14 0x13 0x13 0x13 0x13 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <153 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>, +++ <157 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>, +++ <161 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>, +++ <165 0 0x13 0x13 0x13 0x13 0x13 0x13 0x13 0x13 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>; +++ ETSI = +++ <36 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <40 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <44 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <48 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <52 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <56 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <60 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <64 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <100 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <104 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <108 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <112 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <116 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <120 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <124 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <128 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <132 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <136 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <140 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <149 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>; +++ FCC = +++ <36 0 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0 0xf>, +++ <40 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0xf 0xf 0xf 0xf 0 0xf>, +++ <44 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0xf 0xf 0xf 0xf 0 0xf>, +++ <48 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0xf 0xf 0xf 0xf 0 0xf>, +++ <52 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <56 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <60 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <64 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <100 0 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <104 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <108 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <112 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <116 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <120 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <124 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <128 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <132 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <136 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <140 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <149 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, +++ <153 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, +++ <157 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, +++ <161 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, +++ <165 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>; +++ }; +++ }; +++}; +++ +++&pcie2 { +++ mwlwifi { +++ marvell,chainmask = <4 4>; +++ marvell,powertable { +++ AU = +++ <1 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <2 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <3 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <4 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <5 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <6 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <7 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <8 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <9 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <10 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <11 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>; +++ CA = +++ <1 0 0x17 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0xe 0xe 0xe 0xe 0x0 0x0 0x0 0x0 0 0xf>, +++ <2 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <3 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <4 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <5 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <6 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <7 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <8 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <9 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <10 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <11 0 0x17 0x12 0x12 0x12 0x13 0x13 0x13 0x13 0xf 0xf 0xf 0xf 0x0 0x0 0x0 0x0 0 0xf>; +++ CN = +++ <1 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <2 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <3 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <4 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <5 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <6 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <7 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <8 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <9 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <10 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <11 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <12 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <13 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <14 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>; +++ ETSI = +++ <1 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <2 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <3 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <4 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <5 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <6 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <7 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <8 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <9 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <10 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <11 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <12 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <13 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>; +++ FCC = +++ <1 0 0x17 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0xe 0xe 0xe 0xe 0x0 0x0 0x0 0x0 0 0xf>, +++ <2 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <3 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <4 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <5 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <6 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <7 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <8 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <9 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <10 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <11 0 0x17 0x12 0x12 0x12 0x13 0x13 0x13 0x13 0xf 0xf 0xf 0xf 0x0 0x0 0x0 0x0 0 0xf>; +++ }; +++ }; +++}; ++--- a/arch/arm/boot/dts/armada-385-linksys-shelby.dts +++++ b/arch/arm/boot/dts/armada-385-linksys-shelby.dts ++@@ -142,3 +142,205 @@ ++ }; ++ }; ++ }; +++ +++&pcie1 { +++ mwlwifi { +++ marvell,chainmask = <4 4>; +++ marvell,powertable { +++ AU = +++ <36 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <40 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <44 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <48 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <52 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <56 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <60 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <64 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <100 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <104 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <108 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <112 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <116 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <120 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <124 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <128 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <132 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <136 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <140 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <149 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, +++ <153 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, +++ <157 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, +++ <161 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, +++ <165 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>; +++ CA = +++ <36 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, +++ <40 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, +++ <44 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, +++ <48 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, +++ <52 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <56 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <60 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <64 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <100 0 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <104 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <108 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <112 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <116 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <120 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <124 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <128 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <132 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <136 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <140 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <149 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, +++ <153 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, +++ <157 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, +++ <161 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, +++ <165 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>; +++ CN = +++ <36 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <40 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <44 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <48 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <52 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <56 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <60 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <64 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <100 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <104 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <108 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <112 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <116 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <120 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <124 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <128 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <132 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <136 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <140 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <149 0 0x14 0x14 0x14 0x14 0x13 0x13 0x13 0x13 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <153 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>, +++ <157 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>, +++ <161 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>, +++ <165 0 0x13 0x13 0x13 0x13 0x13 0x13 0x13 0x13 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>; +++ ETSI = +++ <36 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <40 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <44 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <48 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <52 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <56 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <60 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <64 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <100 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <104 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <108 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <112 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <116 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <120 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <124 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <128 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <132 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <136 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <140 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, +++ <149 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>; +++ FCC = +++ <36 0 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0 0xf>, +++ <40 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0xf 0xf 0xf 0xf 0 0xf>, +++ <44 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0xf 0xf 0xf 0xf 0 0xf>, +++ <48 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0xf 0xf 0xf 0xf 0 0xf>, +++ <52 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <56 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <60 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <64 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <100 0 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <104 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, +++ <108 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <112 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <116 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <120 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <124 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <128 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <132 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <136 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <140 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, +++ <149 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, +++ <153 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, +++ <157 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, +++ <161 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, +++ <165 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>; +++ }; +++ }; +++}; +++ +++&pcie2 { +++ mwlwifi { +++ marvell,chainmask = <4 4>; +++ marvell,powertable { +++ AU = +++ <1 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <2 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <3 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <4 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <5 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <6 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <7 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <8 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <9 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <10 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <11 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>; +++ CA = +++ <1 0 0x17 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0xe 0xe 0xe 0xe 0x0 0x0 0x0 0x0 0 0xf>, +++ <2 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <3 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <4 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <5 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <6 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <7 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <8 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <9 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <10 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <11 0 0x17 0x12 0x12 0x12 0x13 0x13 0x13 0x13 0xf 0xf 0xf 0xf 0x0 0x0 0x0 0x0 0 0xf>; +++ CN = +++ <1 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <2 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <3 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <4 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <5 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <6 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <7 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <8 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <9 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <10 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <11 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <12 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <13 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <14 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>; +++ ETSI = +++ <1 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <2 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <3 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <4 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <5 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <6 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <7 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <8 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <9 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <10 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <11 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <12 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, +++ <13 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>; +++ FCC = +++ <1 0 0x17 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0xe 0xe 0xe 0xe 0x0 0x0 0x0 0x0 0 0xf>, +++ <2 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <3 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <4 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <5 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <6 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <7 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <8 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <9 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <10 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, +++ <11 0 0x17 0x12 0x12 0x12 0x13 0x13 0x13 0x13 0xf 0xf 0xf 0xf 0x0 0x0 0x0 0x0 0 0xf>; +++ }; +++ }; +++}; ++--- a/arch/arm/boot/dts/armada-385-linksys-rango.dts +++++ b/arch/arm/boot/dts/armada-385-linksys-rango.dts ++@@ -157,6 +157,18 @@ ++ }; ++ }; ++ +++&pcie1 { +++ mwlwifi { +++ marvell,chainmask = <4 4>; +++ }; +++}; +++ +++&pcie2 { +++ mwlwifi { +++ marvell,chainmask = <4 4>; +++ }; +++}; +++ ++ &sdhci { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdhci_pins>; ++--- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts +++++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts ++@@ -225,12 +225,100 @@ ++ pcie@2,0 { ++ /* Port 0, Lane 1 */ ++ status = "okay"; +++ +++ mwlwifi { +++ marvell,5ghz = <0>; +++ marvell,chainmask = <4 4>; +++ marvell,powertable { +++ FCC = +++ <1 0 0x17 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0x0 0x0 0x0 0x0 0 0xf>, +++ <2 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, +++ <3 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, +++ <4 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, +++ <5 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, +++ <6 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, +++ <7 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, +++ <8 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, +++ <9 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, +++ <10 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, +++ <11 0 0x17 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>; +++ +++ ETSI = +++ <1 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, +++ <2 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, +++ <3 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, +++ <4 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, +++ <5 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, +++ <6 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, +++ <7 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, +++ <8 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, +++ <9 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, +++ <10 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, +++ <11 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, +++ <12 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, +++ <13 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>; +++ }; +++ }; ++ }; ++ ++ /* Second mini-PCIe port */ ++ pcie@3,0 { ++ /* Port 0, Lane 3 */ ++ status = "okay"; +++ +++ mwlwifi { +++ marvell,2ghz = <0>; +++ marvell,chainmask = <4 4>; +++ marvell,powertable { +++ FCC = +++ <36 0 0x8 0x8 0x8 0x8 0x8 0x8 0x8 0x8 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, +++ <40 0 0x8 0x8 0x8 0x8 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, +++ <44 0 0x8 0x8 0x8 0x8 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, +++ <48 0 0x8 0x8 0x8 0x8 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, +++ <52 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0 0xf>, +++ <56 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0 0xf>, +++ <60 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0 0xf>, +++ <64 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0 0xf>, +++ <100 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <104 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <108 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <112 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <116 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <120 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <124 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <128 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <132 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <136 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <140 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, +++ <149 0 0x16 0x16 0x16 0x16 0x14 0x14 0x14 0x14 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0 0xf>, +++ <153 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0 0xf>, +++ <157 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0 0xf>, +++ <161 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0 0xf>, +++ <165 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0 0xf>; +++ +++ ETSI = +++ <36 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, +++ <40 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, +++ <44 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, +++ <48 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, +++ <52 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, +++ <56 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, +++ <60 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, +++ <64 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, +++ <100 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, +++ <104 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, +++ <108 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, +++ <112 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, +++ <116 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, +++ <120 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, +++ <124 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, +++ <128 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, +++ <132 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, +++ <136 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, +++ <140 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, +++ <149 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>; +++ }; +++ }; ++ }; ++ }; ++ +diff --git a/target/linux/mvebu/patches-5.15/304-revert_i2c_delay.patch b/target/linux/mvebu/patches-5.15/304-revert_i2c_delay.patch +new file mode 100644 +index 0000000000..930c0f9494 +--- /dev/null ++++ b/target/linux/mvebu/patches-5.15/304-revert_i2c_delay.patch +@@ -0,0 +1,15 @@ ++--- a/arch/arm/boot/dts/armada-xp.dtsi +++++ b/arch/arm/boot/dts/armada-xp.dtsi ++@@ -237,12 +237,10 @@ ++ }; ++ ++ &i2c0 { ++- compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c"; ++ reg = <0x11000 0x100>; ++ }; ++ ++ &i2c1 { ++- compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c"; ++ reg = <0x11100 0x100>; ++ }; ++ +diff --git a/target/linux/mvebu/patches-5.15/305-armada-385-rd-mtd-partitions.patch b/target/linux/mvebu/patches-5.15/305-armada-385-rd-mtd-partitions.patch +new file mode 100644 +index 0000000000..31bd53b1f3 +--- /dev/null ++++ b/target/linux/mvebu/patches-5.15/305-armada-385-rd-mtd-partitions.patch +@@ -0,0 +1,19 @@ ++--- a/arch/arm/boot/dts/armada-388-rd.dts +++++ b/arch/arm/boot/dts/armada-388-rd.dts ++@@ -103,6 +103,16 @@ ++ compatible = "st,m25p128", "jedec,spi-nor"; ++ reg = <0>; /* Chip select 0 */ ++ spi-max-frequency = <108000000>; +++ +++ partition@0 { +++ label = "uboot"; +++ reg = <0 0x400000>; +++ }; +++ +++ partition@1 { +++ label = "firmware"; +++ reg = <0x400000 0xc00000>; +++ }; ++ }; ++ }; ++ +diff --git a/target/linux/mvebu/patches-5.15/306-ARM-mvebu-385-ap-Add-partitions.patch b/target/linux/mvebu/patches-5.15/306-ARM-mvebu-385-ap-Add-partitions.patch +new file mode 100644 +index 0000000000..2057e31c7e +--- /dev/null ++++ b/target/linux/mvebu/patches-5.15/306-ARM-mvebu-385-ap-Add-partitions.patch +@@ -0,0 +1,35 @@ ++From 9861f93a59142a3131870df2521eb2deb73026d7 Mon Sep 17 00:00:00 2001 ++From: Maxime Ripard <maxime.ripard@free-electrons.com> ++Date: Tue, 13 Jan 2015 11:14:09 +0100 ++Subject: [PATCH 2/2] ARM: mvebu: 385-ap: Add partitions ++ ++Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> ++--- ++ arch/arm/boot/dts/armada-385-db-ap.dts | 15 +++++++++++++++ ++ 1 file changed, 15 insertions(+) ++ ++--- a/arch/arm/boot/dts/armada-385-db-ap.dts +++++ b/arch/arm/boot/dts/armada-385-db-ap.dts ++@@ -218,19 +218,19 @@ ++ #size-cells = <1>; ++ ++ partition@0 { ++- label = "U-Boot"; +++ label = "u-boot"; ++ reg = <0x00000000 0x00800000>; ++ read-only; ++ }; ++ ++ partition@800000 { ++- label = "uImage"; +++ label = "kernel"; ++ reg = <0x00800000 0x00400000>; ++ read-only; ++ }; ++ ++ partition@c00000 { ++- label = "Root"; +++ label = "ubi"; ++ reg = <0x00c00000 0x3f400000>; ++ }; ++ }; +diff --git a/target/linux/mvebu/patches-5.15/307-armada-xp-linksys-mamba-broken-idle.patch b/target/linux/mvebu/patches-5.15/307-armada-xp-linksys-mamba-broken-idle.patch +new file mode 100644 +index 0000000000..16112d53fc +--- /dev/null ++++ b/target/linux/mvebu/patches-5.15/307-armada-xp-linksys-mamba-broken-idle.patch +@@ -0,0 +1,10 @@ ++--- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts +++++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts ++@@ -485,3 +485,7 @@ ++ }; ++ }; ++ }; +++ +++&coherencyfab { +++ broken-idle; +++}; +diff --git a/target/linux/mvebu/patches-5.15/308-armada-xp-linksys-mamba-wan.patch b/target/linux/mvebu/patches-5.15/308-armada-xp-linksys-mamba-wan.patch +new file mode 100644 +index 0000000000..4315abc7d2 +--- /dev/null ++++ b/target/linux/mvebu/patches-5.15/308-armada-xp-linksys-mamba-wan.patch +@@ -0,0 +1,11 @@ ++--- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts +++++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts ++@@ -387,7 +387,7 @@ ++ ++ port@4 { ++ reg = <4>; ++- label = "internet"; +++ label = "wan"; ++ }; ++ ++ port@5 { +diff --git a/target/linux/mvebu/patches-5.15/309-linksys-status-led.patch b/target/linux/mvebu/patches-5.15/309-linksys-status-led.patch +new file mode 100644 +index 0000000000..e5e83572c9 +--- /dev/null ++++ b/target/linux/mvebu/patches-5.15/309-linksys-status-led.patch +@@ -0,0 +1,50 @@ ++--- a/arch/arm/boot/dts/armada-385-linksys.dtsi +++++ b/arch/arm/boot/dts/armada-385-linksys.dtsi ++@@ -14,6 +14,13 @@ ++ compatible = "linksys,armada385", "marvell,armada385", ++ "marvell,armada380"; ++ +++ aliases { +++ led-boot = &led_power; +++ led-failsafe = &led_power; +++ led-running = &led_power; +++ led-upgrade = &led_power; +++ }; +++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++@@ -71,7 +78,7 @@ ++ pinctrl-0 = <&gpio_leds_pins>; ++ pinctrl-names = "default"; ++ ++- power { +++ led_power: power { ++ gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++--- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts +++++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts ++@@ -26,6 +26,13 @@ ++ compatible = "linksys,mamba", "marvell,armadaxp-mv78230", ++ "marvell,armadaxp", "marvell,armada-370-xp"; ++ +++ aliases { +++ led-boot = &led_power; +++ led-failsafe = &led_power; +++ led-running = &led_power; +++ led-upgrade = &led_power; +++ }; +++ ++ chosen { ++ bootargs = "console=ttyS0,115200"; ++ stdout-path = &uart0; ++@@ -197,7 +204,7 @@ ++ pinctrl-0 = <&power_led_pin>; ++ pinctrl-names = "default"; ++ ++- power { +++ led_power: power { ++ label = "mamba:white:power"; ++ gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; +diff --git a/target/linux/mvebu/patches-5.15/310-linksys-use-eth0-as-cpu-port.patch b/target/linux/mvebu/patches-5.15/310-linksys-use-eth0-as-cpu-port.patch +new file mode 100644 +index 0000000000..84d49a004b +--- /dev/null ++++ b/target/linux/mvebu/patches-5.15/310-linksys-use-eth0-as-cpu-port.patch +@@ -0,0 +1,25 @@ ++--- a/arch/arm/boot/dts/armada-385-linksys.dtsi +++++ b/arch/arm/boot/dts/armada-385-linksys.dtsi ++@@ -116,7 +116,7 @@ ++ }; ++ ++ ð2 { ++- status = "okay"; +++ status = "disabled"; ++ phy-mode = "sgmii"; ++ buffer-manager = <&bm>; ++ bm,pool-long = <2>; ++@@ -200,10 +200,10 @@ ++ label = "wan"; ++ }; ++ ++- port@5 { ++- reg = <5>; +++ port@6 { +++ reg = <6>; ++ label = "cpu"; ++- ethernet = <ð2>; +++ ethernet = <ð0>; ++ ++ fixed-link { ++ speed = <1000>; +diff --git a/target/linux/mvebu/patches-5.15/311-adjust-compatible-for-linksys.patch b/target/linux/mvebu/patches-5.15/311-adjust-compatible-for-linksys.patch +new file mode 100644 +index 0000000000..a5d3e63810 +--- /dev/null ++++ b/target/linux/mvebu/patches-5.15/311-adjust-compatible-for-linksys.patch +@@ -0,0 +1,68 @@ ++--- a/arch/arm/boot/dts/armada-385-linksys-rango.dts +++++ b/arch/arm/boot/dts/armada-385-linksys-rango.dts ++@@ -12,8 +12,8 @@ ++ ++ / { ++ model = "Linksys WRT3200ACM"; ++- compatible = "linksys,rango", "linksys,armada385", "marvell,armada385", ++- "marvell,armada380"; +++ compatible = "linksys,wrt3200acm", "linksys,rango", "linksys,armada385", +++ "marvell,armada385", "marvell,armada380"; ++ }; ++ ++ &expander0 { ++--- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts +++++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts ++@@ -22,9 +22,10 @@ ++ #include "armada-xp-mv78230.dtsi" ++ ++ / { ++- model = "Linksys WRT1900AC"; ++- compatible = "linksys,mamba", "marvell,armadaxp-mv78230", ++- "marvell,armadaxp", "marvell,armada-370-xp"; +++ model = "Linksys WRT1900AC v1"; +++ compatible = "linksys,wrt1900ac-v1", "linksys,mamba", +++ "marvell,armadaxp-mv78230", "marvell,armadaxp", +++ "marvell,armada-370-xp"; ++ ++ aliases { ++ led-boot = &led_power; ++--- a/arch/arm/boot/dts/armada-385-linksys-cobra.dts +++++ b/arch/arm/boot/dts/armada-385-linksys-cobra.dts ++@@ -9,8 +9,9 @@ ++ #include "armada-385-linksys.dtsi" ++ ++ / { ++- model = "Linksys WRT1900ACv2"; ++- compatible = "linksys,cobra", "linksys,armada385", "marvell,armada385", +++ model = "Linksys WRT1900AC v2"; +++ compatible = "linksys,wrt1900ac-v2", "linksys,cobra", +++ "linksys,armada385", "marvell,armada385", ++ "marvell,armada380"; ++ }; ++ ++--- a/arch/arm/boot/dts/armada-385-linksys-caiman.dts +++++ b/arch/arm/boot/dts/armada-385-linksys-caiman.dts ++@@ -10,8 +10,8 @@ ++ ++ / { ++ model = "Linksys WRT1200AC"; ++- compatible = "linksys,caiman", "linksys,armada385", "marvell,armada385", ++- "marvell,armada380"; +++ compatible = "linksys,wrt1200ac", "linksys,caiman", "linksys,armada385", +++ "marvell,armada385", "marvell,armada380"; ++ }; ++ ++ &expander0 { ++--- a/arch/arm/boot/dts/armada-385-linksys-shelby.dts +++++ b/arch/arm/boot/dts/armada-385-linksys-shelby.dts ++@@ -10,7 +10,8 @@ ++ ++ / { ++ model = "Linksys WRT1900ACS"; ++- compatible = "linksys,shelby", "linksys,armada385", "marvell,armada385", +++ compatible = "linksys,wrt1900acs", "linksys,shelby", +++ "linksys,armada385", "marvell,armada385", ++ "marvell,armada380"; ++ }; ++ +diff --git a/target/linux/mvebu/patches-5.15/312-ARM-dts-armada388-clearfog-emmc-on-clearfog-base.patch b/target/linux/mvebu/patches-5.15/312-ARM-dts-armada388-clearfog-emmc-on-clearfog-base.patch +new file mode 100644 +index 0000000000..dd2bef7f63 +--- /dev/null ++++ b/target/linux/mvebu/patches-5.15/312-ARM-dts-armada388-clearfog-emmc-on-clearfog-base.patch +@@ -0,0 +1,87 @@ ++From 8137da20701c776ad3481115305a5e8e410871ba Mon Sep 17 00:00:00 2001 ++From: Russell King <rmk+kernel@armlinux.org.uk> ++Date: Tue, 29 Nov 2016 10:15:45 +0000 ++Subject: ARM: dts: armada388-clearfog: emmc on clearfog base ++ ++Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> ++--- ++ arch/arm/boot/dts/armada-388-clearfog-base.dts | 1 + ++ .../dts/armada-38x-solidrun-microsom-emmc.dtsi | 62 ++++++++++++++++++++++ ++ 2 files changed, 63 insertions(+) ++ create mode 100644 arch/arm/boot/dts/armada-38x-solidrun-microsom-emmc.dtsi ++ ++--- a/arch/arm/boot/dts/armada-388-clearfog-base.dts +++++ b/arch/arm/boot/dts/armada-388-clearfog-base.dts ++@@ -7,6 +7,7 @@ ++ ++ /dts-v1/; ++ #include "armada-388-clearfog.dtsi" +++#include "armada-38x-solidrun-microsom-emmc.dtsi" ++ ++ / { ++ model = "SolidRun Clearfog Base A1"; ++--- /dev/null +++++ b/arch/arm/boot/dts/armada-38x-solidrun-microsom-emmc.dtsi ++@@ -0,0 +1,62 @@ +++/* +++ * Device Tree file for SolidRun Armada 38x Microsom add-on for eMMC +++ * +++ * Copyright (C) 2015 Russell King +++ * +++ * This board is in development; the contents of this file work with +++ * the A1 rev 2.0 of the board, which does not represent final +++ * production board. Things will change, don't expect this file to +++ * remain compatible info the future. +++ * +++ * This file is dual-licensed: you can use it either under the terms +++ * of the GPL or the X11 license, at your option. Note that this dual +++ * licensing only applies to this file, and not this project as a +++ * whole. +++ * +++ * a) This file is free software; you can redistribute it and/or +++ * modify it under the terms of the GNU General Public License +++ * version 2 as published by the Free Software Foundation. +++ * +++ * This file is distributed in the hope that it will be useful +++ * but WITHOUT ANY WARRANTY; without even the implied warranty of +++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +++ * GNU General Public License for more details. +++ * +++ * Or, alternatively +++ * +++ * b) Permission is hereby granted, free of charge, to any person +++ * obtaining a copy of this software and associated documentation +++ * files (the "Software"), to deal in the Software without +++ * restriction, including without limitation the rights to use +++ * copy, modify, merge, publish, distribute, sublicense, and/or +++ * sell copies of the Software, and to permit persons to whom the +++ * Software is furnished to do so, subject to the following +++ * conditions: +++ * +++ * The above copyright notice and this permission notice shall be +++ * included in all copies or substantial portions of the Software. +++ * +++ * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND +++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY +++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +++ * OTHER DEALINGS IN THE SOFTWARE. +++ */ +++/ { +++ soc { +++ internal-regs { +++ sdhci@d8000 { +++ bus-width = <4>; +++ no-1-8-v; +++ non-removable; +++ pinctrl-0 = <µsom_sdhci_pins>; +++ pinctrl-names = "default"; +++ status = "okay"; +++ wp-inverted; +++ }; +++ }; +++ }; +++}; +diff --git a/target/linux/mvebu/patches-5.15/313-helios4-dts-status-led-alias.patch b/target/linux/mvebu/patches-5.15/313-helios4-dts-status-led-alias.patch +new file mode 100644 +index 0000000000..607f436297 +--- /dev/null ++++ b/target/linux/mvebu/patches-5.15/313-helios4-dts-status-led-alias.patch +@@ -0,0 +1,28 @@ ++--- a/arch/arm/boot/dts/armada-388-helios4.dts +++++ b/arch/arm/boot/dts/armada-388-helios4.dts ++@@ -15,6 +15,13 @@ ++ model = "Helios4"; ++ compatible = "kobol,helios4", "marvell,armada388", ++ "marvell,armada385", "marvell,armada380"; +++ +++ aliases { +++ led-boot = &led_status; +++ led-failsafe = &led_status; +++ led-running = &led_status; +++ led-upgrade = &led_status; +++ }; ++ ++ memory { ++ device_type = "memory"; ++@@ -73,10 +80,9 @@ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&helios_system_led_pins>; ++ ++- status-led { +++ led_status: status-led { ++ label = "helios4:green:status"; ++ gpios = <&gpio0 24 GPIO_ACTIVE_LOW>; ++- linux,default-trigger = "heartbeat"; ++ default-state = "on"; ++ }; ++ +diff --git a/target/linux/mvebu/patches-5.15/315-armada-xp-linksys-mamba-resize-kernel.patch b/target/linux/mvebu/patches-5.15/315-armada-xp-linksys-mamba-resize-kernel.patch +new file mode 100644 +index 0000000000..f1fddceff4 +--- /dev/null ++++ b/target/linux/mvebu/patches-5.15/315-armada-xp-linksys-mamba-resize-kernel.patch +@@ -0,0 +1,37 @@ ++From 258233f00bcd013050efee00c5d9128ef8cd62dd Mon Sep 17 00:00:00 2001 ++From: Tad <tad@spotco.us> ++Date: Fri, 5 Feb 2021 22:32:11 -0500 ++Subject: [PATCH] ARM: dts: armada-xp-linksys-mamba: Increase kernel ++ partition to 4MB ++ ++Signed-off-by: Tad Davanzo <tad@spotco.us> ++--- ++ arch/arm/boot/dts/armada-xp-linksys-mamba.dts | 8 ++++---- ++ 1 file changed, 4 insertions(+), 4 deletions(-) ++ ++--- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts +++++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts ++@@ -456,9 +456,9 @@ ++ reg = <0xa00000 0x2800000>; /* 40MB */ ++ }; ++ ++- partition@d00000 { +++ partition@e00000 { ++ label = "rootfs1"; ++- reg = <0xd00000 0x2500000>; /* 37MB */ +++ reg = <0xe00000 0x2400000>; /* 36MB */ ++ }; ++ ++ /* kernel2 overlaps with rootfs2 by design */ ++@@ -467,9 +467,9 @@ ++ reg = <0x3200000 0x2800000>; /* 40MB */ ++ }; ++ ++- partition@3500000 { +++ partition@3600000 { ++ label = "rootfs2"; ++- reg = <0x3500000 0x2500000>; /* 37MB */ +++ reg = <0x3600000 0x2400000>; /* 36MB */ ++ }; ++ ++ /* +diff --git a/target/linux/mvebu/patches-5.15/316-armada-370-dts-fix-crypto-engine.patch b/target/linux/mvebu/patches-5.15/316-armada-370-dts-fix-crypto-engine.patch +new file mode 100644 +index 0000000000..19378870ef +--- /dev/null ++++ b/target/linux/mvebu/patches-5.15/316-armada-370-dts-fix-crypto-engine.patch +@@ -0,0 +1,29 @@ ++--- a/arch/arm/boot/dts/armada-370.dtsi +++++ b/arch/arm/boot/dts/armada-370.dtsi ++@@ -234,7 +234,7 @@ ++ clocks = <&gateclk 23>; ++ clock-names = "cesa0"; ++ marvell,crypto-srams = <&crypto_sram>; ++- marvell,crypto-sram-size = <0x7e0>; +++ marvell,crypto-sram-size = <0x800>; ++ }; ++ }; ++ ++@@ -255,12 +255,17 @@ ++ * cpuidle workaround. ++ */ ++ idle-sram@0 { +++ status = "disabled"; ++ reg = <0x0 0x20>; ++ }; ++ }; ++ }; ++ }; ++ +++&coherencyfab { +++ broken-idle; +++}; +++ ++ /* ++ * Default UART pinctrl setting without RTS/CTS, can be overwritten on ++ * board level if a different configuration is used. +diff --git a/target/linux/mvebu/patches-5.15/400-find_active_root.patch b/target/linux/mvebu/patches-5.15/400-find_active_root.patch +new file mode 100644 +index 0000000000..5582d20c68 +--- /dev/null ++++ b/target/linux/mvebu/patches-5.15/400-find_active_root.patch +@@ -0,0 +1,60 @@ ++The WRT1900AC among other Linksys routers uses a dual-firmware layout. ++Dynamically rename the active partition to "ubi". ++ ++Signed-off-by: Imre Kaloz <kaloz@openwrt.org> ++ ++--- a/drivers/mtd/parsers/ofpart_core.c +++++ b/drivers/mtd/parsers/ofpart_core.c ++@@ -38,6 +38,8 @@ static bool node_has_compatible(struct d ++ return of_get_property(pp, "compatible", NULL); ++ } ++ +++static int mangled_rootblock; +++ ++ static int parse_fixed_partitions(struct mtd_info *master, ++ const struct mtd_partition **pparts, ++ struct mtd_part_parser_data *data) ++@@ -48,6 +50,7 @@ static int parse_fixed_partitions(struct ++ struct device_node *mtd_node; ++ struct device_node *ofpart_node; ++ const char *partname; +++ const char *owrtpart = "ubi"; ++ struct device_node *pp; ++ int nr_parts, i, ret = 0; ++ bool dedicated = true; ++@@ -133,9 +136,13 @@ static int parse_fixed_partitions(struct ++ parts[i].size = of_read_number(reg + a_cells, s_cells); ++ parts[i].of_node = pp; ++ ++- partname = of_get_property(pp, "label", &len); ++- if (!partname) ++- partname = of_get_property(pp, "name", &len); +++ if (mangled_rootblock && (i == mangled_rootblock)) { +++ partname = owrtpart; +++ } else { +++ partname = of_get_property(pp, "label", &len); +++ if (!partname) +++ partname = of_get_property(pp, "name", &len); +++ } ++ parts[i].name = partname; ++ ++ if (of_get_property(pp, "read-only", &len)) ++@@ -252,6 +259,18 @@ static int __init ofpart_parser_init(voi ++ return 0; ++ } ++ +++static int __init active_root(char *str) +++{ +++ get_option(&str, &mangled_rootblock); +++ +++ if (!mangled_rootblock) +++ return 1; +++ +++ return 1; +++} +++ +++__setup("mangled_rootblock=", active_root); +++ ++ static void __exit ofpart_parser_exit(void) ++ { ++ deregister_mtd_parser(&ofpart_parser); +diff --git a/target/linux/mvebu/patches-5.15/700-mvneta-tx-queue-workaround.patch b/target/linux/mvebu/patches-5.15/700-mvneta-tx-queue-workaround.patch +new file mode 100644 +index 0000000000..6c07a2915b +--- /dev/null ++++ b/target/linux/mvebu/patches-5.15/700-mvneta-tx-queue-workaround.patch +@@ -0,0 +1,38 @@ ++The hardware queue scheduling is apparently configured with fixed ++priorities, which creates a nasty fairness issue where traffic from one ++CPU can starve traffic from all other CPUs. ++ ++Work around this issue by forcing all tx packets to go through one CPU, ++until this issue is fixed properly. ++ ++Signed-off-by: Felix Fietkau <nbd@nbd.name> ++--- ++--- a/drivers/net/ethernet/marvell/mvneta.c +++++ b/drivers/net/ethernet/marvell/mvneta.c ++@@ -4987,6 +4987,16 @@ static int mvneta_setup_tc(struct net_de ++ } ++ } ++ +++#ifndef CONFIG_ARM64 +++static u16 mvneta_select_queue(struct net_device *dev, struct sk_buff *skb, +++ struct net_device *sb_dev) +++{ +++ /* XXX: hardware queue scheduling is broken, +++ * use only one queue until it is fixed */ +++ return 0; +++} +++#endif +++ ++ static const struct net_device_ops mvneta_netdev_ops = { ++ .ndo_open = mvneta_open, ++ .ndo_stop = mvneta_stop, ++@@ -4997,6 +5007,9 @@ static const struct net_device_ops mvnet ++ .ndo_fix_features = mvneta_fix_features, ++ .ndo_get_stats64 = mvneta_get_stats64, ++ .ndo_eth_ioctl = mvneta_ioctl, +++#ifndef CONFIG_ARM64 +++ .ndo_select_queue = mvneta_select_queue, +++#endif ++ .ndo_bpf = mvneta_xdp, ++ .ndo_xdp_xmit = mvneta_xdp_xmit, ++ .ndo_setup_tc = mvneta_setup_tc, +diff --git a/target/linux/mvebu/patches-5.15/702-net-next-ethernet-marvell-mvnetaMQPrioOffload.patch b/target/linux/mvebu/patches-5.15/702-net-next-ethernet-marvell-mvnetaMQPrioOffload.patch +new file mode 100644 +index 0000000000..96f5042e69 +--- /dev/null ++++ b/target/linux/mvebu/patches-5.15/702-net-next-ethernet-marvell-mvnetaMQPrioOffload.patch +@@ -0,0 +1,66 @@ ++From 75fa71e3acadbb4ab5eda18505277eb9a1f69b23 Mon Sep 17 00:00:00 2001 ++From: Maxime Chevallier <maxime.chevallier@bootlin.com> ++Date: Fri, 26 Nov 2021 12:20:53 +0100 ++Subject: net: mvneta: Use struct tc_mqprio_qopt_offload for MQPrio ++ configuration ++ ++The struct tc_mqprio_qopt_offload is a container for struct tc_mqprio_qopt, ++that allows passing extra parameters, such as traffic shaping. This commit ++converts the current mqprio code to that new struct. ++ ++Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com> ++Signed-off-by: David S. Miller <davem@davemloft.net> ++--- ++ drivers/net/ethernet/marvell/mvneta.c | 17 ++++++++++------- ++ 1 file changed, 10 insertions(+), 7 deletions(-) ++ ++(limited to 'drivers/net/ethernet/marvell/mvneta.c') ++ ++--- a/drivers/net/ethernet/marvell/mvneta.c +++++ b/drivers/net/ethernet/marvell/mvneta.c ++@@ -38,6 +38,7 @@ ++ #include <net/ipv6.h> ++ #include <net/tso.h> ++ #include <net/page_pool.h> +++#include <net/pkt_cls.h> ++ #include <linux/bpf_trace.h> ++ ++ /* Registers */ ++@@ -4947,14 +4948,14 @@ static void mvneta_setup_rx_prio_map(str ++ } ++ ++ static int mvneta_setup_mqprio(struct net_device *dev, ++- struct tc_mqprio_qopt *qopt) +++ struct tc_mqprio_qopt_offload *mqprio) ++ { ++ struct mvneta_port *pp = netdev_priv(dev); ++ u8 num_tc; ++ int i; ++ ++- qopt->hw = TC_MQPRIO_HW_OFFLOAD_TCS; ++- num_tc = qopt->num_tc; +++ mqprio->qopt.hw = TC_MQPRIO_HW_OFFLOAD_TCS; +++ num_tc = mqprio->qopt.num_tc; ++ ++ if (num_tc > rxq_number) ++ return -EINVAL; ++@@ -4965,13 +4966,15 @@ static int mvneta_setup_mqprio(struct ne ++ return 0; ++ } ++ ++- memcpy(pp->prio_tc_map, qopt->prio_tc_map, sizeof(pp->prio_tc_map)); +++ memcpy(pp->prio_tc_map, mqprio->qopt.prio_tc_map, +++ sizeof(pp->prio_tc_map)); ++ ++ mvneta_setup_rx_prio_map(pp); ++ ++- netdev_set_num_tc(dev, qopt->num_tc); ++- for (i = 0; i < qopt->num_tc; i++) ++- netdev_set_tc_queue(dev, i, qopt->count[i], qopt->offset[i]); +++ netdev_set_num_tc(dev, mqprio->qopt.num_tc); +++ for (i = 0; i < mqprio->qopt.num_tc; i++) +++ netdev_set_tc_queue(dev, i, mqprio->qopt.count[i], +++ mqprio->qopt.offset[i]); ++ ++ return 0; ++ } +diff --git a/target/linux/mvebu/patches-5.15/703-net-next-ethernet-marvell-mvnetaMQPrioFlag.patch b/target/linux/mvebu/patches-5.15/703-net-next-ethernet-marvell-mvnetaMQPrioFlag.patch +new file mode 100644 +index 0000000000..997f301f39 +--- /dev/null ++++ b/target/linux/mvebu/patches-5.15/703-net-next-ethernet-marvell-mvnetaMQPrioFlag.patch +@@ -0,0 +1,30 @@ ++From e7ca75fe6662f78bfeb0112671c812e4c7b8e214 Mon Sep 17 00:00:00 2001 ++From: Maxime Chevallier <maxime.chevallier@bootlin.com> ++Date: Fri, 26 Nov 2021 12:20:54 +0100 ++Subject: net: mvneta: Don't force-set the offloading flag ++ ++The qopt->hw flag is set by the TC code according to the offloading mode ++asked by user. Don't force-set it in the driver, but instead read it to ++make sure we do what's asked. ++ ++Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com> ++Signed-off-by: David S. Miller <davem@davemloft.net> ++--- ++ drivers/net/ethernet/marvell/mvneta.c | 4 +++- ++ 1 file changed, 3 insertions(+), 1 deletion(-) ++ ++(limited to 'drivers/net/ethernet/marvell/mvneta.c') ++ ++--- a/drivers/net/ethernet/marvell/mvneta.c +++++ b/drivers/net/ethernet/marvell/mvneta.c ++@@ -4954,7 +4954,9 @@ static int mvneta_setup_mqprio(struct ne ++ u8 num_tc; ++ int i; ++ ++- mqprio->qopt.hw = TC_MQPRIO_HW_OFFLOAD_TCS; +++ if (mqprio->qopt.hw != TC_MQPRIO_HW_OFFLOAD_TCS) +++ return 0; +++ ++ num_tc = mqprio->qopt.num_tc; ++ ++ if (num_tc > rxq_number) +diff --git a/target/linux/mvebu/patches-5.15/704-net-next-ethernet-marvell-mvnetaMQPrioQueue.patch b/target/linux/mvebu/patches-5.15/704-net-next-ethernet-marvell-mvnetaMQPrioQueue.patch +new file mode 100644 +index 0000000000..73563a57a0 +--- /dev/null ++++ b/target/linux/mvebu/patches-5.15/704-net-next-ethernet-marvell-mvnetaMQPrioQueue.patch +@@ -0,0 +1,97 @@ ++From e9f7099d0730341b24c057acbf545dd019581db6 Mon Sep 17 00:00:00 2001 ++From: Maxime Chevallier <maxime.chevallier@bootlin.com> ++Date: Fri, 26 Nov 2021 12:20:55 +0100 ++Subject: net: mvneta: Allow having more than one queue per TC ++ ++The current mqprio implementation assumed that we are only using one ++queue per TC. Use the offset and count parameters to allow using ++multiple queues per TC. In that case, the controller will use a standard ++round-robin algorithm to pick queues assigned to the same TC, with the ++same priority. ++ ++This only applies to VLAN priorities in ingress traffic, each TC ++corresponding to a vlan priority. ++ ++Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com> ++Signed-off-by: David S. Miller <davem@davemloft.net> ++--- ++ drivers/net/ethernet/marvell/mvneta.c | 35 ++++++++++++++++++++--------------- ++ 1 file changed, 20 insertions(+), 15 deletions(-) ++ ++(limited to 'drivers/net/ethernet/marvell/mvneta.c') ++ ++--- a/drivers/net/ethernet/marvell/mvneta.c +++++ b/drivers/net/ethernet/marvell/mvneta.c ++@@ -493,7 +493,6 @@ struct mvneta_port { ++ u8 mcast_count[256]; ++ u16 tx_ring_size; ++ u16 rx_ring_size; ++- u8 prio_tc_map[8]; ++ ++ phy_interface_t phy_interface; ++ struct device_node *dn; ++@@ -4936,13 +4935,12 @@ static void mvneta_clear_rx_prio_map(str ++ mvreg_write(pp, MVNETA_VLAN_PRIO_TO_RXQ, 0); ++ } ++ ++-static void mvneta_setup_rx_prio_map(struct mvneta_port *pp) +++static void mvneta_map_vlan_prio_to_rxq(struct mvneta_port *pp, u8 pri, u8 rxq) ++ { ++- u32 val = 0; ++- int i; +++ u32 val = mvreg_read(pp, MVNETA_VLAN_PRIO_TO_RXQ); ++ ++- for (i = 0; i < rxq_number; i++) ++- val |= MVNETA_VLAN_PRIO_RXQ_MAP(i, pp->prio_tc_map[i]); +++ val &= ~MVNETA_VLAN_PRIO_RXQ_MAP(pri, 0x7); +++ val |= MVNETA_VLAN_PRIO_RXQ_MAP(pri, rxq); ++ ++ mvreg_write(pp, MVNETA_VLAN_PRIO_TO_RXQ, val); ++ } ++@@ -4951,8 +4949,8 @@ static int mvneta_setup_mqprio(struct ne ++ struct tc_mqprio_qopt_offload *mqprio) ++ { ++ struct mvneta_port *pp = netdev_priv(dev); +++ int rxq, tc; ++ u8 num_tc; ++- int i; ++ ++ if (mqprio->qopt.hw != TC_MQPRIO_HW_OFFLOAD_TCS) ++ return 0; ++@@ -4962,21 +4960,28 @@ static int mvneta_setup_mqprio(struct ne ++ if (num_tc > rxq_number) ++ return -EINVAL; ++ +++ mvneta_clear_rx_prio_map(pp); +++ ++ if (!num_tc) { ++- mvneta_clear_rx_prio_map(pp); ++ netdev_reset_tc(dev); ++ return 0; ++ } ++ ++- memcpy(pp->prio_tc_map, mqprio->qopt.prio_tc_map, ++- sizeof(pp->prio_tc_map)); +++ netdev_set_num_tc(dev, mqprio->qopt.num_tc); ++ ++- mvneta_setup_rx_prio_map(pp); +++ for (tc = 0; tc < mqprio->qopt.num_tc; tc++) { +++ netdev_set_tc_queue(dev, tc, mqprio->qopt.count[tc], +++ mqprio->qopt.offset[tc]); +++ +++ for (rxq = mqprio->qopt.offset[tc]; +++ rxq < mqprio->qopt.count[tc] + mqprio->qopt.offset[tc]; +++ rxq++) { +++ if (rxq >= rxq_number) +++ return -EINVAL; ++ ++- netdev_set_num_tc(dev, mqprio->qopt.num_tc); ++- for (i = 0; i < mqprio->qopt.num_tc; i++) ++- netdev_set_tc_queue(dev, i, mqprio->qopt.count[i], ++- mqprio->qopt.offset[i]); +++ mvneta_map_vlan_prio_to_rxq(pp, tc, rxq); +++ } +++ } ++ ++ return 0; ++ } +diff --git a/target/linux/mvebu/patches-5.15/705-net-next-ethernet-marvell-mvnetaMQPrioTCOffload.patch b/target/linux/mvebu/patches-5.15/705-net-next-ethernet-marvell-mvnetaMQPrioTCOffload.patch +new file mode 100644 +index 0000000000..7b837d0b49 +--- /dev/null ++++ b/target/linux/mvebu/patches-5.15/705-net-next-ethernet-marvell-mvnetaMQPrioTCOffload.patch +@@ -0,0 +1,182 @@ ++From 2551dc9e398c37a15e52122d385c29a8b06be45f Mon Sep 17 00:00:00 2001 ++From: Maxime Chevallier <maxime.chevallier@bootlin.com> ++Date: Fri, 26 Nov 2021 12:20:56 +0100 ++Subject: net: mvneta: Add TC traffic shaping offload ++ ++The mvneta controller is able to do some tocken-bucket per-queue traffic ++shaping. This commit adds support for setting these using the TC mqprio ++interface. ++ ++The token-bucket parameters are customisable, but the current ++implementation configures them to have a 10kbps resolution for the ++rate limitation, since it allows to cover the whole range of max_rate ++values from 10kbps to 5Gbps with 10kbps increments. ++ ++Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com> ++Signed-off-by: David S. Miller <davem@davemloft.net> ++--- ++ drivers/net/ethernet/marvell/mvneta.c | 120 +++++++++++++++++++++++++++++++++- ++ 1 file changed, 119 insertions(+), 1 deletion(-) ++ ++(limited to 'drivers/net/ethernet/marvell/mvneta.c') ++ ++--- a/drivers/net/ethernet/marvell/mvneta.c +++++ b/drivers/net/ethernet/marvell/mvneta.c ++@@ -248,12 +248,39 @@ ++ #define MVNETA_TXQ_SENT_DESC_MASK 0x3fff0000 ++ #define MVNETA_PORT_TX_RESET 0x3cf0 ++ #define MVNETA_PORT_TX_DMA_RESET BIT(0) +++#define MVNETA_TXQ_CMD1_REG 0x3e00 +++#define MVNETA_TXQ_CMD1_BW_LIM_SEL_V1 BIT(3) +++#define MVNETA_TXQ_CMD1_BW_LIM_EN BIT(0) +++#define MVNETA_REFILL_NUM_CLK_REG 0x3e08 +++#define MVNETA_REFILL_MAX_NUM_CLK 0x0000ffff ++ #define MVNETA_TX_MTU 0x3e0c ++ #define MVNETA_TX_TOKEN_SIZE 0x3e14 ++ #define MVNETA_TX_TOKEN_SIZE_MAX 0xffffffff +++#define MVNETA_TXQ_BUCKET_REFILL_REG(q) (0x3e20 + ((q) << 2)) +++#define MVNETA_TXQ_BUCKET_REFILL_PERIOD_MASK 0x3ff00000 +++#define MVNETA_TXQ_BUCKET_REFILL_PERIOD_SHIFT 20 +++#define MVNETA_TXQ_BUCKET_REFILL_VALUE_MAX 0x0007ffff ++ #define MVNETA_TXQ_TOKEN_SIZE_REG(q) (0x3e40 + ((q) << 2)) ++ #define MVNETA_TXQ_TOKEN_SIZE_MAX 0x7fffffff ++ +++/* The values of the bucket refill base period and refill period are taken from +++ * the reference manual, and adds up to a base resolution of 10Kbps. This allows +++ * to cover all rate-limit values from 10Kbps up to 5Gbps +++ */ +++ +++/* Base period for the rate limit algorithm */ +++#define MVNETA_TXQ_BUCKET_REFILL_BASE_PERIOD_NS 100 +++ +++/* Number of Base Period to wait between each bucket refill */ +++#define MVNETA_TXQ_BUCKET_REFILL_PERIOD 1000 +++ +++/* The base resolution for rate limiting, in bps. Any max_rate value should be +++ * a multiple of that value. +++ */ +++#define MVNETA_TXQ_RATE_LIMIT_RESOLUTION (NSEC_PER_SEC / \ +++ (MVNETA_TXQ_BUCKET_REFILL_BASE_PERIOD_NS * \ +++ MVNETA_TXQ_BUCKET_REFILL_PERIOD)) +++ ++ #define MVNETA_LPI_CTRL_0 0x2cc0 ++ #define MVNETA_LPI_CTRL_1 0x2cc4 ++ #define MVNETA_LPI_REQUEST_ENABLE BIT(0) ++@@ -4945,11 +4972,74 @@ static void mvneta_map_vlan_prio_to_rxq( ++ mvreg_write(pp, MVNETA_VLAN_PRIO_TO_RXQ, val); ++ } ++ +++static int mvneta_enable_per_queue_rate_limit(struct mvneta_port *pp) +++{ +++ unsigned long core_clk_rate; +++ u32 refill_cycles; +++ u32 val; +++ +++ core_clk_rate = clk_get_rate(pp->clk); +++ if (!core_clk_rate) +++ return -EINVAL; +++ +++ refill_cycles = MVNETA_TXQ_BUCKET_REFILL_BASE_PERIOD_NS / +++ (NSEC_PER_SEC / core_clk_rate); +++ +++ if (refill_cycles > MVNETA_REFILL_MAX_NUM_CLK) +++ return -EINVAL; +++ +++ /* Enable bw limit algorithm version 3 */ +++ val = mvreg_read(pp, MVNETA_TXQ_CMD1_REG); +++ val &= ~(MVNETA_TXQ_CMD1_BW_LIM_SEL_V1 | MVNETA_TXQ_CMD1_BW_LIM_EN); +++ mvreg_write(pp, MVNETA_TXQ_CMD1_REG, val); +++ +++ /* Set the base refill rate */ +++ mvreg_write(pp, MVNETA_REFILL_NUM_CLK_REG, refill_cycles); +++ +++ return 0; +++} +++ +++static void mvneta_disable_per_queue_rate_limit(struct mvneta_port *pp) +++{ +++ u32 val = mvreg_read(pp, MVNETA_TXQ_CMD1_REG); +++ +++ val |= (MVNETA_TXQ_CMD1_BW_LIM_SEL_V1 | MVNETA_TXQ_CMD1_BW_LIM_EN); +++ mvreg_write(pp, MVNETA_TXQ_CMD1_REG, val); +++} +++ +++static int mvneta_setup_queue_rates(struct mvneta_port *pp, int queue, +++ u64 min_rate, u64 max_rate) +++{ +++ u32 refill_val, rem; +++ u32 val = 0; +++ +++ /* Convert to from Bps to bps */ +++ max_rate *= 8; +++ +++ if (min_rate) +++ return -EINVAL; +++ +++ refill_val = div_u64_rem(max_rate, MVNETA_TXQ_RATE_LIMIT_RESOLUTION, +++ &rem); +++ +++ if (rem || !refill_val || +++ refill_val > MVNETA_TXQ_BUCKET_REFILL_VALUE_MAX) +++ return -EINVAL; +++ +++ val = refill_val; +++ val |= (MVNETA_TXQ_BUCKET_REFILL_PERIOD << +++ MVNETA_TXQ_BUCKET_REFILL_PERIOD_SHIFT); +++ +++ mvreg_write(pp, MVNETA_TXQ_BUCKET_REFILL_REG(queue), val); +++ +++ return 0; +++} +++ ++ static int mvneta_setup_mqprio(struct net_device *dev, ++ struct tc_mqprio_qopt_offload *mqprio) ++ { ++ struct mvneta_port *pp = netdev_priv(dev); ++- int rxq, tc; +++ int rxq, txq, tc, ret; ++ u8 num_tc; ++ ++ if (mqprio->qopt.hw != TC_MQPRIO_HW_OFFLOAD_TCS) ++@@ -4963,6 +5053,7 @@ static int mvneta_setup_mqprio(struct ne ++ mvneta_clear_rx_prio_map(pp); ++ ++ if (!num_tc) { +++ mvneta_disable_per_queue_rate_limit(pp); ++ netdev_reset_tc(dev); ++ return 0; ++ } ++@@ -4983,6 +5074,33 @@ static int mvneta_setup_mqprio(struct ne ++ } ++ } ++ +++ if (mqprio->shaper != TC_MQPRIO_SHAPER_BW_RATE) { +++ mvneta_disable_per_queue_rate_limit(pp); +++ return 0; +++ } +++ +++ if (mqprio->qopt.num_tc > txq_number) +++ return -EINVAL; +++ +++ ret = mvneta_enable_per_queue_rate_limit(pp); +++ if (ret) +++ return ret; +++ +++ for (tc = 0; tc < mqprio->qopt.num_tc; tc++) { +++ for (txq = mqprio->qopt.offset[tc]; +++ txq < mqprio->qopt.count[tc] + mqprio->qopt.offset[tc]; +++ txq++) { +++ if (txq >= txq_number) +++ return -EINVAL; +++ +++ ret = mvneta_setup_queue_rates(pp, txq, +++ mqprio->min_rate[tc], +++ mqprio->max_rate[tc]); +++ if (ret) +++ return ret; +++ } +++ } +++ ++ return 0; ++ } ++ +diff --git a/target/linux/mvebu/patches-5.15/800-cpuidle-mvebu-indicate-failure-to-enter-deeper-sleep.patch b/target/linux/mvebu/patches-5.15/800-cpuidle-mvebu-indicate-failure-to-enter-deeper-sleep.patch +new file mode 100644 +index 0000000000..29f36be460 +--- /dev/null ++++ b/target/linux/mvebu/patches-5.15/800-cpuidle-mvebu-indicate-failure-to-enter-deeper-sleep.patch +@@ -0,0 +1,40 @@ ++From c28b2d367da8a471482e6a4aa8337ab6369a80c2 Mon Sep 17 00:00:00 2001 ++From: Russell King <rmk+kernel@arm.linux.org.uk> ++Date: Sat, 3 Oct 2015 09:13:05 +0100 ++Subject: cpuidle: mvebu: indicate failure to enter deeper sleep states ++ ++The cpuidle ->enter method expects the return value to be the sleep ++state we entered. Returning negative numbers or other codes is not ++permissible since coupled CPU idle was merged. ++ ++At least some of the mvebu_v7_cpu_suspend() implementations return the ++value from cpu_suspend(), which returns zero if the CPU vectors back ++into the kernel via cpu_resume() (the success case), or the non-zero ++return value of the suspend actor, or one (failure cases). ++ ++We do not want to be returning the failure case value back to CPU idle ++as that indicates that we successfully entered one of the deeper idle ++states. Always return zero instead, indicating that we slept for the ++shortest amount of time. ++ ++Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> ++--- ++ drivers/cpuidle/cpuidle-mvebu-v7.c | 6 +++++- ++ 1 file changed, 5 insertions(+), 1 deletion(-) ++ ++--- a/drivers/cpuidle/cpuidle-mvebu-v7.c +++++ b/drivers/cpuidle/cpuidle-mvebu-v7.c ++@@ -39,8 +39,12 @@ static int mvebu_v7_enter_idle(struct cp ++ ret = mvebu_v7_cpu_suspend(deepidle); ++ cpu_pm_exit(); ++ +++ /* +++ * If we failed to enter the desired state, indicate that we +++ * slept lightly. +++ */ ++ if (ret) ++- return ret; +++ return 0; ++ ++ return index; ++ } +diff --git a/target/linux/mvebu/patches-5.15/801-pci-mvebu-time-out-reset-on-link-up.patch b/target/linux/mvebu/patches-5.15/801-pci-mvebu-time-out-reset-on-link-up.patch +new file mode 100644 +index 0000000000..dba1253699 +--- /dev/null ++++ b/target/linux/mvebu/patches-5.15/801-pci-mvebu-time-out-reset-on-link-up.patch +@@ -0,0 +1,60 @@ ++From 287b9df160b6159f8d385424904f8bac501280c1 Mon Sep 17 00:00:00 2001 ++From: Russell King <rmk+kernel@armlinux.org.uk> ++Date: Sat, 9 Jul 2016 10:58:16 +0100 ++Subject: pci: mvebu: time out reset on link up ++ ++If the port reports that the link is up while we are resetting, there's ++little point in waiting for the full duration. ++ ++Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> ++--- ++ drivers/pci/controller/pci-mvebu.c | 20 ++++++++++++++------ ++ 1 file changed, 14 insertions(+), 6 deletions(-) ++ ++--- a/drivers/pci/controller/pci-mvebu.c +++++ b/drivers/pci/controller/pci-mvebu.c ++@@ -1023,6 +1023,7 @@ static int mvebu_pcie_powerup(struct mve ++ ++ if (port->reset_gpio) { ++ u32 reset_udelay = PCI_PM_D3COLD_WAIT * 1000; +++ unsigned int i; ++ ++ of_property_read_u32(port->dn, "reset-delay-us", ++ &reset_udelay); ++@@ -1030,7 +1031,13 @@ static int mvebu_pcie_powerup(struct mve ++ udelay(100); ++ ++ gpiod_set_value_cansleep(port->reset_gpio, 0); ++- msleep(reset_udelay / 1000); +++ for (i = 0; i < reset_udelay; i += 1000) { +++ if (mvebu_pcie_link_up(port)) +++ break; +++ msleep(1); +++ } +++ +++ printk("%s: reset completed in %dus\n", port->name, i); ++ } ++ ++ return 0; ++@@ -1190,15 +1197,16 @@ static int mvebu_pcie_probe(struct platf ++ if (!child) ++ continue; ++ ++- ret = mvebu_pcie_powerup(port); ++- if (ret < 0) ++- continue; ++- ++ port->base = mvebu_pcie_map_registers(pdev, child, port); ++ if (IS_ERR(port->base)) { ++ dev_err(dev, "%s: cannot map registers\n", port->name); ++ port->base = NULL; ++- mvebu_pcie_powerdown(port); +++ continue; +++ } +++ +++ ret = mvebu_pcie_powerup(port); +++ if (ret < 0) { +++ port->base = NULL; ++ continue; ++ } ++ +diff --git a/target/linux/mvebu/patches-5.15/901-dt-bindings-Add-IEI-vendor-prefix-and-IEI-WT61P803-P.patch b/target/linux/mvebu/patches-5.15/901-dt-bindings-Add-IEI-vendor-prefix-and-IEI-WT61P803-P.patch +new file mode 100644 +index 0000000000..3446086cad +--- /dev/null ++++ b/target/linux/mvebu/patches-5.15/901-dt-bindings-Add-IEI-vendor-prefix-and-IEI-WT61P803-P.patch +@@ -0,0 +1,218 @@ ++From aa4a0ccc41997f2da172165c92803abace43bd1c Mon Sep 17 00:00:00 2001 ++From: Luka Kovacic <luka.kovacic () sartura ! hr> ++Date: Tue, 24 Aug 2021 12:44:32 +0000 ++Subject: [PATCH 1/7] dt-bindings: Add IEI vendor prefix and IEI WT61P803 ++ PUZZLE driver bindings ++ ++Add the IEI WT61P803 PUZZLE Device Tree bindings for MFD, HWMON and LED ++drivers. A new vendor prefix is also added accordingly for ++IEI Integration Corp. ++ ++Signed-off-by: Luka Kovacic <luka.kovacic@sartura.hr> ++Signed-off-by: Pavo Banicevic <pavo.banicevic@sartura.hr> ++Cc: Luka Perkov <luka.perkov@sartura.hr> ++Cc: Robert Marko <robert.marko@sartura.hr> ++--- ++ .../hwmon/iei,wt61p803-puzzle-hwmon.yaml | 53 ++++++++++++ ++ .../leds/iei,wt61p803-puzzle-leds.yaml | 39 +++++++++ ++ .../bindings/mfd/iei,wt61p803-puzzle.yaml | 82 +++++++++++++++++++ ++ .../devicetree/bindings/vendor-prefixes.yaml | 2 + ++ 4 files changed, 176 insertions(+) ++ create mode 100644 Documentation/devicetree/bindings/hwmon/iei,wt61p803-puzzle-hwmon.yaml ++ create mode 100644 Documentation/devicetree/bindings/leds/iei,wt61p803-puzzle-leds.yaml ++ create mode 100644 Documentation/devicetree/bindings/mfd/iei,wt61p803-puzzle.yaml ++ ++--- /dev/null +++++ b/Documentation/devicetree/bindings/hwmon/iei,wt61p803-puzzle-hwmon.yaml ++@@ -0,0 +1,53 @@ +++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +++%YAML 1.2 +++--- +++$id: http://devicetree.org/schemas/hwmon/iei,wt61p803-puzzle-hwmon.yaml# +++$schema: http://devicetree.org/meta-schemas/core.yaml# +++ +++title: IEI WT61P803 PUZZLE MCU HWMON module from IEI Integration Corp. +++ +++maintainers: +++ - Luka Kovacic <luka.kovacic@sartura.hr> +++ +++description: | +++ This module is a part of the IEI WT61P803 PUZZLE MFD device. For more details +++ see Documentation/devicetree/bindings/mfd/iei,wt61p803-puzzle.yaml. +++ +++ The HWMON module is a sub-node of the MCU node in the Device Tree. +++ +++properties: +++ compatible: +++ const: iei,wt61p803-puzzle-hwmon +++ +++ "#address-cells": +++ const: 1 +++ +++ "#size-cells": +++ const: 0 +++ +++patternProperties: +++ "^fan-group@[0-1]$": +++ type: object +++ properties: +++ reg: +++ minimum: 0 +++ maximum: 1 +++ description: +++ Fan group ID +++ +++ cooling-levels: +++ minItems: 1 +++ maxItems: 255 +++ description: +++ Cooling levels for the fans (PWM value mapping) +++ description: | +++ Properties for each fan group. +++ required: +++ - reg +++ +++required: +++ - compatible +++ - "#address-cells" +++ - "#size-cells" +++ +++additionalProperties: false ++--- /dev/null +++++ b/Documentation/devicetree/bindings/leds/iei,wt61p803-puzzle-leds.yaml ++@@ -0,0 +1,39 @@ +++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +++%YAML 1.2 +++--- +++$id: http://devicetree.org/schemas/leds/iei,wt61p803-puzzle-leds.yaml# +++$schema: http://devicetree.org/meta-schemas/core.yaml# +++ +++title: IEI WT61P803 PUZZLE MCU LED module from IEI Integration Corp. +++ +++maintainers: +++ - Luka Kovacic <luka.kovacic@sartura.hr> +++ +++description: | +++ This module is a part of the IEI WT61P803 PUZZLE MFD device. For more details +++ see Documentation/devicetree/bindings/mfd/iei,wt61p803-puzzle.yaml. +++ +++ The LED module is a sub-node of the MCU node in the Device Tree. +++ +++properties: +++ compatible: +++ const: iei,wt61p803-puzzle-leds +++ +++ "#address-cells": +++ const: 1 +++ +++ "#size-cells": +++ const: 0 +++ +++ led@0: +++ type: object +++ $ref: common.yaml +++ description: | +++ Properties for a single LED. +++ +++required: +++ - compatible +++ - "#address-cells" +++ - "#size-cells" +++ +++additionalProperties: false ++--- /dev/null +++++ b/Documentation/devicetree/bindings/mfd/iei,wt61p803-puzzle.yaml ++@@ -0,0 +1,82 @@ +++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +++%YAML 1.2 +++--- +++$id: http://devicetree.org/schemas/mfd/iei,wt61p803-puzzle.yaml# +++$schema: http://devicetree.org/meta-schemas/core.yaml# +++ +++title: IEI WT61P803 PUZZLE MCU from IEI Integration Corp. +++ +++maintainers: +++ - Luka Kovacic <luka.kovacic@sartura.hr> +++ +++description: | +++ IEI WT61P803 PUZZLE MCU is embedded in some IEI Puzzle series boards. +++ It's used for controlling system power states, fans, LEDs and temperature +++ sensors. +++ +++ For Device Tree bindings of other sub-modules (HWMON, LEDs) refer to the +++ binding documents under the respective subsystem directories. +++ +++properties: +++ compatible: +++ const: iei,wt61p803-puzzle +++ +++ current-speed: +++ description: +++ Serial bus speed in bps +++ maxItems: 1 +++ +++ enable-beep: true +++ +++ hwmon: +++ $ref: /schemas/hwmon/iei,wt61p803-puzzle-hwmon.yaml +++ +++ leds: +++ $ref: /schemas/leds/iei,wt61p803-puzzle-leds.yaml +++ +++required: +++ - compatible +++ - current-speed +++ +++additionalProperties: false +++ +++examples: +++ - | +++ #include <dt-bindings/leds/common.h> +++ serial { +++ mcu { +++ compatible = "iei,wt61p803-puzzle"; +++ current-speed = <115200>; +++ enable-beep; +++ +++ leds { +++ compatible = "iei,wt61p803-puzzle-leds"; +++ #address-cells = <1>; +++ #size-cells = <0>; +++ +++ led@0 { +++ reg = <0>; +++ function = LED_FUNCTION_POWER; +++ color = <LED_COLOR_ID_BLUE>; +++ }; +++ }; +++ +++ hwmon { +++ compatible = "iei,wt61p803-puzzle-hwmon"; +++ #address-cells = <1>; +++ #size-cells = <0>; +++ +++ fan-group@0 { +++ #cooling-cells = <2>; +++ reg = <0x00>; +++ cooling-levels = <64 102 170 230 250>; +++ }; +++ +++ fan-group@1 { +++ #cooling-cells = <2>; +++ reg = <0x01>; +++ cooling-levels = <64 102 170 230 250>; +++ }; +++ }; +++ }; +++ }; ++--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml ++@@ -519,6 +519,8 @@ patternProperties: ++ description: IC Plus Corp. ++ "^idt,.*": ++ description: Integrated Device Technologies, Inc. +++ "^iei,.*": +++ description: IEI Integration Corp. ++ "^ifi,.*": ++ description: Ingenieurburo Fur Ic-Technologie (I/F/I) ++ "^ilitek,.*": +diff --git a/target/linux/mvebu/patches-5.15/902-drivers-mfd-Add-a-driver-for-IEI-WT61P803-PUZZLE-MCU.patch b/target/linux/mvebu/patches-5.15/902-drivers-mfd-Add-a-driver-for-IEI-WT61P803-PUZZLE-MCU.patch +new file mode 100644 +index 0000000000..84d995b902 +--- /dev/null ++++ b/target/linux/mvebu/patches-5.15/902-drivers-mfd-Add-a-driver-for-IEI-WT61P803-PUZZLE-MCU.patch +@@ -0,0 +1,1034 @@ ++From 692cfa85272dd12995b427c0a7a585ced5d54f32 Mon Sep 17 00:00:00 2001 ++From: Luka Kovacic <luka.kovacic () sartura ! hr> ++Date: Tue, 24 Aug 2021 12:44:33 +0000 ++Subject: [PATCH 2/7] drivers: mfd: Add a driver for IEI WT61P803 PUZZLE MCU ++ ++Add a driver for the IEI WT61P803 PUZZLE microcontroller, used in some ++IEI Puzzle series devices. The microcontroller controls system power, ++temperature sensors, fans and LEDs. ++ ++This driver implements the core functionality for device communication ++over the system serial (serdev bus). It handles MCU messages and the ++internal MCU properties. Some properties can be managed over sysfs. ++ ++Signed-off-by: Luka Kovacic <luka.kovacic@sartura.hr> ++Signed-off-by: Pavo Banicevic <pavo.banicevic@sartura.hr> ++Cc: Luka Perkov <luka.perkov@sartura.hr> ++Cc: Robert Marko <robert.marko@sartura.hr> ++--- ++ drivers/mfd/Kconfig | 8 + ++ drivers/mfd/Makefile | 1 + ++ drivers/mfd/iei-wt61p803-puzzle.c | 908 ++++++++++++++++++++++++ ++ include/linux/mfd/iei-wt61p803-puzzle.h | 66 ++ ++ 4 files changed, 983 insertions(+) ++ create mode 100644 drivers/mfd/iei-wt61p803-puzzle.c ++ create mode 100644 include/linux/mfd/iei-wt61p803-puzzle.h ++ ++--- a/drivers/mfd/Kconfig +++++ b/drivers/mfd/Kconfig ++@@ -2187,6 +2187,15 @@ config SGI_MFD_IOC3 ++ If you have an SGI Origin, Octane, or a PCI IOC3 card, ++ then say Y. Otherwise say N. ++ +++config MFD_IEI_WT61P803_PUZZLE +++ tristate "IEI WT61P803 PUZZLE MCU driver" +++ depends on SERIAL_DEV_BUS +++ select MFD_CORE +++ help +++ IEI WT61P803 PUZZLE is a system power management microcontroller +++ used for fan control, temperature sensor reading, LED control +++ and system identification. +++ ++ config MFD_INTEL_M10_BMC ++ tristate "Intel MAX 10 Board Management Controller" ++ depends on SPI_MASTER ++--- a/drivers/mfd/Makefile +++++ b/drivers/mfd/Makefile ++@@ -237,6 +237,7 @@ obj-$(CONFIG_MFD_DLN2) += dln2.o ++ obj-$(CONFIG_MFD_RT4831) += rt4831.o ++ obj-$(CONFIG_MFD_RT5033) += rt5033.o ++ obj-$(CONFIG_MFD_SKY81452) += sky81452.o +++obj-$(CONFIG_MFD_IEI_WT61P803_PUZZLE) += iei-wt61p803-puzzle.o ++ ++ intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o ++ obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o ++--- /dev/null +++++ b/drivers/mfd/iei-wt61p803-puzzle.c ++@@ -0,0 +1,908 @@ +++// SPDX-License-Identifier: GPL-2.0-only +++/* IEI WT61P803 PUZZLE MCU Driver +++ * System management microcontroller for fan control, temperature sensor reading, +++ * LED control and system identification on IEI Puzzle series ARM-based appliances. +++ * +++ * Copyright (C) 2020 Sartura Ltd. +++ * Author: Luka Kovacic <luka.kovacic@sartura.hr> +++ */ +++ +++#include <linux/atomic.h> +++#include <linux/delay.h> +++#include <linux/export.h> +++#include <linux/init.h> +++#include <linux/kernel.h> +++#include <linux/mfd/core.h> +++#include <linux/mfd/iei-wt61p803-puzzle.h> +++#include <linux/mod_devicetable.h> +++#include <linux/module.h> +++#include <linux/of_platform.h> +++#include <linux/property.h> +++#include <linux/sched.h> +++#include <linux/serdev.h> +++#include <linux/slab.h> +++#include <linux/sysfs.h> +++#include <asm/unaligned.h> +++ +++/* start, payload and XOR checksum at end */ +++#define IEI_WT61P803_PUZZLE_MAX_COMMAND_LENGTH (1 + 20 + 1) +++#define IEI_WT61P803_PUZZLE_RESP_BUF_SIZE 512 +++ +++#define IEI_WT61P803_PUZZLE_MAC_LENGTH 17 +++#define IEI_WT61P803_PUZZLE_SN_LENGTH 36 +++#define IEI_WT61P803_PUZZLE_VERSION_LENGTH 6 +++#define IEI_WT61P803_PUZZLE_BUILD_INFO_LENGTH 16 +++#define IEI_WT61P803_PUZZLE_PROTOCOL_VERSION_LENGTH 8 +++#define IEI_WT61P803_PUZZLE_NB_MAC 8 +++ +++/* Use HZ as a timeout value throughout the driver */ +++#define IEI_WT61P803_PUZZLE_GENERAL_TIMEOUT HZ +++ +++enum iei_wt61p803_puzzle_attribute_type { +++ IEI_WT61P803_PUZZLE_VERSION, +++ IEI_WT61P803_PUZZLE_BUILD_INFO, +++ IEI_WT61P803_PUZZLE_BOOTLOADER_MODE, +++ IEI_WT61P803_PUZZLE_PROTOCOL_VERSION, +++ IEI_WT61P803_PUZZLE_SERIAL_NUMBER, +++ IEI_WT61P803_PUZZLE_MAC_ADDRESS, +++ IEI_WT61P803_PUZZLE_AC_RECOVERY_STATUS, +++ IEI_WT61P803_PUZZLE_POWER_LOSS_RECOVERY, +++ IEI_WT61P803_PUZZLE_POWER_STATUS, +++}; +++ +++struct iei_wt61p803_puzzle_device_attribute { +++ struct device_attribute dev_attr; +++ enum iei_wt61p803_puzzle_attribute_type type; +++ u8 index; +++}; +++ +++/** +++ * struct iei_wt61p803_puzzle_mcu_status - MCU flags state +++ * @ac_recovery_status_flag: AC Recovery Status Flag +++ * @power_loss_recovery: System recovery after power loss +++ * @power_status: System Power-on Method +++ */ +++struct iei_wt61p803_puzzle_mcu_status { +++ u8 ac_recovery_status_flag; +++ u8 power_loss_recovery; +++ u8 power_status; +++}; +++ +++/** +++ * struct iei_wt61p803_puzzle_reply - MCU reply +++ * @size: Size of the MCU reply +++ * @data: Full MCU reply buffer +++ * @state: Current state of the packet +++ * @received: Was the response fullfilled +++ */ +++struct iei_wt61p803_puzzle_reply { +++ size_t size; +++ unsigned char data[IEI_WT61P803_PUZZLE_RESP_BUF_SIZE]; +++ struct completion received; +++}; +++ +++/** +++ * struct iei_wt61p803_puzzle_mcu_version - MCU version status +++ * @version: Primary firmware version +++ * @build_info: Build date and time +++ * @bootloader_mode: Status of the MCU operation +++ * @protocol_version: MCU communication protocol version +++ * @serial_number: Device factory serial number +++ * @mac_address: Device factory MAC addresses +++ * +++ * Last element of arrays is reserved for '\0'. +++ */ +++struct iei_wt61p803_puzzle_mcu_version { +++ char version[IEI_WT61P803_PUZZLE_VERSION_LENGTH + 1]; +++ char build_info[IEI_WT61P803_PUZZLE_BUILD_INFO_LENGTH + 1]; +++ bool bootloader_mode; +++ char protocol_version[IEI_WT61P803_PUZZLE_PROTOCOL_VERSION_LENGTH + 1]; +++ char serial_number[IEI_WT61P803_PUZZLE_SN_LENGTH + 1]; +++ char mac_address[IEI_WT61P803_PUZZLE_NB_MAC][IEI_WT61P803_PUZZLE_MAC_LENGTH + 1]; +++}; +++ +++/** +++ * struct iei_wt61p803_puzzle - IEI WT61P803 PUZZLE MCU Driver +++ * @serdev: Pointer to underlying serdev device +++ * @dev: Pointer to underlying dev device +++ * @reply_lock: Reply mutex lock +++ * @reply: Pointer to the iei_wt61p803_puzzle_reply struct +++ * @version: MCU version related data +++ * @status: MCU status related data +++ * @response_buffer Command response buffer allocation +++ * @lock General member mutex lock +++ */ +++struct iei_wt61p803_puzzle { +++ struct serdev_device *serdev; +++ struct device *dev; +++ struct mutex reply_lock; /* lock to prevent multiple firmware calls */ +++ struct iei_wt61p803_puzzle_reply *reply; +++ struct iei_wt61p803_puzzle_mcu_version version; +++ struct iei_wt61p803_puzzle_mcu_status status; +++ unsigned char response_buffer[IEI_WT61P803_PUZZLE_BUF_SIZE]; +++ struct mutex lock; /* lock to protect response buffer */ +++}; +++ +++static unsigned char iei_wt61p803_puzzle_checksum(unsigned char *buf, size_t len) +++{ +++ unsigned char checksum = 0; +++ size_t i; +++ +++ for (i = 0; i < len; i++) +++ checksum ^= buf[i]; +++ return checksum; +++} +++ +++static int iei_wt61p803_puzzle_process_resp(struct iei_wt61p803_puzzle *mcu, +++ const unsigned char *raw_resp_data, size_t size) +++{ +++ unsigned char checksum; +++ +++ /* Check the incoming frame header */ +++ if (!(raw_resp_data[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START || +++ raw_resp_data[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START_OTHER || +++ (raw_resp_data[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_EEPROM && +++ raw_resp_data[1] == IEI_WT61P803_PUZZLE_CMD_EEPROM_READ))) { +++ if (mcu->reply->size + size >= sizeof(mcu->reply->data)) +++ return -EIO; +++ +++ /* Append the frame to existing data */ +++ memcpy(mcu->reply->data + mcu->reply->size, raw_resp_data, size); +++ mcu->reply->size += size; +++ } else { +++ if (size >= sizeof(mcu->reply->data)) +++ return -EIO; +++ +++ /* Start processing a new frame */ +++ memcpy(mcu->reply->data, raw_resp_data, size); +++ mcu->reply->size = size; +++ } +++ +++ checksum = iei_wt61p803_puzzle_checksum(mcu->reply->data, mcu->reply->size - 1); +++ if (checksum != mcu->reply->data[mcu->reply->size - 1]) { +++ /* The checksum isn't matched yet, wait for new frames */ +++ return size; +++ } +++ +++ /* Received all the data */ +++ complete(&mcu->reply->received); +++ +++ return size; +++} +++ +++static int iei_wt61p803_puzzle_recv_buf(struct serdev_device *serdev, +++ const unsigned char *data, size_t size) +++{ +++ struct iei_wt61p803_puzzle *mcu = serdev_device_get_drvdata(serdev); +++ int ret; +++ +++ ret = iei_wt61p803_puzzle_process_resp(mcu, data, size); +++ /* Return the number of processed bytes if function returns error, +++ * discard the remaining incoming data, since the frame this data +++ * belongs to is broken anyway +++ */ +++ if (ret < 0) +++ return size; +++ +++ return ret; +++} +++ +++static const struct serdev_device_ops iei_wt61p803_puzzle_serdev_device_ops = { +++ .receive_buf = iei_wt61p803_puzzle_recv_buf, +++ .write_wakeup = serdev_device_write_wakeup, +++}; +++ +++/** +++ * iei_wt61p803_puzzle_write_command_watchdog() - Watchdog of the normal cmd +++ * @mcu: Pointer to the iei_wt61p803_puzzle core MFD struct +++ * @cmd: Pointer to the char array to send (size should be content + 1 (xor)) +++ * @size: Size of the cmd char array +++ * @reply_data: Pointer to the reply/response data array (should be allocated) +++ * @reply_size: Pointer to size_t (size of reply_data) +++ * @retry_count: Number of times to retry sending the command to the MCU +++ */ +++int iei_wt61p803_puzzle_write_command_watchdog(struct iei_wt61p803_puzzle *mcu, +++ unsigned char *cmd, size_t size, +++ unsigned char *reply_data, +++ size_t *reply_size, int retry_count) +++{ +++ struct device *dev = &mcu->serdev->dev; +++ int ret, i; +++ +++ for (i = 0; i < retry_count; i++) { +++ ret = iei_wt61p803_puzzle_write_command(mcu, cmd, size, +++ reply_data, reply_size); +++ if (ret != -ETIMEDOUT) +++ return ret; +++ } +++ +++ dev_err(dev, "Command response timed out. Retries: %d\n", retry_count); +++ +++ return -ETIMEDOUT; +++} +++EXPORT_SYMBOL_GPL(iei_wt61p803_puzzle_write_command_watchdog); +++ +++/** +++ * iei_wt61p803_puzzle_write_command() - Send a structured command to the MCU +++ * @mcu: Pointer to the iei_wt61p803_puzzle core MFD struct +++ * @cmd: Pointer to the char array to send (size should be content + 1 (xor)) +++ * @size: Size of the cmd char array +++ * @reply_data: Pointer to the reply/response data array (should be allocated) +++ * +++ * Sends a structured command to the MCU. +++ */ +++int iei_wt61p803_puzzle_write_command(struct iei_wt61p803_puzzle *mcu, +++ unsigned char *cmd, size_t size, +++ unsigned char *reply_data, +++ size_t *reply_size) +++{ +++ struct device *dev = &mcu->serdev->dev; +++ int ret; +++ +++ if (size <= 1 || size > IEI_WT61P803_PUZZLE_MAX_COMMAND_LENGTH) +++ return -EINVAL; +++ +++ mutex_lock(&mcu->reply_lock); +++ +++ cmd[size - 1] = iei_wt61p803_puzzle_checksum(cmd, size - 1); +++ +++ /* Initialize reply struct */ +++ reinit_completion(&mcu->reply->received); +++ mcu->reply->size = 0; +++ usleep_range(2000, 10000); +++ serdev_device_write_flush(mcu->serdev); +++ ret = serdev_device_write_buf(mcu->serdev, cmd, size); +++ if (ret < 0) +++ goto exit; +++ +++ serdev_device_wait_until_sent(mcu->serdev, IEI_WT61P803_PUZZLE_GENERAL_TIMEOUT); +++ ret = wait_for_completion_timeout(&mcu->reply->received, +++ IEI_WT61P803_PUZZLE_GENERAL_TIMEOUT); +++ if (ret == 0) { +++ dev_err(dev, "Command reply receive timeout\n"); +++ ret = -ETIMEDOUT; +++ goto exit; +++ } +++ +++ *reply_size = mcu->reply->size; +++ /* Copy the received data, as it will not be available after a new frame is received */ +++ memcpy(reply_data, mcu->reply->data, mcu->reply->size); +++ ret = 0; +++exit: +++ mutex_unlock(&mcu->reply_lock); +++ return ret; +++} +++EXPORT_SYMBOL_GPL(iei_wt61p803_puzzle_write_command); +++ +++static int iei_wt61p803_puzzle_buzzer(struct iei_wt61p803_puzzle *mcu, bool long_beep) +++{ +++ unsigned char *resp_buf = mcu->response_buffer; +++ unsigned char buzzer_cmd[4] = {}; +++ size_t reply_size; +++ int ret; +++ +++ buzzer_cmd[0] = IEI_WT61P803_PUZZLE_CMD_HEADER_START; +++ buzzer_cmd[1] = IEI_WT61P803_PUZZLE_CMD_FUNCTION_SINGLE; +++ buzzer_cmd[2] = long_beep ? '3' : '2'; /* Buzzer 1.5 / 0.5 second beep */ +++ +++ mutex_lock(&mcu->lock); +++ ret = iei_wt61p803_puzzle_write_command(mcu, buzzer_cmd, sizeof(buzzer_cmd), +++ resp_buf, &reply_size); +++ if (ret) +++ goto exit; +++ +++ if (reply_size != 3) { +++ ret = -EIO; +++ goto exit; +++ } +++ +++ if (!(resp_buf[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START && +++ resp_buf[1] == IEI_WT61P803_PUZZLE_CMD_RESPONSE_OK && +++ resp_buf[2] == IEI_WT61P803_PUZZLE_CHECKSUM_RESPONSE_OK)) { +++ ret = -EPROTO; +++ goto exit; +++ } +++exit: +++ mutex_unlock(&mcu->lock); +++ return ret; +++} +++ +++static int iei_wt61p803_puzzle_get_version(struct iei_wt61p803_puzzle *mcu) +++{ +++ unsigned char version_cmd[3] = { +++ IEI_WT61P803_PUZZLE_CMD_HEADER_START_OTHER, +++ IEI_WT61P803_PUZZLE_CMD_OTHER_VERSION, +++ }; +++ unsigned char build_info_cmd[3] = { +++ IEI_WT61P803_PUZZLE_CMD_HEADER_START_OTHER, +++ IEI_WT61P803_PUZZLE_CMD_OTHER_BUILD, +++ }; +++ unsigned char bootloader_mode_cmd[3] = { +++ IEI_WT61P803_PUZZLE_CMD_HEADER_START_OTHER, +++ IEI_WT61P803_PUZZLE_CMD_OTHER_BOOTLOADER_MODE, +++ }; +++ unsigned char protocol_version_cmd[3] = { +++ IEI_WT61P803_PUZZLE_CMD_HEADER_START_OTHER, +++ IEI_WT61P803_PUZZLE_CMD_OTHER_PROTOCOL_VERSION, +++ }; +++ unsigned char *rb = mcu->response_buffer; +++ size_t reply_size; +++ int ret; +++ +++ mutex_lock(&mcu->lock); +++ +++ ret = iei_wt61p803_puzzle_write_command(mcu, version_cmd, sizeof(version_cmd), +++ rb, &reply_size); +++ if (ret) +++ goto err; +++ if (reply_size < 7) { +++ ret = -EIO; +++ goto err; +++ } +++ sprintf(mcu->version.version, "v%c.%.3s", rb[2], &rb[3]); +++ +++ ret = iei_wt61p803_puzzle_write_command(mcu, build_info_cmd, +++ sizeof(build_info_cmd), rb, +++ &reply_size); +++ if (ret) +++ goto err; +++ if (reply_size < 15) { +++ ret = -EIO; +++ goto err; +++ } +++ sprintf(mcu->version.build_info, "%c%c/%c%c/%.4s %c%c:%c%c", +++ rb[8], rb[9], rb[6], rb[7], &rb[2], rb[10], rb[11], +++ rb[12], rb[13]); +++ +++ ret = iei_wt61p803_puzzle_write_command(mcu, bootloader_mode_cmd, +++ sizeof(bootloader_mode_cmd), rb, +++ &reply_size); +++ if (ret) +++ goto err; +++ if (reply_size < 4) { +++ ret = -EIO; +++ goto err; +++ } +++ if (rb[2] == IEI_WT61P803_PUZZLE_CMD_OTHER_MODE_APPS) +++ mcu->version.bootloader_mode = false; +++ else if (rb[2] == IEI_WT61P803_PUZZLE_CMD_OTHER_MODE_BOOTLOADER) +++ mcu->version.bootloader_mode = true; +++ +++ ret = iei_wt61p803_puzzle_write_command(mcu, protocol_version_cmd, +++ sizeof(protocol_version_cmd), rb, +++ &reply_size); +++ if (ret) +++ goto err; +++ if (reply_size < 9) { +++ ret = -EIO; +++ goto err; +++ } +++ sprintf(mcu->version.protocol_version, "v%c.%c%c%c%c%c", +++ rb[7], rb[6], rb[5], rb[4], rb[3], rb[2]); +++err: +++ mutex_unlock(&mcu->lock); +++ return ret; +++} +++ +++static int iei_wt61p803_puzzle_get_mcu_status(struct iei_wt61p803_puzzle *mcu) +++{ +++ unsigned char mcu_status_cmd[5] = { +++ IEI_WT61P803_PUZZLE_CMD_HEADER_START, +++ IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER, +++ IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER_STATUS, +++ IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER_STATUS, +++ }; +++ unsigned char *resp_buf = mcu->response_buffer; +++ size_t reply_size; +++ int ret; +++ +++ mutex_lock(&mcu->lock); +++ ret = iei_wt61p803_puzzle_write_command(mcu, mcu_status_cmd, sizeof(mcu_status_cmd), +++ resp_buf, &reply_size); +++ if (ret) +++ goto exit; +++ if (reply_size < 20) { +++ ret = -EIO; +++ goto exit; +++ } +++ +++ /* Response format: +++ * (IDX RESPONSE) +++ * 0 @ +++ * 1 O +++ * 2 S +++ * 3 S +++ * ... +++ * 5 AC Recovery Status Flag +++ * ... +++ * 10 Power Loss Recovery +++ * ... +++ * 19 Power Status (system power on method) +++ * 20 XOR checksum +++ */ +++ if (resp_buf[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START && +++ resp_buf[1] == IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER && +++ resp_buf[2] == IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER_STATUS && +++ resp_buf[3] == IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER_STATUS) { +++ mcu->status.ac_recovery_status_flag = resp_buf[5]; +++ mcu->status.power_loss_recovery = resp_buf[10]; +++ mcu->status.power_status = resp_buf[19]; +++ } +++exit: +++ mutex_unlock(&mcu->lock); +++ return ret; +++} +++ +++static int iei_wt61p803_puzzle_get_serial_number(struct iei_wt61p803_puzzle *mcu) +++{ +++ unsigned char *resp_buf = mcu->response_buffer; +++ unsigned char serial_number_cmd[5] = { +++ IEI_WT61P803_PUZZLE_CMD_HEADER_EEPROM, +++ IEI_WT61P803_PUZZLE_CMD_EEPROM_READ, +++ 0x00, /* EEPROM read address */ +++ 0x24, /* Data length */ +++ }; +++ size_t reply_size; +++ int ret; +++ +++ mutex_lock(&mcu->lock); +++ ret = iei_wt61p803_puzzle_write_command(mcu, serial_number_cmd, +++ sizeof(serial_number_cmd), +++ resp_buf, &reply_size); +++ if (ret) +++ goto err; +++ +++ if (reply_size < IEI_WT61P803_PUZZLE_SN_LENGTH + 4) { +++ ret = -EIO; +++ goto err; +++ } +++ +++ sprintf(mcu->version.serial_number, "%.*s", +++ IEI_WT61P803_PUZZLE_SN_LENGTH, resp_buf + 4); +++err: +++ mutex_unlock(&mcu->lock); +++ return ret; +++} +++ +++static int iei_wt61p803_puzzle_write_serial_number(struct iei_wt61p803_puzzle *mcu, +++ unsigned char serial_number[36]) +++{ +++ unsigned char *resp_buf = mcu->response_buffer; +++ unsigned char serial_number_header[4] = { +++ IEI_WT61P803_PUZZLE_CMD_HEADER_EEPROM, +++ IEI_WT61P803_PUZZLE_CMD_EEPROM_WRITE, +++ 0x00, /* EEPROM write address */ +++ 0xC, /* Data length */ +++ }; +++ unsigned char serial_number_cmd[4 + 12 + 1]; /* header, serial number, XOR checksum */ +++ int ret, sn_counter; +++ size_t reply_size; +++ +++ /* The MCU can only handle 22 byte messages, send the S/N in 12 byte chunks */ +++ mutex_lock(&mcu->lock); +++ for (sn_counter = 0; sn_counter < 3; sn_counter++) { +++ serial_number_header[2] = 0x0 + 0xC * sn_counter; +++ +++ memcpy(serial_number_cmd, serial_number_header, sizeof(serial_number_header)); +++ memcpy(serial_number_cmd + sizeof(serial_number_header), +++ serial_number + 0xC * sn_counter, 0xC); +++ +++ ret = iei_wt61p803_puzzle_write_command(mcu, serial_number_cmd, +++ sizeof(serial_number_cmd), +++ resp_buf, &reply_size); +++ if (ret) +++ goto err; +++ if (reply_size != 3) { +++ ret = -EIO; +++ goto err; +++ } +++ if (!(resp_buf[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START && +++ resp_buf[1] == IEI_WT61P803_PUZZLE_CMD_RESPONSE_OK && +++ resp_buf[2] == IEI_WT61P803_PUZZLE_CHECKSUM_RESPONSE_OK)) { +++ ret = -EPROTO; +++ goto err; +++ } +++ } +++ +++ sprintf(mcu->version.serial_number, "%.*s", +++ IEI_WT61P803_PUZZLE_SN_LENGTH, serial_number); +++err: +++ mutex_unlock(&mcu->lock); +++ return ret; +++} +++ +++static int iei_wt61p803_puzzle_get_mac_address(struct iei_wt61p803_puzzle *mcu, int index) +++{ +++ unsigned char *resp_buf = mcu->response_buffer; +++ unsigned char mac_address_cmd[5] = { +++ IEI_WT61P803_PUZZLE_CMD_HEADER_EEPROM, +++ IEI_WT61P803_PUZZLE_CMD_EEPROM_READ, +++ 0x00, /* EEPROM read address */ +++ 0x11, /* Data length */ +++ }; +++ size_t reply_size; +++ int ret; +++ +++ mutex_lock(&mcu->lock); +++ mac_address_cmd[2] = 0x24 + 0x11 * index; +++ +++ ret = iei_wt61p803_puzzle_write_command(mcu, mac_address_cmd, +++ sizeof(mac_address_cmd), +++ resp_buf, &reply_size); +++ if (ret) +++ goto err; +++ +++ if (reply_size < 22) { +++ ret = -EIO; +++ goto err; +++ } +++ +++ sprintf(mcu->version.mac_address[index], "%.*s", +++ IEI_WT61P803_PUZZLE_MAC_LENGTH, resp_buf + 4); +++err: +++ mutex_unlock(&mcu->lock); +++ return ret; +++} +++ +++static int +++iei_wt61p803_puzzle_write_mac_address(struct iei_wt61p803_puzzle *mcu, +++ unsigned char mac_address[IEI_WT61P803_PUZZLE_MAC_LENGTH], +++ int mac_address_idx) +++{ +++ unsigned char mac_address_cmd[4 + IEI_WT61P803_PUZZLE_MAC_LENGTH + 1]; +++ unsigned char *resp_buf = mcu->response_buffer; +++ unsigned char mac_address_header[4] = { +++ IEI_WT61P803_PUZZLE_CMD_HEADER_EEPROM, +++ IEI_WT61P803_PUZZLE_CMD_EEPROM_WRITE, +++ 0x00, /* EEPROM write address */ +++ 0x11, /* Data length */ +++ }; +++ size_t reply_size; +++ int ret; +++ +++ if (mac_address_idx < 0 || mac_address_idx >= IEI_WT61P803_PUZZLE_NB_MAC) +++ return -EINVAL; +++ +++ mac_address_header[2] = 0x24 + 0x11 * mac_address_idx; +++ +++ /* Concat mac_address_header, mac_address to mac_address_cmd */ +++ memcpy(mac_address_cmd, mac_address_header, sizeof(mac_address_header)); +++ memcpy(mac_address_cmd + sizeof(mac_address_header), mac_address, +++ IEI_WT61P803_PUZZLE_MAC_LENGTH); +++ +++ mutex_lock(&mcu->lock); +++ ret = iei_wt61p803_puzzle_write_command(mcu, mac_address_cmd, +++ sizeof(mac_address_cmd), +++ resp_buf, &reply_size); +++ if (ret) +++ goto err; +++ if (reply_size != 3) { +++ ret = -EIO; +++ goto err; +++ } +++ if (!(resp_buf[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START && +++ resp_buf[1] == IEI_WT61P803_PUZZLE_CMD_RESPONSE_OK && +++ resp_buf[2] == IEI_WT61P803_PUZZLE_CHECKSUM_RESPONSE_OK)) { +++ ret = -EPROTO; +++ goto err; +++ } +++ +++ sprintf(mcu->version.mac_address[mac_address_idx], "%.*s", +++ IEI_WT61P803_PUZZLE_MAC_LENGTH, mac_address); +++err: +++ mutex_unlock(&mcu->lock); +++ return ret; +++} +++ +++static int iei_wt61p803_puzzle_write_power_loss_recovery(struct iei_wt61p803_puzzle *mcu, +++ int power_loss_recovery_action) +++{ +++ unsigned char *resp_buf = mcu->response_buffer; +++ unsigned char power_loss_recovery_cmd[5] = {}; +++ size_t reply_size; +++ int ret; +++ +++ if (power_loss_recovery_action < 0 || power_loss_recovery_action > 4) +++ return -EINVAL; +++ +++ power_loss_recovery_cmd[0] = IEI_WT61P803_PUZZLE_CMD_HEADER_START; +++ power_loss_recovery_cmd[1] = IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER; +++ power_loss_recovery_cmd[2] = IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER_POWER_LOSS; +++ power_loss_recovery_cmd[3] = hex_asc[power_loss_recovery_action]; +++ +++ mutex_lock(&mcu->lock); +++ ret = iei_wt61p803_puzzle_write_command(mcu, power_loss_recovery_cmd, +++ sizeof(power_loss_recovery_cmd), +++ resp_buf, &reply_size); +++ if (ret) +++ goto exit; +++ mcu->status.power_loss_recovery = power_loss_recovery_action; +++exit: +++ mutex_unlock(&mcu->lock); +++ return ret; +++} +++ +++#define to_puzzle_dev_attr(_attr) \ +++ container_of(_attr, struct iei_wt61p803_puzzle_device_attribute, dev_attr) +++ +++static ssize_t show_output(struct device *dev, +++ struct device_attribute *attr, char *buf) +++{ +++ struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev); +++ struct iei_wt61p803_puzzle_device_attribute *pattr = to_puzzle_dev_attr(attr); +++ int ret; +++ +++ switch (pattr->type) { +++ case IEI_WT61P803_PUZZLE_VERSION: +++ return scnprintf(buf, PAGE_SIZE, "%s\n", mcu->version.version); +++ case IEI_WT61P803_PUZZLE_BUILD_INFO: +++ return scnprintf(buf, PAGE_SIZE, "%s\n", mcu->version.build_info); +++ case IEI_WT61P803_PUZZLE_BOOTLOADER_MODE: +++ return scnprintf(buf, PAGE_SIZE, "%d\n", mcu->version.bootloader_mode); +++ case IEI_WT61P803_PUZZLE_PROTOCOL_VERSION: +++ return scnprintf(buf, PAGE_SIZE, "%s\n", mcu->version.protocol_version); +++ case IEI_WT61P803_PUZZLE_SERIAL_NUMBER: +++ ret = iei_wt61p803_puzzle_get_serial_number(mcu); +++ if (!ret) +++ ret = scnprintf(buf, PAGE_SIZE, "%s\n", mcu->version.serial_number); +++ else +++ ret = 0; +++ return ret; +++ case IEI_WT61P803_PUZZLE_MAC_ADDRESS: +++ ret = iei_wt61p803_puzzle_get_mac_address(mcu, pattr->index); +++ if (!ret) +++ ret = scnprintf(buf, PAGE_SIZE, "%s\n", +++ mcu->version.mac_address[pattr->index]); +++ else +++ ret = 0; +++ return ret; +++ case IEI_WT61P803_PUZZLE_AC_RECOVERY_STATUS: +++ case IEI_WT61P803_PUZZLE_POWER_LOSS_RECOVERY: +++ case IEI_WT61P803_PUZZLE_POWER_STATUS: +++ ret = iei_wt61p803_puzzle_get_mcu_status(mcu); +++ if (ret) +++ return ret; +++ +++ mutex_lock(&mcu->lock); +++ switch (pattr->type) { +++ case IEI_WT61P803_PUZZLE_AC_RECOVERY_STATUS: +++ ret = scnprintf(buf, PAGE_SIZE, "%x\n", +++ mcu->status.ac_recovery_status_flag); +++ break; +++ case IEI_WT61P803_PUZZLE_POWER_LOSS_RECOVERY: +++ ret = scnprintf(buf, PAGE_SIZE, "%x\n", mcu->status.power_loss_recovery); +++ break; +++ case IEI_WT61P803_PUZZLE_POWER_STATUS: +++ ret = scnprintf(buf, PAGE_SIZE, "%x\n", mcu->status.power_status); +++ break; +++ default: +++ ret = 0; +++ break; +++ } +++ mutex_unlock(&mcu->lock); +++ return ret; +++ default: +++ return 0; +++ } +++ +++ return 0; +++} +++ +++static ssize_t store_output(struct device *dev, +++ struct device_attribute *attr, +++ const char *buf, size_t len) +++{ +++ unsigned char serial_number[IEI_WT61P803_PUZZLE_SN_LENGTH]; +++ unsigned char mac_address[IEI_WT61P803_PUZZLE_MAC_LENGTH]; +++ struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev); +++ struct iei_wt61p803_puzzle_device_attribute *pattr = to_puzzle_dev_attr(attr); +++ int power_loss_recovery_action = 0; +++ int ret; +++ +++ switch (pattr->type) { +++ case IEI_WT61P803_PUZZLE_SERIAL_NUMBER: +++ if (len != (size_t)(IEI_WT61P803_PUZZLE_SN_LENGTH + 1)) +++ return -EINVAL; +++ memcpy(serial_number, buf, sizeof(serial_number)); +++ ret = iei_wt61p803_puzzle_write_serial_number(mcu, serial_number); +++ if (ret) +++ return ret; +++ return len; +++ case IEI_WT61P803_PUZZLE_MAC_ADDRESS: +++ if (len != (size_t)(IEI_WT61P803_PUZZLE_MAC_LENGTH + 1)) +++ return -EINVAL; +++ +++ memcpy(mac_address, buf, sizeof(mac_address)); +++ +++ if (strlen(attr->attr.name) != 13) +++ return -EIO; +++ +++ ret = iei_wt61p803_puzzle_write_mac_address(mcu, mac_address, pattr->index); +++ if (ret) +++ return ret; +++ return len; +++ case IEI_WT61P803_PUZZLE_POWER_LOSS_RECOVERY: +++ ret = kstrtoint(buf, 10, &power_loss_recovery_action); +++ if (ret) +++ return ret; +++ ret = iei_wt61p803_puzzle_write_power_loss_recovery(mcu, +++ power_loss_recovery_action); +++ if (ret) +++ return ret; +++ return len; +++ default: +++ return -EINVAL; +++ } +++ +++ return 0; +++} +++ +++#define IEI_WT61P803_PUZZLE_ATTR(_name, _mode, _show, _store, _type, _index) \ +++ struct iei_wt61p803_puzzle_device_attribute dev_attr_##_name = \ +++ { .dev_attr = __ATTR(_name, _mode, _show, _store), \ +++ .type = _type, \ +++ .index = _index } +++ +++#define IEI_WT61P803_PUZZLE_ATTR_RO(_name, _type, _id) \ +++ IEI_WT61P803_PUZZLE_ATTR(_name, 0444, show_output, NULL, _type, _id) +++ +++#define IEI_WT61P803_PUZZLE_ATTR_RW(_name, _type, _id) \ +++ IEI_WT61P803_PUZZLE_ATTR(_name, 0644, show_output, store_output, _type, _id) +++ +++static IEI_WT61P803_PUZZLE_ATTR_RO(version, IEI_WT61P803_PUZZLE_VERSION, 0); +++static IEI_WT61P803_PUZZLE_ATTR_RO(build_info, IEI_WT61P803_PUZZLE_BUILD_INFO, 0); +++static IEI_WT61P803_PUZZLE_ATTR_RO(bootloader_mode, IEI_WT61P803_PUZZLE_BOOTLOADER_MODE, 0); +++static IEI_WT61P803_PUZZLE_ATTR_RO(protocol_version, IEI_WT61P803_PUZZLE_PROTOCOL_VERSION, 0); +++static IEI_WT61P803_PUZZLE_ATTR_RW(serial_number, IEI_WT61P803_PUZZLE_SERIAL_NUMBER, 0); +++static IEI_WT61P803_PUZZLE_ATTR_RW(mac_address_0, IEI_WT61P803_PUZZLE_MAC_ADDRESS, 0); +++static IEI_WT61P803_PUZZLE_ATTR_RW(mac_address_1, IEI_WT61P803_PUZZLE_MAC_ADDRESS, 1); +++static IEI_WT61P803_PUZZLE_ATTR_RW(mac_address_2, IEI_WT61P803_PUZZLE_MAC_ADDRESS, 2); +++static IEI_WT61P803_PUZZLE_ATTR_RW(mac_address_3, IEI_WT61P803_PUZZLE_MAC_ADDRESS, 3); +++static IEI_WT61P803_PUZZLE_ATTR_RW(mac_address_4, IEI_WT61P803_PUZZLE_MAC_ADDRESS, 4); +++static IEI_WT61P803_PUZZLE_ATTR_RW(mac_address_5, IEI_WT61P803_PUZZLE_MAC_ADDRESS, 5); +++static IEI_WT61P803_PUZZLE_ATTR_RW(mac_address_6, IEI_WT61P803_PUZZLE_MAC_ADDRESS, 6); +++static IEI_WT61P803_PUZZLE_ATTR_RW(mac_address_7, IEI_WT61P803_PUZZLE_MAC_ADDRESS, 7); +++static IEI_WT61P803_PUZZLE_ATTR_RO(ac_recovery_status, IEI_WT61P803_PUZZLE_AC_RECOVERY_STATUS, 0); +++static IEI_WT61P803_PUZZLE_ATTR_RW(power_loss_recovery, IEI_WT61P803_PUZZLE_POWER_LOSS_RECOVERY, 0); +++static IEI_WT61P803_PUZZLE_ATTR_RO(power_status, IEI_WT61P803_PUZZLE_POWER_STATUS, 0); +++ +++static struct attribute *iei_wt61p803_puzzle_attrs[] = { +++ &dev_attr_version.dev_attr.attr, +++ &dev_attr_build_info.dev_attr.attr, +++ &dev_attr_bootloader_mode.dev_attr.attr, +++ &dev_attr_protocol_version.dev_attr.attr, +++ &dev_attr_serial_number.dev_attr.attr, +++ &dev_attr_mac_address_0.dev_attr.attr, +++ &dev_attr_mac_address_1.dev_attr.attr, +++ &dev_attr_mac_address_2.dev_attr.attr, +++ &dev_attr_mac_address_3.dev_attr.attr, +++ &dev_attr_mac_address_4.dev_attr.attr, +++ &dev_attr_mac_address_5.dev_attr.attr, +++ &dev_attr_mac_address_6.dev_attr.attr, +++ &dev_attr_mac_address_7.dev_attr.attr, +++ &dev_attr_ac_recovery_status.dev_attr.attr, +++ &dev_attr_power_loss_recovery.dev_attr.attr, +++ &dev_attr_power_status.dev_attr.attr, +++ NULL +++}; +++ATTRIBUTE_GROUPS(iei_wt61p803_puzzle); +++ +++static int iei_wt61p803_puzzle_sysfs_create(struct device *dev, +++ struct iei_wt61p803_puzzle *mcu) +++{ +++ int ret; +++ +++ ret = sysfs_create_groups(&mcu->dev->kobj, iei_wt61p803_puzzle_groups); +++ if (ret) +++ mfd_remove_devices(mcu->dev); +++ +++ return ret; +++} +++ +++static int iei_wt61p803_puzzle_sysfs_remove(struct device *dev, +++ struct iei_wt61p803_puzzle *mcu) +++{ +++ /* Remove sysfs groups */ +++ sysfs_remove_groups(&mcu->dev->kobj, iei_wt61p803_puzzle_groups); +++ mfd_remove_devices(mcu->dev); +++ +++ return 0; +++} +++ +++static int iei_wt61p803_puzzle_probe(struct serdev_device *serdev) +++{ +++ struct device *dev = &serdev->dev; +++ struct iei_wt61p803_puzzle *mcu; +++ u32 baud; +++ int ret; +++ +++ /* Read the baud rate from 'current-speed', because the MCU supports different rates */ +++ if (device_property_read_u32(dev, "current-speed", &baud)) { +++ dev_err(dev, +++ "'current-speed' is not specified in device node\n"); +++ return -EINVAL; +++ } +++ dev_dbg(dev, "Driver baud rate: %d\n", baud); +++ +++ /* Allocate the memory */ +++ mcu = devm_kzalloc(dev, sizeof(*mcu), GFP_KERNEL); +++ if (!mcu) +++ return -ENOMEM; +++ +++ mcu->reply = devm_kzalloc(dev, sizeof(*mcu->reply), GFP_KERNEL); +++ if (!mcu->reply) +++ return -ENOMEM; +++ +++ /* Initialize device struct data */ +++ mcu->serdev = serdev; +++ mcu->dev = dev; +++ init_completion(&mcu->reply->received); +++ mutex_init(&mcu->reply_lock); +++ mutex_init(&mcu->lock); +++ +++ /* Setup UART interface */ +++ serdev_device_set_drvdata(serdev, mcu); +++ serdev_device_set_client_ops(serdev, &iei_wt61p803_puzzle_serdev_device_ops); +++ ret = devm_serdev_device_open(dev, serdev); +++ if (ret) +++ return ret; +++ serdev_device_set_baudrate(serdev, baud); +++ serdev_device_set_flow_control(serdev, false); +++ ret = serdev_device_set_parity(serdev, SERDEV_PARITY_NONE); +++ if (ret) { +++ dev_err(dev, "Failed to set parity\n"); +++ return ret; +++ } +++ +++ ret = iei_wt61p803_puzzle_get_version(mcu); +++ if (ret) +++ return ret; +++ +++ dev_dbg(dev, "MCU version: %s\n", mcu->version.version); +++ dev_dbg(dev, "MCU firmware build info: %s\n", mcu->version.build_info); +++ dev_dbg(dev, "MCU in bootloader mode: %s\n", +++ mcu->version.bootloader_mode ? "true" : "false"); +++ dev_dbg(dev, "MCU protocol version: %s\n", mcu->version.protocol_version); +++ +++ if (device_property_read_bool(dev, "enable-beep")) { +++ ret = iei_wt61p803_puzzle_buzzer(mcu, false); +++ if (ret) +++ return ret; +++ } +++ +++ ret = iei_wt61p803_puzzle_sysfs_create(dev, mcu); +++ if (ret) +++ return ret; +++ +++ return devm_of_platform_populate(dev); +++} +++ +++static void iei_wt61p803_puzzle_remove(struct serdev_device *serdev) +++{ +++ struct device *dev = &serdev->dev; +++ struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev); +++ +++ iei_wt61p803_puzzle_sysfs_remove(dev, mcu); +++} +++ +++static const struct of_device_id iei_wt61p803_puzzle_dt_ids[] = { +++ { .compatible = "iei,wt61p803-puzzle" }, +++ { } +++}; +++ +++MODULE_DEVICE_TABLE(of, iei_wt61p803_puzzle_dt_ids); +++ +++static struct serdev_device_driver iei_wt61p803_puzzle_drv = { +++ .probe = iei_wt61p803_puzzle_probe, +++ .remove = iei_wt61p803_puzzle_remove, +++ .driver = { +++ .name = "iei-wt61p803-puzzle", +++ .of_match_table = iei_wt61p803_puzzle_dt_ids, +++ }, +++}; +++ +++module_serdev_device_driver(iei_wt61p803_puzzle_drv); +++ +++MODULE_LICENSE("GPL v2"); +++MODULE_AUTHOR("Luka Kovacic <luka.kovacic@sartura.hr>"); +++MODULE_DESCRIPTION("IEI WT61P803 PUZZLE MCU Driver"); ++--- /dev/null +++++ b/include/linux/mfd/iei-wt61p803-puzzle.h ++@@ -0,0 +1,66 @@ +++/* SPDX-License-Identifier: GPL-2.0-only */ +++/* IEI WT61P803 PUZZLE MCU Driver +++ * System management microcontroller for fan control, temperature sensor reading, +++ * LED control and system identification on IEI Puzzle series ARM-based appliances. +++ * +++ * Copyright (C) 2020 Sartura Ltd. +++ * Author: Luka Kovacic <luka.kovacic@sartura.hr> +++ */ +++ +++#ifndef _MFD_IEI_WT61P803_PUZZLE_H_ +++#define _MFD_IEI_WT61P803_PUZZLE_H_ +++ +++#define IEI_WT61P803_PUZZLE_BUF_SIZE 512 +++ +++/* Command magic numbers */ +++#define IEI_WT61P803_PUZZLE_CMD_HEADER_START 0x40 /* @ */ +++#define IEI_WT61P803_PUZZLE_CMD_HEADER_START_OTHER 0x25 /* % */ +++#define IEI_WT61P803_PUZZLE_CMD_HEADER_EEPROM 0xF7 +++ +++#define IEI_WT61P803_PUZZLE_CMD_RESPONSE_OK 0x30 /* 0 */ +++#define IEI_WT61P803_PUZZLE_CHECKSUM_RESPONSE_OK 0x70 +++ +++#define IEI_WT61P803_PUZZLE_CMD_EEPROM_READ 0xA1 +++#define IEI_WT61P803_PUZZLE_CMD_EEPROM_WRITE 0xA0 +++ +++#define IEI_WT61P803_PUZZLE_CMD_OTHER_VERSION 0x56 /* V */ +++#define IEI_WT61P803_PUZZLE_CMD_OTHER_BUILD 0x42 /* B */ +++#define IEI_WT61P803_PUZZLE_CMD_OTHER_BOOTLOADER_MODE 0x4D /* M */ +++#define IEI_WT61P803_PUZZLE_CMD_OTHER_MODE_BOOTLOADER 0x30 +++#define IEI_WT61P803_PUZZLE_CMD_OTHER_MODE_APPS 0x31 +++#define IEI_WT61P803_PUZZLE_CMD_OTHER_PROTOCOL_VERSION 0x50 /* P */ +++ +++#define IEI_WT61P803_PUZZLE_CMD_FUNCTION_SINGLE 0x43 /* C */ +++#define IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER 0x4F /* O */ +++#define IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER_STATUS 0x53 /* S */ +++#define IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER_POWER_LOSS 0x41 /* A */ +++ +++#define IEI_WT61P803_PUZZLE_CMD_LED 0x52 /* R */ +++#define IEI_WT61P803_PUZZLE_CMD_LED_POWER 0x31 /* 1 */ +++ +++#define IEI_WT61P803_PUZZLE_CMD_TEMP 0x54 /* T */ +++#define IEI_WT61P803_PUZZLE_CMD_TEMP_ALL 0x41 /* A */ +++ +++#define IEI_WT61P803_PUZZLE_CMD_FAN 0x46 /* F */ +++#define IEI_WT61P803_PUZZLE_CMD_FAN_PWM_READ 0x5A /* Z */ +++#define IEI_WT61P803_PUZZLE_CMD_FAN_PWM_WRITE 0x57 /* W */ +++#define IEI_WT61P803_PUZZLE_CMD_FAN_PWM_BASE 0x30 +++#define IEI_WT61P803_PUZZLE_CMD_FAN_RPM_BASE 0x41 /* A */ +++ +++#define IEI_WT61P803_PUZZLE_CMD_FAN_PWM(x) (IEI_WT61P803_PUZZLE_CMD_FAN_PWM_BASE + (x)) /* 0 - 1 */ +++#define IEI_WT61P803_PUZZLE_CMD_FAN_RPM(x) (IEI_WT61P803_PUZZLE_CMD_FAN_RPM_BASE + (x)) /* 0 - 5 */ +++ +++struct iei_wt61p803_puzzle_mcu_version; +++struct iei_wt61p803_puzzle_reply; +++struct iei_wt61p803_puzzle; +++ +++int iei_wt61p803_puzzle_write_command_watchdog(struct iei_wt61p803_puzzle *mcu, +++ unsigned char *cmd, size_t size, +++ unsigned char *reply_data, size_t *reply_size, +++ int retry_count); +++ +++int iei_wt61p803_puzzle_write_command(struct iei_wt61p803_puzzle *mcu, +++ unsigned char *cmd, size_t size, +++ unsigned char *reply_data, size_t *reply_size); +++ +++#endif /* _MFD_IEI_WT61P803_PUZZLE_H_ */ +diff --git a/target/linux/mvebu/patches-5.15/903-drivers-hwmon-Add-the-IEI-WT61P803-PUZZLE-HWMON-driv.patch b/target/linux/mvebu/patches-5.15/903-drivers-hwmon-Add-the-IEI-WT61P803-PUZZLE-HWMON-driv.patch +new file mode 100644 +index 0000000000..c22314e41c +--- /dev/null ++++ b/target/linux/mvebu/patches-5.15/903-drivers-hwmon-Add-the-IEI-WT61P803-PUZZLE-HWMON-driv.patch +@@ -0,0 +1,469 @@ ++From e3310a638cd310bfd93dbbc6d2732ab6aea18dd2 Mon Sep 17 00:00:00 2001 ++From: Luka Kovacic <luka.kovacic () sartura ! hr> ++Date: Tue, 24 Aug 2021 12:44:34 +0000 ++Subject: [PATCH 3/7] drivers: hwmon: Add the IEI WT61P803 PUZZLE HWMON driver ++ ++Add the IEI WT61P803 PUZZLE HWMON driver, that handles the fan speed ++control via PWM, reading fan speed and reading on-board temperature ++sensors. ++ ++The driver registers a HWMON device and a simple thermal cooling device to ++enable in-kernel fan management. ++ ++This driver depends on the IEI WT61P803 PUZZLE MFD driver. ++ ++Signed-off-by: Luka Kovacic <luka.kovacic@sartura.hr> ++Signed-off-by: Pavo Banicevic <pavo.banicevic@sartura.hr> ++Acked-by: Guenter Roeck <linux@roeck-us.net> ++Cc: Luka Perkov <luka.perkov@sartura.hr> ++Cc: Robert Marko <robert.marko@sartura.hr> ++--- ++ drivers/hwmon/Kconfig | 8 + ++ drivers/hwmon/Makefile | 1 + ++ drivers/hwmon/iei-wt61p803-puzzle-hwmon.c | 413 ++++++++++++++++++++++ ++ 3 files changed, 422 insertions(+) ++ create mode 100644 drivers/hwmon/iei-wt61p803-puzzle-hwmon.c ++ ++--- a/drivers/hwmon/Kconfig +++++ b/drivers/hwmon/Kconfig ++@@ -732,6 +732,14 @@ config SENSORS_IBMPOWERNV ++ This driver can also be built as a module. If so, the module ++ will be called ibmpowernv. ++ +++config SENSORS_IEI_WT61P803_PUZZLE_HWMON +++ tristate "IEI WT61P803 PUZZLE MFD HWMON Driver" +++ depends on MFD_IEI_WT61P803_PUZZLE +++ help +++ The IEI WT61P803 PUZZLE MFD HWMON Driver handles reading fan speed +++ and writing fan PWM values. It also supports reading on-board +++ temperature sensors. +++ ++ config SENSORS_IIO_HWMON ++ tristate "Hwmon driver that uses channels specified via iio maps" ++ depends on IIO ++--- a/drivers/hwmon/Makefile +++++ b/drivers/hwmon/Makefile ++@@ -84,6 +84,7 @@ obj-$(CONFIG_SENSORS_HIH6130) += hih6130 ++ obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o ++ obj-$(CONFIG_SENSORS_I5500) += i5500_temp.o ++ obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o +++obj-$(CONFIG_SENSORS_IEI_WT61P803_PUZZLE_HWMON) += iei-wt61p803-puzzle-hwmon.o ++ obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o ++ obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o ++ obj-$(CONFIG_SENSORS_IBMPOWERNV)+= ibmpowernv.o ++--- /dev/null +++++ b/drivers/hwmon/iei-wt61p803-puzzle-hwmon.c ++@@ -0,0 +1,413 @@ +++// SPDX-License-Identifier: GPL-2.0-only +++/* IEI WT61P803 PUZZLE MCU HWMON Driver +++ * +++ * Copyright (C) 2020 Sartura Ltd. +++ * Author: Luka Kovacic <luka.kovacic@sartura.hr> +++ */ +++ +++#include <linux/err.h> +++#include <linux/hwmon.h> +++#include <linux/interrupt.h> +++#include <linux/irq.h> +++#include <linux/math64.h> +++#include <linux/mfd/iei-wt61p803-puzzle.h> +++#include <linux/mod_devicetable.h> +++#include <linux/module.h> +++#include <linux/platform_device.h> +++#include <linux/property.h> +++#include <linux/slab.h> +++#include <linux/thermal.h> +++ +++#define IEI_WT61P803_PUZZLE_HWMON_MAX_PWM 2 +++#define IEI_WT61P803_PUZZLE_HWMON_MAX_PWM_VAL 255 +++ +++/** +++ * struct iei_wt61p803_puzzle_thermal_cooling_device - Thermal cooling device instance +++ * @mcu_hwmon: Parent driver struct pointer +++ * @tcdev: Thermal cooling device pointer +++ * @name: Thermal cooling device name +++ * @pwm_channel: Controlled PWM channel (0 or 1) +++ * @cooling_levels: Thermal cooling device cooling levels (DT) +++ */ +++struct iei_wt61p803_puzzle_thermal_cooling_device { +++ struct iei_wt61p803_puzzle_hwmon *mcu_hwmon; +++ struct thermal_cooling_device *tcdev; +++ char name[THERMAL_NAME_LENGTH]; +++ int pwm_channel; +++ u8 *cooling_levels; +++}; +++ +++/** +++ * struct iei_wt61p803_puzzle_hwmon - MCU HWMON Driver +++ * @mcu: MCU struct pointer +++ * @response_buffer Global MCU response buffer +++ * @thermal_cooling_dev_present: Per-channel thermal cooling device control indicator +++ * @cdev: Per-channel thermal cooling device private structure +++ */ +++struct iei_wt61p803_puzzle_hwmon { +++ struct iei_wt61p803_puzzle *mcu; +++ unsigned char response_buffer[IEI_WT61P803_PUZZLE_BUF_SIZE]; +++ bool thermal_cooling_dev_present[IEI_WT61P803_PUZZLE_HWMON_MAX_PWM]; +++ struct iei_wt61p803_puzzle_thermal_cooling_device +++ *cdev[IEI_WT61P803_PUZZLE_HWMON_MAX_PWM]; +++ struct mutex lock; /* mutex to protect response_buffer array */ +++}; +++ +++#define raw_temp_to_milidegree_celsius(x) (((x) - 0x80) * 1000) +++static int iei_wt61p803_puzzle_read_temp_sensor(struct iei_wt61p803_puzzle_hwmon *mcu_hwmon, +++ int channel, long *value) +++{ +++ unsigned char *resp_buf = mcu_hwmon->response_buffer; +++ unsigned char temp_sensor_ntc_cmd[4] = { +++ IEI_WT61P803_PUZZLE_CMD_HEADER_START, +++ IEI_WT61P803_PUZZLE_CMD_TEMP, +++ IEI_WT61P803_PUZZLE_CMD_TEMP_ALL, +++ }; +++ size_t reply_size; +++ int ret; +++ +++ mutex_lock(&mcu_hwmon->lock); +++ ret = iei_wt61p803_puzzle_write_command(mcu_hwmon->mcu, temp_sensor_ntc_cmd, +++ sizeof(temp_sensor_ntc_cmd), resp_buf, +++ &reply_size); +++ if (ret) +++ goto exit; +++ +++ if (reply_size != 7) { +++ ret = -EIO; +++ goto exit; +++ } +++ +++ /* Check the number of NTC values */ +++ if (resp_buf[3] != '2') { +++ ret = -EIO; +++ goto exit; +++ } +++ +++ *value = raw_temp_to_milidegree_celsius(resp_buf[4 + channel]); +++exit: +++ mutex_unlock(&mcu_hwmon->lock); +++ return ret; +++} +++ +++#define raw_fan_val_to_rpm(x, y) ((((x) << 8 | (y)) / 2) * 60) +++static int iei_wt61p803_puzzle_read_fan_speed(struct iei_wt61p803_puzzle_hwmon *mcu_hwmon, +++ int channel, long *value) +++{ +++ unsigned char *resp_buf = mcu_hwmon->response_buffer; +++ unsigned char fan_speed_cmd[4] = {}; +++ size_t reply_size; +++ int ret; +++ +++ fan_speed_cmd[0] = IEI_WT61P803_PUZZLE_CMD_HEADER_START; +++ fan_speed_cmd[1] = IEI_WT61P803_PUZZLE_CMD_FAN; +++ fan_speed_cmd[2] = IEI_WT61P803_PUZZLE_CMD_FAN_RPM(channel); +++ +++ mutex_lock(&mcu_hwmon->lock); +++ ret = iei_wt61p803_puzzle_write_command(mcu_hwmon->mcu, fan_speed_cmd, +++ sizeof(fan_speed_cmd), resp_buf, +++ &reply_size); +++ if (ret) +++ goto exit; +++ +++ if (reply_size != 7) { +++ ret = -EIO; +++ goto exit; +++ } +++ +++ *value = raw_fan_val_to_rpm(resp_buf[3], resp_buf[4]); +++exit: +++ mutex_unlock(&mcu_hwmon->lock); +++ return ret; +++} +++ +++static int iei_wt61p803_puzzle_write_pwm_channel(struct iei_wt61p803_puzzle_hwmon *mcu_hwmon, +++ int channel, long pwm_set_val) +++{ +++ unsigned char *resp_buf = mcu_hwmon->response_buffer; +++ unsigned char pwm_set_cmd[6] = {}; +++ size_t reply_size; +++ int ret; +++ +++ pwm_set_cmd[0] = IEI_WT61P803_PUZZLE_CMD_HEADER_START; +++ pwm_set_cmd[1] = IEI_WT61P803_PUZZLE_CMD_FAN; +++ pwm_set_cmd[2] = IEI_WT61P803_PUZZLE_CMD_FAN_PWM_WRITE; +++ pwm_set_cmd[3] = IEI_WT61P803_PUZZLE_CMD_FAN_PWM(channel); +++ pwm_set_cmd[4] = pwm_set_val; +++ +++ mutex_lock(&mcu_hwmon->lock); +++ ret = iei_wt61p803_puzzle_write_command(mcu_hwmon->mcu, pwm_set_cmd, +++ sizeof(pwm_set_cmd), resp_buf, +++ &reply_size); +++ if (ret) +++ goto exit; +++ +++ if (reply_size != 3) { +++ ret = -EIO; +++ goto exit; +++ } +++ +++ if (!(resp_buf[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START && +++ resp_buf[1] == IEI_WT61P803_PUZZLE_CMD_RESPONSE_OK && +++ resp_buf[2] == IEI_WT61P803_PUZZLE_CHECKSUM_RESPONSE_OK)) { +++ ret = -EIO; +++ goto exit; +++ } +++exit: +++ mutex_unlock(&mcu_hwmon->lock); +++ return ret; +++} +++ +++static int iei_wt61p803_puzzle_read_pwm_channel(struct iei_wt61p803_puzzle_hwmon *mcu_hwmon, +++ int channel, long *value) +++{ +++ unsigned char *resp_buf = mcu_hwmon->response_buffer; +++ unsigned char pwm_get_cmd[5] = {}; +++ size_t reply_size; +++ int ret; +++ +++ pwm_get_cmd[0] = IEI_WT61P803_PUZZLE_CMD_HEADER_START; +++ pwm_get_cmd[1] = IEI_WT61P803_PUZZLE_CMD_FAN; +++ pwm_get_cmd[2] = IEI_WT61P803_PUZZLE_CMD_FAN_PWM_READ; +++ pwm_get_cmd[3] = IEI_WT61P803_PUZZLE_CMD_FAN_PWM(channel); +++ +++ ret = iei_wt61p803_puzzle_write_command(mcu_hwmon->mcu, pwm_get_cmd, +++ sizeof(pwm_get_cmd), resp_buf, +++ &reply_size); +++ if (ret) +++ return ret; +++ +++ if (reply_size != 5) +++ return -EIO; +++ +++ if (resp_buf[2] != IEI_WT61P803_PUZZLE_CMD_FAN_PWM_READ) +++ return -EIO; +++ +++ *value = resp_buf[3]; +++ +++ return 0; +++} +++ +++static int iei_wt61p803_puzzle_read(struct device *dev, enum hwmon_sensor_types type, +++ u32 attr, int channel, long *val) +++{ +++ struct iei_wt61p803_puzzle_hwmon *mcu_hwmon = dev_get_drvdata(dev->parent); +++ +++ switch (type) { +++ case hwmon_pwm: +++ return iei_wt61p803_puzzle_read_pwm_channel(mcu_hwmon, channel, val); +++ case hwmon_fan: +++ return iei_wt61p803_puzzle_read_fan_speed(mcu_hwmon, channel, val); +++ case hwmon_temp: +++ return iei_wt61p803_puzzle_read_temp_sensor(mcu_hwmon, channel, val); +++ default: +++ return -EINVAL; +++ } +++} +++ +++static int iei_wt61p803_puzzle_write(struct device *dev, enum hwmon_sensor_types type, +++ u32 attr, int channel, long val) +++{ +++ struct iei_wt61p803_puzzle_hwmon *mcu_hwmon = dev_get_drvdata(dev->parent); +++ +++ return iei_wt61p803_puzzle_write_pwm_channel(mcu_hwmon, channel, val); +++} +++ +++static umode_t iei_wt61p803_puzzle_is_visible(const void *data, enum hwmon_sensor_types type, +++ u32 attr, int channel) +++{ +++ const struct iei_wt61p803_puzzle_hwmon *mcu_hwmon = data; +++ +++ switch (type) { +++ case hwmon_pwm: +++ if (mcu_hwmon->thermal_cooling_dev_present[channel]) +++ return 0444; +++ if (attr == hwmon_pwm_input) +++ return 0644; +++ break; +++ case hwmon_fan: +++ if (attr == hwmon_fan_input) +++ return 0444; +++ break; +++ case hwmon_temp: +++ if (attr == hwmon_temp_input) +++ return 0444; +++ break; +++ default: +++ return 0; +++ } +++ +++ return 0; +++} +++ +++static const struct hwmon_ops iei_wt61p803_puzzle_hwmon_ops = { +++ .is_visible = iei_wt61p803_puzzle_is_visible, +++ .read = iei_wt61p803_puzzle_read, +++ .write = iei_wt61p803_puzzle_write, +++}; +++ +++static const struct hwmon_channel_info *iei_wt61p803_puzzle_info[] = { +++ HWMON_CHANNEL_INFO(pwm, +++ HWMON_PWM_INPUT, +++ HWMON_PWM_INPUT), +++ HWMON_CHANNEL_INFO(fan, +++ HWMON_F_INPUT, +++ HWMON_F_INPUT, +++ HWMON_F_INPUT, +++ HWMON_F_INPUT, +++ HWMON_F_INPUT), +++ HWMON_CHANNEL_INFO(temp, +++ HWMON_T_INPUT, +++ HWMON_T_INPUT), +++ NULL +++}; +++ +++static const struct hwmon_chip_info iei_wt61p803_puzzle_chip_info = { +++ .ops = &iei_wt61p803_puzzle_hwmon_ops, +++ .info = iei_wt61p803_puzzle_info, +++}; +++ +++static int iei_wt61p803_puzzle_get_max_state(struct thermal_cooling_device *tcdev, +++ unsigned long *state) +++{ +++ *state = IEI_WT61P803_PUZZLE_HWMON_MAX_PWM_VAL; +++ +++ return 0; +++} +++ +++static int iei_wt61p803_puzzle_get_cur_state(struct thermal_cooling_device *tcdev, +++ unsigned long *state) +++{ +++ struct iei_wt61p803_puzzle_thermal_cooling_device *cdev = tcdev->devdata; +++ struct iei_wt61p803_puzzle_hwmon *mcu_hwmon = cdev->mcu_hwmon; +++ long value; +++ int ret; +++ +++ ret = iei_wt61p803_puzzle_read_pwm_channel(mcu_hwmon, cdev->pwm_channel, &value); +++ if (ret) +++ return ret; +++ *state = value; +++ return 0; +++} +++ +++static int iei_wt61p803_puzzle_set_cur_state(struct thermal_cooling_device *tcdev, +++ unsigned long state) +++{ +++ struct iei_wt61p803_puzzle_thermal_cooling_device *cdev = tcdev->devdata; +++ struct iei_wt61p803_puzzle_hwmon *mcu_hwmon = cdev->mcu_hwmon; +++ +++ return iei_wt61p803_puzzle_write_pwm_channel(mcu_hwmon, cdev->pwm_channel, state); +++} +++ +++static const struct thermal_cooling_device_ops iei_wt61p803_puzzle_cooling_ops = { +++ .get_max_state = iei_wt61p803_puzzle_get_max_state, +++ .get_cur_state = iei_wt61p803_puzzle_get_cur_state, +++ .set_cur_state = iei_wt61p803_puzzle_set_cur_state, +++}; +++ +++static int +++iei_wt61p803_puzzle_enable_thermal_cooling_dev(struct device *dev, +++ struct fwnode_handle *child, +++ struct iei_wt61p803_puzzle_hwmon *mcu_hwmon) +++{ +++ struct iei_wt61p803_puzzle_thermal_cooling_device *cdev; +++ u32 pwm_channel; +++ u8 num_levels; +++ int ret; +++ +++ ret = fwnode_property_read_u32(child, "reg", &pwm_channel); +++ if (ret) +++ return ret; +++ +++ mcu_hwmon->thermal_cooling_dev_present[pwm_channel] = true; +++ +++ num_levels = fwnode_property_count_u8(child, "cooling-levels"); +++ if (!num_levels) +++ return -EINVAL; +++ +++ cdev = devm_kzalloc(dev, sizeof(*cdev), GFP_KERNEL); +++ if (!cdev) +++ return -ENOMEM; +++ +++ cdev->cooling_levels = devm_kmalloc_array(dev, num_levels, sizeof(u8), GFP_KERNEL); +++ if (!cdev->cooling_levels) +++ return -ENOMEM; +++ +++ ret = fwnode_property_read_u8_array(child, "cooling-levels", +++ cdev->cooling_levels, +++ num_levels); +++ if (ret) { +++ dev_err(dev, "Couldn't read property 'cooling-levels'\n"); +++ return ret; +++ } +++ +++ snprintf(cdev->name, THERMAL_NAME_LENGTH, "wt61p803_puzzle_%d", pwm_channel); +++ cdev->tcdev = devm_thermal_of_cooling_device_register(dev, NULL, cdev->name, cdev, +++ &iei_wt61p803_puzzle_cooling_ops); +++ if (IS_ERR(cdev->tcdev)) +++ return PTR_ERR(cdev->tcdev); +++ +++ cdev->mcu_hwmon = mcu_hwmon; +++ cdev->pwm_channel = pwm_channel; +++ mcu_hwmon->cdev[pwm_channel] = cdev; +++ +++ return 0; +++} +++ +++static int iei_wt61p803_puzzle_hwmon_probe(struct platform_device *pdev) +++{ +++ struct device *dev = &pdev->dev; +++ struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev->parent); +++ struct iei_wt61p803_puzzle_hwmon *mcu_hwmon; +++ struct fwnode_handle *child; +++ struct device *hwmon_dev; +++ int ret; +++ +++ mcu_hwmon = devm_kzalloc(dev, sizeof(*mcu_hwmon), GFP_KERNEL); +++ if (!mcu_hwmon) +++ return -ENOMEM; +++ +++ mcu_hwmon->mcu = mcu; +++ platform_set_drvdata(pdev, mcu_hwmon); +++ mutex_init(&mcu_hwmon->lock); +++ +++ hwmon_dev = devm_hwmon_device_register_with_info(dev, "iei_wt61p803_puzzle", +++ mcu_hwmon, +++ &iei_wt61p803_puzzle_chip_info, +++ NULL); +++ if (IS_ERR(hwmon_dev)) +++ return PTR_ERR(hwmon_dev); +++ +++ /* Control fans via PWM lines via Linux Kernel */ +++ if (IS_ENABLED(CONFIG_THERMAL)) { +++ device_for_each_child_node(dev, child) { +++ ret = iei_wt61p803_puzzle_enable_thermal_cooling_dev(dev, child, mcu_hwmon); +++ if (ret) { +++ dev_err(dev, "Enabling the PWM fan failed\n"); +++ fwnode_handle_put(child); +++ return ret; +++ } +++ } +++ } +++ return 0; +++} +++ +++static const struct of_device_id iei_wt61p803_puzzle_hwmon_id_table[] = { +++ { .compatible = "iei,wt61p803-puzzle-hwmon" }, +++ {} +++}; +++MODULE_DEVICE_TABLE(of, iei_wt61p803_puzzle_hwmon_id_table); +++ +++static struct platform_driver iei_wt61p803_puzzle_hwmon_driver = { +++ .driver = { +++ .name = "iei-wt61p803-puzzle-hwmon", +++ .of_match_table = iei_wt61p803_puzzle_hwmon_id_table, +++ }, +++ .probe = iei_wt61p803_puzzle_hwmon_probe, +++}; +++ +++module_platform_driver(iei_wt61p803_puzzle_hwmon_driver); +++ +++MODULE_DESCRIPTION("IEI WT61P803 PUZZLE MCU HWMON Driver"); +++MODULE_AUTHOR("Luka Kovacic <luka.kovacic@sartura.hr>"); +++MODULE_LICENSE("GPL v2"); +diff --git a/target/linux/mvebu/patches-5.15/904-drivers-leds-Add-the-IEI-WT61P803-PUZZLE-LED-driver.patch b/target/linux/mvebu/patches-5.15/904-drivers-leds-Add-the-IEI-WT61P803-PUZZLE-LED-driver.patch +new file mode 100644 +index 0000000000..0452bd641b +--- /dev/null ++++ b/target/linux/mvebu/patches-5.15/904-drivers-leds-Add-the-IEI-WT61P803-PUZZLE-LED-driver.patch +@@ -0,0 +1,207 @@ ++From f3b44eb69cc561cf05d00506dcec0dd9be003ed8 Mon Sep 17 00:00:00 2001 ++From: Luka Kovacic <luka.kovacic () sartura ! hr> ++Date: Tue, 24 Aug 2021 12:44:35 +0000 ++Subject: [PATCH 4/7] drivers: leds: Add the IEI WT61P803 PUZZLE LED driver ++ ++Add support for the IEI WT61P803 PUZZLE LED driver. ++Currently only the front panel power LED is supported, ++since it is the only LED on this board wired through the ++MCU. ++ ++The LED is wired directly to the on-board MCU controller ++and is toggled using an MCU command. ++ ++Support for more LEDs is going to be added in case more ++boards implement this microcontroller, as LEDs use many ++different GPIOs. ++ ++This driver depends on the IEI WT61P803 PUZZLE MFD driver. ++ ++Signed-off-by: Luka Kovacic <luka.kovacic@sartura.hr> ++Signed-off-by: Pavo Banicevic <pavo.banicevic@sartura.hr> ++Cc: Luka Perkov <luka.perkov@sartura.hr> ++Cc: Robert Marko <robert.marko@sartura.hr> ++--- ++ drivers/leds/Kconfig | 8 ++ ++ drivers/leds/Makefile | 1 + ++ drivers/leds/leds-iei-wt61p803-puzzle.c | 147 ++++++++++++++++++++++++ ++ 3 files changed, 156 insertions(+) ++ create mode 100644 drivers/leds/leds-iei-wt61p803-puzzle.c ++ ++--- a/drivers/leds/Kconfig +++++ b/drivers/leds/Kconfig ++@@ -305,6 +305,14 @@ config LEDS_IPAQ_MICRO ++ Choose this option if you want to use the notification LED on ++ Compaq/HP iPAQ h3100 and h3600. ++ +++config LEDS_IEI_WT61P803_PUZZLE +++ tristate "LED Support for the IEI WT61P803 PUZZLE MCU" +++ depends on LEDS_CLASS +++ depends on MFD_IEI_WT61P803_PUZZLE +++ help +++ This option enables support for LEDs controlled by the IEI WT61P803 +++ M801 MCU. +++ ++ config LEDS_HP6XX ++ tristate "LED Support for the HP Jornada 6xx" ++ depends on LEDS_CLASS ++--- a/drivers/leds/Makefile +++++ b/drivers/leds/Makefile ++@@ -33,6 +33,7 @@ obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx. ++ obj-$(CONFIG_LEDS_INTEL_SS4200) += leds-ss4200.o ++ obj-$(CONFIG_LEDS_IP30) += leds-ip30.o ++ obj-$(CONFIG_LEDS_IPAQ_MICRO) += leds-ipaq-micro.o +++obj-$(CONFIG_LEDS_IEI_WT61P803_PUZZLE) += leds-iei-wt61p803-puzzle.o ++ obj-$(CONFIG_LEDS_IS31FL319X) += leds-is31fl319x.o ++ obj-$(CONFIG_LEDS_IS31FL32XX) += leds-is31fl32xx.o ++ obj-$(CONFIG_LEDS_LM3530) += leds-lm3530.o ++--- /dev/null +++++ b/drivers/leds/leds-iei-wt61p803-puzzle.c ++@@ -0,0 +1,147 @@ +++// SPDX-License-Identifier: GPL-2.0-only +++/* IEI WT61P803 PUZZLE MCU LED Driver +++ * +++ * Copyright (C) 2020 Sartura Ltd. +++ * Author: Luka Kovacic <luka.kovacic@sartura.hr> +++ */ +++ +++#include <linux/leds.h> +++#include <linux/mfd/iei-wt61p803-puzzle.h> +++#include <linux/mod_devicetable.h> +++#include <linux/module.h> +++#include <linux/platform_device.h> +++#include <linux/property.h> +++#include <linux/slab.h> +++ +++enum iei_wt61p803_puzzle_led_state { +++ IEI_LED_OFF = 0x30, +++ IEI_LED_ON = 0x31, +++ IEI_LED_BLINK_5HZ = 0x32, +++ IEI_LED_BLINK_1HZ = 0x33, +++}; +++ +++/** +++ * struct iei_wt61p803_puzzle_led - MCU LED Driver +++ * @cdev: LED classdev +++ * @mcu: MCU struct pointer +++ * @response_buffer Global MCU response buffer +++ * @lock: General mutex lock to protect simultaneous R/W access to led_power_state +++ * @led_power_state: State of the front panel power LED +++ */ +++struct iei_wt61p803_puzzle_led { +++ struct led_classdev cdev; +++ struct iei_wt61p803_puzzle *mcu; +++ unsigned char response_buffer[IEI_WT61P803_PUZZLE_BUF_SIZE]; +++ struct mutex lock; /* mutex to protect led_power_state */ +++ int led_power_state; +++}; +++ +++static inline struct iei_wt61p803_puzzle_led *cdev_to_iei_wt61p803_puzzle_led +++ (struct led_classdev *led_cdev) +++{ +++ return container_of(led_cdev, struct iei_wt61p803_puzzle_led, cdev); +++} +++ +++static int iei_wt61p803_puzzle_led_brightness_set_blocking(struct led_classdev *cdev, +++ enum led_brightness brightness) +++{ +++ struct iei_wt61p803_puzzle_led *priv = cdev_to_iei_wt61p803_puzzle_led(cdev); +++ unsigned char *resp_buf = priv->response_buffer; +++ unsigned char led_power_cmd[5] = {}; +++ size_t reply_size; +++ int ret; +++ +++ led_power_cmd[0] = IEI_WT61P803_PUZZLE_CMD_HEADER_START; +++ led_power_cmd[1] = IEI_WT61P803_PUZZLE_CMD_LED; +++ led_power_cmd[2] = IEI_WT61P803_PUZZLE_CMD_LED_POWER; +++ led_power_cmd[3] = brightness == LED_OFF ? IEI_LED_OFF : IEI_LED_ON; +++ +++ ret = iei_wt61p803_puzzle_write_command(priv->mcu, led_power_cmd, +++ sizeof(led_power_cmd), +++ resp_buf, +++ &reply_size); +++ if (ret) +++ return ret; +++ +++ if (reply_size != 3) +++ return -EIO; +++ +++ if (!(resp_buf[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START && +++ resp_buf[1] == IEI_WT61P803_PUZZLE_CMD_RESPONSE_OK && +++ resp_buf[2] == IEI_WT61P803_PUZZLE_CHECKSUM_RESPONSE_OK)) +++ return -EIO; +++ +++ mutex_lock(&priv->lock); +++ priv->led_power_state = brightness; +++ mutex_unlock(&priv->lock); +++ +++ return 0; +++} +++ +++static enum led_brightness iei_wt61p803_puzzle_led_brightness_get(struct led_classdev *cdev) +++{ +++ struct iei_wt61p803_puzzle_led *priv = cdev_to_iei_wt61p803_puzzle_led(cdev); +++ int led_state; +++ +++ mutex_lock(&priv->lock); +++ led_state = priv->led_power_state; +++ mutex_unlock(&priv->lock); +++ +++ return led_state; +++} +++ +++static int iei_wt61p803_puzzle_led_probe(struct platform_device *pdev) +++{ +++ struct device *dev = &pdev->dev; +++ struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev->parent); +++ struct iei_wt61p803_puzzle_led *priv; +++ struct led_init_data init_data = {}; +++ struct fwnode_handle *child; +++ int ret; +++ +++ if (device_get_child_node_count(dev) != 1) +++ return -EINVAL; +++ +++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); +++ if (!priv) +++ return -ENOMEM; +++ +++ priv->mcu = mcu; +++ priv->led_power_state = 1; +++ mutex_init(&priv->lock); +++ dev_set_drvdata(dev, priv); +++ +++ child = device_get_next_child_node(dev, NULL); +++ init_data.fwnode = child; +++ +++ priv->cdev.brightness_set_blocking = iei_wt61p803_puzzle_led_brightness_set_blocking; +++ priv->cdev.brightness_get = iei_wt61p803_puzzle_led_brightness_get; +++ priv->cdev.max_brightness = 1; +++ +++ ret = devm_led_classdev_register_ext(dev, &priv->cdev, &init_data); +++ if (ret) +++ dev_err(dev, "Could not register LED\n"); +++ +++ fwnode_handle_put(child); +++ return ret; +++} +++ +++static const struct of_device_id iei_wt61p803_puzzle_led_of_match[] = { +++ { .compatible = "iei,wt61p803-puzzle-leds" }, +++ { } +++}; +++MODULE_DEVICE_TABLE(of, iei_wt61p803_puzzle_led_of_match); +++ +++static struct platform_driver iei_wt61p803_puzzle_led_driver = { +++ .driver = { +++ .name = "iei-wt61p803-puzzle-led", +++ .of_match_table = iei_wt61p803_puzzle_led_of_match, +++ }, +++ .probe = iei_wt61p803_puzzle_led_probe, +++}; +++module_platform_driver(iei_wt61p803_puzzle_led_driver); +++ +++MODULE_DESCRIPTION("IEI WT61P803 PUZZLE front panel LED driver"); +++MODULE_AUTHOR("Luka Kovacic <luka.kovacic@sartura.hr>"); +++MODULE_LICENSE("GPL v2"); +++MODULE_ALIAS("platform:leds-iei-wt61p803-puzzle"); +diff --git a/target/linux/mvebu/patches-5.15/905-Documentation-ABI-Add-iei-wt61p803-puzzle-driver-sys.patch b/target/linux/mvebu/patches-5.15/905-Documentation-ABI-Add-iei-wt61p803-puzzle-driver-sys.patch +new file mode 100644 +index 0000000000..b1d420ef0a +--- /dev/null ++++ b/target/linux/mvebu/patches-5.15/905-Documentation-ABI-Add-iei-wt61p803-puzzle-driver-sys.patch +@@ -0,0 +1,82 @@ ++From 2fab3b4956c5b2f83c1e1abffc1df39de2933d83 Mon Sep 17 00:00:00 2001 ++From: Luka Kovacic <luka.kovacic () sartura ! hr> ++Date: Tue, 24 Aug 2021 12:44:36 +0000 ++Subject: [PATCH 5/7] Documentation/ABI: Add iei-wt61p803-puzzle driver sysfs ++ interface documentation ++ ++Add the iei-wt61p803-puzzle driver sysfs interface documentation to allow ++monitoring and control of the microcontroller from user space. ++ ++Signed-off-by: Luka Kovacic <luka.kovacic@sartura.hr> ++Signed-off-by: Pavo Banicevic <pavo.banicevic@sartura.hr> ++Cc: Luka Perkov <luka.perkov@sartura.hr> ++Cc: Robert Marko <robert.marko@sartura.hr> ++--- ++ .../testing/sysfs-driver-iei-wt61p803-puzzle | 61 +++++++++++++++++++ ++ 1 file changed, 61 insertions(+) ++ create mode 100644 Documentation/ABI/testing/sysfs-driver-iei-wt61p803-puzzle ++ ++--- /dev/null +++++ b/Documentation/ABI/testing/sysfs-driver-iei-wt61p803-puzzle ++@@ -0,0 +1,61 @@ +++What: /sys/bus/serial/devices/.../mac_address_* +++Date: September 2020 +++Contact: Luka Kovacic <luka.kovacic@sartura.hr> +++Description: (RW) Internal factory assigned MAC address values +++ +++What: /sys/bus/serial/devices/.../serial_number +++Date: September 2020 +++Contact: Luka Kovacic <luka.kovacic@sartura.hr> +++Description: (RW) Internal factory assigned serial number +++ +++What: /sys/bus/serial/devices/.../version +++Date: September 2020 +++Contact: Luka Kovacic <luka.kovacic@sartura.hr> +++Description: (RO) Internal MCU firmware version +++ +++What: /sys/bus/serial/devices/.../protocol_version +++Date: September 2020 +++Contact: Luka Kovacic <luka.kovacic@sartura.hr> +++Description: (RO) Internal MCU communication protocol version +++ +++What: /sys/bus/serial/devices/.../power_loss_recovery +++Date: September 2020 +++Contact: Luka Kovacic <luka.kovacic@sartura.hr> +++Description: (RW) Host platform power loss recovery settings +++ Value mapping: 0 - Always-On, 1 - Always-Off, 2 - Always-AC, 3 - Always-WA +++ +++What: /sys/bus/serial/devices/.../bootloader_mode +++Date: September 2020 +++Contact: Luka Kovacic <luka.kovacic@sartura.hr> +++Description: (RO) Internal MCU bootloader mode status +++ Value mapping: +++ 0 - normal mode +++ 1 - bootloader mode +++ +++What: /sys/bus/serial/devices/.../power_status +++Date: September 2020 +++Contact: Luka Kovacic <luka.kovacic@sartura.hr> +++Description: (RO) Power status indicates the host platform power on method. +++ Value mapping (bitwise list): +++ 0x80 - Null +++ 0x40 - Firmware flag +++ 0x20 - Power loss detection flag (powered off) +++ 0x10 - Power loss detection flag (AC mode) +++ 0x08 - Button power on +++ 0x04 - Wake-on-LAN power on +++ 0x02 - RTC alarm power on +++ 0x01 - AC recover power on +++ +++What: /sys/bus/serial/devices/.../build_info +++Date: September 2020 +++Contact: Luka Kovacic <luka.kovacic@sartura.hr> +++Description: (RO) Internal MCU firmware build date +++ Format: yyyy/mm/dd hh:mm +++ +++What: /sys/bus/serial/devices/.../ac_recovery_status +++Date: September 2020 +++Contact: Luka Kovacic <luka.kovacic@sartura.hr> +++Description: (RO) Host platform AC recovery status value +++ Value mapping: +++ 0 - board has not been recovered from power down +++ 1 - board has been recovered from power down +diff --git a/target/linux/mvebu/patches-5.15/906-Documentation-hwmon-Add-iei-wt61p803-puzzle-hwmon-dr.patch b/target/linux/mvebu/patches-5.15/906-Documentation-hwmon-Add-iei-wt61p803-puzzle-hwmon-dr.patch +new file mode 100644 +index 0000000000..9015436f6a +--- /dev/null ++++ b/target/linux/mvebu/patches-5.15/906-Documentation-hwmon-Add-iei-wt61p803-puzzle-hwmon-dr.patch +@@ -0,0 +1,74 @@ ++From 0aff3e5923fecc6842473ad07a688d6e2f2c2d55 Mon Sep 17 00:00:00 2001 ++From: Luka Kovacic <luka.kovacic () sartura ! hr> ++Date: Tue, 24 Aug 2021 12:44:37 +0000 ++Subject: [PATCH 6/7] Documentation/hwmon: Add iei-wt61p803-puzzle hwmon driver ++ documentation ++ ++Add the iei-wt61p803-puzzle driver hwmon driver interface documentation. ++ ++Signed-off-by: Luka Kovacic <luka.kovacic@sartura.hr> ++Signed-off-by: Pavo Banicevic <pavo.banicevic@sartura.hr> ++Cc: Luka Perkov <luka.perkov@sartura.hr> ++Cc: Robert Marko <robert.marko@sartura.hr> ++--- ++ .../hwmon/iei-wt61p803-puzzle-hwmon.rst | 43 +++++++++++++++++++ ++ Documentation/hwmon/index.rst | 1 + ++ 2 files changed, 44 insertions(+) ++ create mode 100644 Documentation/hwmon/iei-wt61p803-puzzle-hwmon.rst ++ ++--- /dev/null +++++ b/Documentation/hwmon/iei-wt61p803-puzzle-hwmon.rst ++@@ -0,0 +1,43 @@ +++.. SPDX-License-Identifier: GPL-2.0-only +++ +++Kernel driver iei-wt61p803-puzzle-hwmon +++======================================= +++ +++Supported chips: +++ * IEI WT61P803 PUZZLE for IEI Puzzle M801 +++ +++ Prefix: 'iei-wt61p803-puzzle-hwmon' +++ +++Author: Luka Kovacic <luka.kovacic@sartura.hr> +++ +++ +++Description +++----------- +++ +++This driver adds fan and temperature sensor reading for some IEI Puzzle +++series boards. +++ +++Sysfs attributes +++---------------- +++ +++The following attributes are supported: +++ +++- IEI WT61P803 PUZZLE for IEI Puzzle M801 +++ +++/sys files in hwmon subsystem +++----------------------------- +++ +++================= == ===================================================== +++fan[1-5]_input RO files for fan speed (in RPM) +++pwm[1-2] RW files for fan[1-2] target duty cycle (0..255) +++temp[1-2]_input RO files for temperature sensors, in millidegree Celsius +++================= == ===================================================== +++ +++/sys files in thermal subsystem +++------------------------------- +++ +++================= == ===================================================== +++cur_state RW file for current cooling state of the cooling device +++ (0..max_state) +++max_state RO file for maximum cooling state of the cooling device +++================= == ===================================================== ++--- a/Documentation/hwmon/index.rst +++++ b/Documentation/hwmon/index.rst ++@@ -74,6 +74,7 @@ Hardware Monitoring Kernel Drivers ++ ibmaem ++ ibm-cffps ++ ibmpowernv +++ iei-wt61p803-puzzle-hwmon ++ ina209 ++ ina2xx ++ ina3221 +diff --git a/target/linux/mvebu/patches-5.15/907-MAINTAINERS-Add-an-entry-for-the-IEI-WT61P803-PUZZLE.patch b/target/linux/mvebu/patches-5.15/907-MAINTAINERS-Add-an-entry-for-the-IEI-WT61P803-PUZZLE.patch +new file mode 100644 +index 0000000000..14b928d332 +--- /dev/null ++++ b/target/linux/mvebu/patches-5.15/907-MAINTAINERS-Add-an-entry-for-the-IEI-WT61P803-PUZZLE.patch +@@ -0,0 +1,41 @@ ++From 12479baad28d2a08c6cb9e83471057635fa1635c Mon Sep 17 00:00:00 2001 ++From: Luka Kovacic <luka.kovacic () sartura ! hr> ++Date: Tue, 24 Aug 2021 12:44:38 +0000 ++Subject: [PATCH 7/7] MAINTAINERS: Add an entry for the IEI WT61P803 PUZZLE ++ driver ++ ++Add an entry for the IEI WT61P803 PUZZLE driver (MFD, HWMON, LED drivers). ++ ++Signed-off-by: Luka Kovacic <luka.kovacic@sartura.hr> ++Signed-off-by: Pavo Banicevic <pavo.banicevic@sartura.hr> ++Cc: Luka Perkov <luka.perkov@sartura.hr> ++Cc: Robert Marko <robert.marko@sartura.hr> ++--- ++ MAINTAINERS | 16 ++++++++++++++++ ++ 1 file changed, 16 insertions(+) ++ ++--- a/MAINTAINERS +++++ b/MAINTAINERS ++@@ -9060,6 +9060,22 @@ F: include/net/nl802154.h ++ F: net/ieee802154/ ++ F: net/mac802154/ ++ +++IEI WT61P803 M801 MFD DRIVER +++M: Luka Kovacic <luka.kovacic@sartura.hr> +++M: Luka Perkov <luka.perkov@sartura.hr> +++M: Goran Medic <goran.medic@sartura.hr> +++L: linux-kernel@vger.kernel.org +++S: Maintained +++F: Documentation/ABI/stable/sysfs-driver-iei-wt61p803-puzzle +++F: Documentation/devicetree/bindings/hwmon/iei,wt61p803-puzzle-hwmon.yaml +++F: Documentation/devicetree/bindings/leds/iei,wt61p803-puzzle-leds.yaml +++F: Documentation/devicetree/bindings/mfd/iei,wt61p803-puzzle.yaml +++F: Documentation/hwmon/iei-wt61p803-puzzle-hwmon.rst +++F: drivers/hwmon/iei-wt61p803-puzzle-hwmon.c +++F: drivers/leds/leds-iei-wt61p803-puzzle.c +++F: drivers/mfd/iei-wt61p803-puzzle.c +++F: include/linux/mfd/iei-wt61p803-puzzle.h +++ ++ IFE PROTOCOL ++ M: Yotam Gigi <yotam.gi@gmail.com> ++ M: Jamal Hadi Salim <jhs@mojatatu.com> +diff --git a/target/linux/mvebu/patches-5.15/910-drivers-leds-wt61p803-puzzle-improvements.patch b/target/linux/mvebu/patches-5.15/910-drivers-leds-wt61p803-puzzle-improvements.patch +new file mode 100644 +index 0000000000..150a65498c +--- /dev/null ++++ b/target/linux/mvebu/patches-5.15/910-drivers-leds-wt61p803-puzzle-improvements.patch +@@ -0,0 +1,271 @@ ++--- a/drivers/leds/leds-iei-wt61p803-puzzle.c +++++ b/drivers/leds/leds-iei-wt61p803-puzzle.c ++@@ -9,9 +9,13 @@ ++ #include <linux/mfd/iei-wt61p803-puzzle.h> ++ #include <linux/mod_devicetable.h> ++ #include <linux/module.h> +++#include <linux/of.h> ++ #include <linux/platform_device.h> ++ #include <linux/property.h> ++ #include <linux/slab.h> +++#include <linux/workqueue.h> +++ +++#define IEI_LEDS_MAX 4 ++ ++ enum iei_wt61p803_puzzle_led_state { ++ IEI_LED_OFF = 0x30, ++@@ -33,7 +37,11 @@ struct iei_wt61p803_puzzle_led { ++ struct iei_wt61p803_puzzle *mcu; ++ unsigned char response_buffer[IEI_WT61P803_PUZZLE_BUF_SIZE]; ++ struct mutex lock; /* mutex to protect led_power_state */ +++ struct work_struct work; ++ int led_power_state; +++ int id; +++ u8 blinking; +++ bool active_low; ++ }; ++ ++ static inline struct iei_wt61p803_puzzle_led *cdev_to_iei_wt61p803_puzzle_led ++@@ -51,10 +59,18 @@ static int iei_wt61p803_puzzle_led_brigh ++ size_t reply_size; ++ int ret; ++ +++ if (priv->blinking) { +++ if (brightness == LED_OFF) +++ priv->blinking = 0; +++ else +++ return 0; +++ } +++ ++ led_power_cmd[0] = IEI_WT61P803_PUZZLE_CMD_HEADER_START; ++ led_power_cmd[1] = IEI_WT61P803_PUZZLE_CMD_LED; ++- led_power_cmd[2] = IEI_WT61P803_PUZZLE_CMD_LED_POWER; ++- led_power_cmd[3] = brightness == LED_OFF ? IEI_LED_OFF : IEI_LED_ON; +++ led_power_cmd[2] = IEI_WT61P803_PUZZLE_CMD_LED_SET(priv->id); +++ led_power_cmd[3] = ((brightness == LED_OFF) ^ priv->active_low) ? +++ IEI_LED_OFF : priv->blinking?priv->blinking:IEI_LED_ON; ++ ++ ret = iei_wt61p803_puzzle_write_command(priv->mcu, led_power_cmd, ++ sizeof(led_power_cmd), ++@@ -90,39 +106,166 @@ static enum led_brightness iei_wt61p803_ ++ return led_state; ++ } ++ +++static void iei_wt61p803_puzzle_led_apply_blink(struct work_struct *work) +++{ +++ struct iei_wt61p803_puzzle_led *priv = container_of(work, struct iei_wt61p803_puzzle_led, work); +++ unsigned char led_blink_cmd[5] = {}; +++ unsigned char resp_buf[IEI_WT61P803_PUZZLE_BUF_SIZE]; +++ size_t reply_size; +++ +++ led_blink_cmd[0] = IEI_WT61P803_PUZZLE_CMD_HEADER_START; +++ led_blink_cmd[1] = IEI_WT61P803_PUZZLE_CMD_LED; +++ led_blink_cmd[2] = IEI_WT61P803_PUZZLE_CMD_LED_SET(priv->id); +++ led_blink_cmd[3] = priv->blinking; +++ +++ iei_wt61p803_puzzle_write_command(priv->mcu, led_blink_cmd, +++ sizeof(led_blink_cmd), +++ resp_buf, +++ &reply_size); +++ +++ return; +++} +++ +++static int iei_wt61p803_puzzle_led_set_blink(struct led_classdev *cdev, +++ unsigned long *delay_on, +++ unsigned long *delay_off) +++{ +++ struct iei_wt61p803_puzzle_led *priv = cdev_to_iei_wt61p803_puzzle_led(cdev); +++ u8 blink_mode = 0; +++ int ret = 0; +++ +++ /* set defaults */ +++ if (!*delay_on && !*delay_off) { +++ *delay_on = 500; +++ *delay_off = 500; +++ } +++ +++ /* minimum delay for soft-driven blinking is 100ms to keep load low */ +++ if (*delay_on < 100) +++ *delay_on = 100; +++ +++ if (*delay_off < 100) +++ *delay_off = 100; +++ +++ /* offload blinking to hardware, if possible */ +++ if (*delay_on != *delay_off) { +++ ret = -EINVAL; +++ } else if (*delay_on == 100) { +++ blink_mode = IEI_LED_BLINK_5HZ; +++ *delay_on = 100; +++ *delay_off = 100; +++ } else if (*delay_on <= 500) { +++ blink_mode = IEI_LED_BLINK_1HZ; +++ *delay_on = 500; +++ *delay_off = 500; +++ } else { +++ ret = -EINVAL; +++ } +++ +++ mutex_lock(&priv->lock); +++ priv->blinking = blink_mode; +++ mutex_unlock(&priv->lock); +++ +++ if (blink_mode) +++ schedule_work(&priv->work); +++ +++ return ret; +++} +++ +++ +++static int iei_wt61p803_puzzle_led_set_dt_default(struct led_classdev *cdev, +++ struct device_node *np) +++{ +++ const char *state; +++ int ret = 0; +++ +++ state = of_get_property(np, "default-state", NULL); +++ if (state) { +++ if (!strcmp(state, "on")) { +++ ret = +++ iei_wt61p803_puzzle_led_brightness_set_blocking( +++ cdev, cdev->max_brightness); +++ } else { +++ ret = iei_wt61p803_puzzle_led_brightness_set_blocking( +++ cdev, LED_OFF); +++ } +++ } +++ +++ return ret; +++} +++ ++ static int iei_wt61p803_puzzle_led_probe(struct platform_device *pdev) ++ { ++ struct device *dev = &pdev->dev; +++ struct device_node *np = dev_of_node(dev); +++ struct device_node *child; ++ struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev->parent); ++ struct iei_wt61p803_puzzle_led *priv; ++- struct led_init_data init_data = {}; ++- struct fwnode_handle *child; ++ int ret; +++ u32 reg; ++ ++- if (device_get_child_node_count(dev) != 1) +++ if (device_get_child_node_count(dev) > IEI_LEDS_MAX) ++ return -EINVAL; ++ ++- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++- if (!priv) ++- return -ENOMEM; ++- ++- priv->mcu = mcu; ++- priv->led_power_state = 1; ++- mutex_init(&priv->lock); ++- dev_set_drvdata(dev, priv); ++- ++- child = device_get_next_child_node(dev, NULL); ++- init_data.fwnode = child; ++- ++- priv->cdev.brightness_set_blocking = iei_wt61p803_puzzle_led_brightness_set_blocking; ++- priv->cdev.brightness_get = iei_wt61p803_puzzle_led_brightness_get; ++- priv->cdev.max_brightness = 1; +++ for_each_available_child_of_node(np, child) { +++ struct led_init_data init_data = {}; ++ ++- ret = devm_led_classdev_register_ext(dev, &priv->cdev, &init_data); ++- if (ret) ++- dev_err(dev, "Could not register LED\n"); +++ ret = of_property_read_u32(child, "reg", ®); +++ if (ret) { +++ dev_err(dev, "Failed to read led 'reg' property\n"); +++ goto put_child_node; +++ } +++ +++ if (reg > IEI_LEDS_MAX) { +++ dev_err(dev, "Invalid led reg %u\n", reg); +++ ret = -EINVAL; +++ goto put_child_node; +++ } +++ +++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); +++ if (!priv) { +++ ret = -ENOMEM; +++ goto put_child_node; +++ } +++ +++ mutex_init(&priv->lock); +++ +++ dev_set_drvdata(dev, priv); +++ +++ if (of_property_read_bool(child, "active-low")) +++ priv->active_low = true; +++ +++ priv->mcu = mcu; +++ priv->id = reg; +++ priv->led_power_state = 1; +++ priv->blinking = 0; +++ init_data.fwnode = of_fwnode_handle(child); +++ +++ priv->cdev.brightness_set_blocking = iei_wt61p803_puzzle_led_brightness_set_blocking; +++ priv->cdev.brightness_get = iei_wt61p803_puzzle_led_brightness_get; +++ priv->cdev.blink_set = iei_wt61p803_puzzle_led_set_blink; +++ +++ priv->cdev.max_brightness = 1; +++ +++ INIT_WORK(&priv->work, iei_wt61p803_puzzle_led_apply_blink); +++ +++ ret = iei_wt61p803_puzzle_led_set_dt_default(&priv->cdev, child); +++ if (ret) { +++ dev_err(dev, "Could apply default from DT\n"); +++ goto put_child_node; +++ } +++ +++ ret = devm_led_classdev_register_ext(dev, &priv->cdev, &init_data); +++ if (ret) { +++ dev_err(dev, "Could not register LED\n"); +++ goto put_child_node; +++ } +++ } +++ +++ return ret; ++ ++- fwnode_handle_put(child); +++put_child_node: +++ of_node_put(child); ++ return ret; ++ } ++ ++--- a/include/linux/mfd/iei-wt61p803-puzzle.h +++++ b/include/linux/mfd/iei-wt61p803-puzzle.h ++@@ -36,7 +36,7 @@ ++ #define IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER_POWER_LOSS 0x41 /* A */ ++ ++ #define IEI_WT61P803_PUZZLE_CMD_LED 0x52 /* R */ ++-#define IEI_WT61P803_PUZZLE_CMD_LED_POWER 0x31 /* 1 */ +++#define IEI_WT61P803_PUZZLE_CMD_LED_SET(n) (0x30 | (n)) ++ ++ #define IEI_WT61P803_PUZZLE_CMD_TEMP 0x54 /* T */ ++ #define IEI_WT61P803_PUZZLE_CMD_TEMP_ALL 0x41 /* A */ ++--- a/drivers/mfd/iei-wt61p803-puzzle.c +++++ b/drivers/mfd/iei-wt61p803-puzzle.c ++@@ -176,6 +176,9 @@ static int iei_wt61p803_puzzle_recv_buf( ++ struct iei_wt61p803_puzzle *mcu = serdev_device_get_drvdata(serdev); ++ int ret; ++ +++ print_hex_dump_debug("puzzle-mcu rx: ", DUMP_PREFIX_NONE, +++ 16, 1, data, size, false); +++ ++ ret = iei_wt61p803_puzzle_process_resp(mcu, data, size); ++ /* Return the number of processed bytes if function returns error, ++ * discard the remaining incoming data, since the frame this data ++@@ -246,6 +249,9 @@ int iei_wt61p803_puzzle_write_command(st ++ ++ cmd[size - 1] = iei_wt61p803_puzzle_checksum(cmd, size - 1); ++ +++ print_hex_dump_debug("puzzle-mcu tx: ", DUMP_PREFIX_NONE, +++ 16, 1, cmd, size, false); +++ ++ /* Initialize reply struct */ ++ reinit_completion(&mcu->reply->received); ++ mcu->reply->size = 0; +-- +2.34.1 + -- GitLab