Browse Source

mvebu: Add basic support for WRT1900AC (v1) and Turris Omnia (pre 2019)

This adds basic support for the WRT1900AC and Turris Omnia. In order
to continue to use these as wifi routers, some or all of the wifi
modules will need to be replaced, preferably with an ath9k based
chipset. Keep in mind that not all ath9k chipsets work well in
AP mode.

WRT1900AC:

* The original issue with this router, in addition to the non-free
wifi, was an init / learning blob needed for the DDR3 memory. This
issue was resolved in 2015, but there were some stability issues.

* The Marvell wifi chipset is not supported and will need to be
removed or replaced.

* RISCi_ATOM was not able to successfully flash upstream u-boot.
It's most likely a configuration or build issue.

* libreCMC can be installed from the stock firmware web-ui using
the *-factory.img.

Turris Omnnia:

* The ath10k wifi chipset will need to be removed.

* Full support is not ready yet; it works with some hacks.

* Upstream u-boot can be built and flashed; the libreCMC
toolchain was used to build it.

Taken from upstrem openwrt-19.07 @ 153392e209c5110448db9e1e7ce9a3566f124b37
RISCi_ATOM 3 years ago
parent
commit
4eaf9e5e42
84 changed files with 7649 additions and 0 deletions
  1. 21 0
      target/linux/mvebu/Makefile
  2. 55 0
      target/linux/mvebu/base-files/etc/board.d/01_leds
  3. 71 0
      target/linux/mvebu/base-files/etc/board.d/02_network
  4. 48 0
      target/linux/mvebu/base-files/etc/diag.sh
  5. 41 0
      target/linux/mvebu/base-files/etc/hotplug.d/ieee80211/00-wifi-config-migrate
  6. 18 0
      target/linux/mvebu/base-files/etc/init.d/bootcount
  7. 56 0
      target/linux/mvebu/base-files/etc/uci-defaults/03_wireless
  8. 23 0
      target/linux/mvebu/base-files/etc/uci-defaults/04_mambafan
  9. 46 0
      target/linux/mvebu/base-files/lib/preinit/06_set_iface_mac
  10. 26 0
      target/linux/mvebu/base-files/lib/preinit/79_move_config
  11. 37 0
      target/linux/mvebu/base-files/lib/preinit/81_linksys_syscfg
  12. 98 0
      target/linux/mvebu/base-files/lib/upgrade/linksys.sh
  13. 46 0
      target/linux/mvebu/base-files/lib/upgrade/platform.sh
  14. 113 0
      target/linux/mvebu/base-files/lib/upgrade/sdcard.sh
  15. 28 0
      target/linux/mvebu/base-files/sbin/fan_ctrl.sh
  16. 498 0
      target/linux/mvebu/config-4.14
  17. 14 0
      target/linux/mvebu/cortexa9/target.mk
  18. 207 0
      target/linux/mvebu/files-4.14/arch/arm/boot/dts/armada-385-linksys-venom.dts
  19. 28 0
      target/linux/mvebu/files-4.14/arch/arm64/boot/dts/marvell/armada-3720-espressobin-emmc.dts
  20. 43 0
      target/linux/mvebu/files-4.14/arch/arm64/boot/dts/marvell/armada-3720-espressobin-v7-emmc.dts
  21. 31 0
      target/linux/mvebu/files-4.14/arch/arm64/boot/dts/marvell/armada-3720-espressobin-v7.dts
  22. 114 0
      target/linux/mvebu/image/Makefile
  23. 23 0
      target/linux/mvebu/image/clearfog.bootscript
  24. 46 0
      target/linux/mvebu/image/cortex-a9.mk
  25. 84 0
      target/linux/mvebu/image/gen_mvebu_sdcard_img.sh
  26. 16 0
      target/linux/mvebu/image/generic-arm64.bootscript
  27. 770 0
      target/linux/mvebu/patches-4.14/002-add_powertables.patch
  28. 40 0
      target/linux/mvebu/patches-4.14/003-add_switch_nodes.patch
  29. 39 0
      target/linux/mvebu/patches-4.14/004-add_sata_disk_activity_trigger.patch
  30. 17 0
      target/linux/mvebu/patches-4.14/005-linksys_hardcode_nand_ecc_settings.patch
  31. 201 0
      target/linux/mvebu/patches-4.14/006-mvebu-Mangle-bootloader-s-kernel-arguments.patch
  32. 60 0
      target/linux/mvebu/patches-4.14/100-find_active_root.patch
  33. 15 0
      target/linux/mvebu/patches-4.14/102-revert_i2c_delay.patch
  34. 13 0
      target/linux/mvebu/patches-4.14/103-remove-nand-driver-bug.patch
  35. 10 0
      target/linux/mvebu/patches-4.14/104-linksys_mamba_disable_keep_config.patch
  36. 69 0
      target/linux/mvebu/patches-4.14/110-pxa3xxx_revert_irq_thread.patch
  37. 19 0
      target/linux/mvebu/patches-4.14/205-armada-385-rd-mtd-partitions.patch
  38. 35 0
      target/linux/mvebu/patches-4.14/206-ARM-mvebu-385-ap-Add-partitions.patch
  39. 21 0
      target/linux/mvebu/patches-4.14/210-clearfog_switch_node.patch
  40. 30 0
      target/linux/mvebu/patches-4.14/220-disable-untested-dsa-boards.patch
  41. 10 0
      target/linux/mvebu/patches-4.14/230-armada-xp-linksys-mamba-broken-idle.patch
  42. 35 0
      target/linux/mvebu/patches-4.14/300-mvneta-tx-queue-workaround.patch
  43. 40 0
      target/linux/mvebu/patches-4.14/400-cpuidle-mvebu-indicate-failure-to-enter-deeper-sleep.patch
  44. 60 0
      target/linux/mvebu/patches-4.14/401-pci-mvebu-time-out-reset-on-link-up.patch
  45. 290 0
      target/linux/mvebu/patches-4.14/402-sfp-display-SFP-module-information.patch
  46. 979 0
      target/linux/mvebu/patches-4.14/403-net-mvneta-convert-to-phylink.patch
  47. 28 0
      target/linux/mvebu/patches-4.14/404-net-mvneta-hack-fix-phy_interface.patch
  48. 56 0
      target/linux/mvebu/patches-4.14/405-net-mvneta-disable-MVNETA_CAUSE_PSC_SYNC_CHANGE-inte.patch
  49. 44 0
      target/linux/mvebu/patches-4.14/406-net-mvneta-add-module-EEPROM-reading-support.patch
  50. 80 0
      target/linux/mvebu/patches-4.14/407-phy-fixed-phy-remove-fixed_phy_update_state.patch
  51. 181 0
      target/linux/mvebu/patches-4.14/408-sfp-move-module-eeprom-ethtool-access-into-netdev-co.patch
  52. 34 0
      target/linux/mvebu/patches-4.14/409-sfp-use-netdev-sfp_bus-for-start-stop.patch
  53. 132 0
      target/linux/mvebu/patches-4.14/410-sfp-hack-allow-marvell-10G-phy-support-to-use-SFP.patch
  54. 24 0
      target/linux/mvebu/patches-4.14/411-sfp-add-sfp-compatible.patch
  55. 87 0
      target/linux/mvebu/patches-4.14/412-ARM-dts-armada388-clearfog-emmc-on-clearfog-base.patch
  56. 42 0
      target/linux/mvebu/patches-4.14/413-ARM-dts-armada388-clearfog-increase-speed-of-i2c0-to.patch
  57. 81 0
      target/linux/mvebu/patches-4.14/414-ARM-dts-armada388-clearfog-add-SFP-module-support.patch
  58. 124 0
      target/linux/mvebu/patches-4.14/415-ARM-dts-armada388-clearfog-document-MPP-usage.patch
  59. 143 0
      target/linux/mvebu/patches-4.14/420-rtc-armada38x-add-support-for-trimming-the-RTC.patch
  60. 73 0
      target/linux/mvebu/patches-4.14/421-rtc-armada38x-reset-after-rtc-power-loss.patch
  61. 28 0
      target/linux/mvebu/patches-4.14/423-ARM-dts-armada-385-linksys-Disable-internal-RTC.patch
  62. 94 0
      target/linux/mvebu/patches-4.14/450-reprobe_sfp_phy.patch
  63. 70 0
      target/linux/mvebu/patches-4.14/501-spi-a3700-Change-SPI-mode-before-asserting-chip-sele.patch
  64. 27 0
      target/linux/mvebu/patches-4.14/502-arm64-dts-marvell-armada-37xx-add-UART-clock.patch
  65. 78 0
      target/linux/mvebu/patches-4.14/503-clk-mvebu-armada-37xx-periph-cosmetic-changes.patch
  66. 178 0
      target/linux/mvebu/patches-4.14/504-clk-mvebu-armada-37xx-periph-prepare-cpu-clk-to-be-u.patch
  67. 315 0
      target/linux/mvebu/patches-4.14/505-clk-mvebu-armada-37xx-periph-add-DVFS-support-for-cp.patch
  68. 297 0
      target/linux/mvebu/patches-4.14/506-cpufreq-Add-DVFS-support-for-Armada-37xx.patch
  69. 48 0
      target/linux/mvebu/patches-4.14/507-arm64-dts-marvell-armada-37xx-add-nodes-allowing-cpu.patch
  70. 56 0
      target/linux/mvebu/patches-4.14/508-arm64-dts-armada-3720-espressobin-wire-up-spi-flash.patch
  71. 35 0
      target/linux/mvebu/patches-4.14/509-cpufreq-armada-37xx-Fix-clock-leak.patch
  72. 92 0
      target/linux/mvebu/patches-4.14/510-clk-mvebu-armada-37xx-periph-Fix-switching-CPU-rate-.patch
  73. 33 0
      target/linux/mvebu/patches-4.14/511-clk-mvebu-armada-37xx-periph-Fix-wrong-return-value-.patch
  74. 33 0
      target/linux/mvebu/patches-4.14/512-clk-mvebu-armada-37xx-periph-Remove-unused-var-num_p.patch
  75. 40 0
      target/linux/mvebu/patches-4.14/513-arm64-dts-marvell-armada37xx-Add-emmc-sdio-pinctrl-d.patch
  76. 49 0
      target/linux/mvebu/patches-4.14/514-arm64-dts-marvell-armada-37xx-Enable-emmc-on-espress.patch
  77. 20 0
      target/linux/mvebu/patches-4.14/520-arm64-dts-marvell-armada37xx-Add-eth0-alias.patch
  78. 58 0
      target/linux/mvebu/patches-4.14/521-arm64-dts-armada-3720-espressobin-correct-spi-node.patch
  79. 26 0
      target/linux/mvebu/patches-4.14/522-arm64-dts-marvell-armada-3720-espressobin-add-ports-.patch
  80. 138 0
      target/linux/mvebu/patches-4.14/524-PCI-aardvark-set-host-and-device-to-the-same-MAX-payload-size.patch
  81. 55 0
      target/linux/mvebu/patches-4.14/526-PCI-aardvark-disable-LOS-state-by-default.patch
  82. 43 0
      target/linux/mvebu/patches-4.14/527-PCI-aardvark-allow-to-specify-link-capability.patch
  83. 73 0
      target/linux/mvebu/patches-4.14/528-arm64-dts-armada-3720-espressobin-set-max-link-to-ge.patch
  84. 50 0
      target/linux/mvebu/patches-4.14/529-armada388-clearfog-enable-spi-flash.patch

+ 21 - 0
target/linux/mvebu/Makefile

@@ -0,0 +1,21 @@
+#
+# Copyright (C) 2012-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+BOARD:=mvebu
+BOARDNAME:=Marvell EBU Armada
+FEATURES:=fpu usb pci pcie gpio nand squashfs ramdisk boot-part rootfs-part
+SUBTARGETS:=cortexa9
+MAINTAINER:=Imre Kaloz <kaloz@openwrt.org>
+
+KERNEL_PATCHVER:=4.14
+
+include $(INCLUDE_DIR)/target.mk
+
+DEFAULT_PACKAGES += uboot-envtools kmod-gpio-button-hotplug
+
+$(eval $(call BuildTarget))

+ 55 - 0
target/linux/mvebu/base-files/etc/board.d/01_leds

@@ -0,0 +1,55 @@
+#!/bin/sh
+#
+# Copyright (C) 2014-2016 OpenWrt.org
+# Copyright (C) 2016 LEDE-Project.org
+#
+
+. /lib/functions/uci-defaults.sh
+
+board_config_update
+
+board=$(board_name)
+
+case "$board" in
+linksys,caiman)
+	ucidef_set_led_netdev "wan" "WAN" "pca963x:caiman:white:wan" "eth1"
+	ucidef_set_led_usbport "usb1" "USB 1" "pca963x:caiman:white:usb2" "usb1-port1"
+	ucidef_set_led_usbport "usb2" "USB 2" "pca963x:caiman:white:usb3_1" "usb2-port1" "usb3-port1"
+	ucidef_set_led_usbport "usb2_ss" "USB 2 SS" "pca963x:caiman:white:usb3_2" "usb3-port1"
+	;;
+linksys,cobra)
+	ucidef_set_led_netdev "wan" "WAN" "pca963x:cobra:white:wan" "eth1"
+	ucidef_set_led_usbport "usb1" "USB 1" "pca963x:cobra:white:usb2" "usb1-port1"
+	ucidef_set_led_usbport "usb2" "USB 2" "pca963x:cobra:white:usb3_1" "usb2-port1" "usb3-port1"
+	ucidef_set_led_usbport "usb2_ss" "USB 2 SS" "pca963x:cobra:white:usb3_2" "usb3-port1"
+	;;
+linksys,mamba)
+	ucidef_set_led_netdev "wan" "WAN" "mamba:white:wan" "eth1"
+	ucidef_set_led_usbport "usb1" "USB 1" "mamba:white:usb2" "usb1-port1"
+	ucidef_set_led_usbport "usb2" "USB 2" "mamba:white:usb3_1" "usb2-port1" "usb3-port1"
+	ucidef_set_led_usbport "usb2_ss" "USB 2 SS" "mamba:white:usb3_2" "usb3-port2"
+	;;
+linksys,rango)
+	ucidef_set_led_netdev "wan" "WAN" "pca963x:rango:white:wan" "eth1"
+	ucidef_set_led_usbport "usb1" "USB 1" "pca963x:rango:white:usb2" "usb1-port1"
+	ucidef_set_led_usbport "usb2" "USB 2" "pca963x:rango:white:usb3_1" "usb2-port1" "usb3-port1"
+	ucidef_set_led_usbport "usb2_ss" "USB 2 SS" "pca963x:rango:white:usb3_2" "usb3-port1"
+	;;
+linksys,shelby)
+	ucidef_set_led_netdev "wan" "WAN" "pca963x:shelby:white:wan" "eth1"
+	ucidef_set_led_usbport "usb1" "USB 1" "pca963x:shelby:white:usb2" "usb1-port1"
+	ucidef_set_led_usbport "usb2" "USB 2" "pca963x:shelby:white:usb3_1" "usb2-port1" "usb3-port1"
+	ucidef_set_led_usbport "usb2_ss" "USB 2 SS" "pca963x:shelby:white:usb3_2" "usb3-port1"
+	;;
+linksys,venom)
+	ucidef_set_led_netdev "wan" "WAN" "pca963x:venom:blue:wan" "eth1"
+	ucidef_set_led_usbport "usb1" "USB 1" "pca963x:venom:blue:usb2" "usb1-port1"
+	ucidef_set_led_usbport "usb2" "USB 2" "pca963x:venom:blue:usb3_1" "usb2-port1" "usb3-port1"
+	ucidef_set_led_usbport "usb2_ss" "USB 2 SS" "pca963x:venom:blue:usb3_2" "usb3-port1"
+	;;
+
+esac
+
+board_config_flush
+
+exit 0

+ 71 - 0
target/linux/mvebu/base-files/etc/board.d/02_network

@@ -0,0 +1,71 @@
+#!/bin/sh
+#
+# Copyright (C) 2014-2016 OpenWrt.org
+# Copyright (C) 2016 LEDE-Project.org
+#
+
+. /lib/functions/uci-defaults.sh
+
+board_config_update
+
+board=$(board_name)
+
+case "$board" in
+cznic,turris-omnia)
+	ucidef_set_interface_lan "lan0 lan1 lan2 lan3 lan4"
+	ucidef_set_interface_wan "eth2"
+	;;
+globalscale,espressobin|\
+globalscale,espressobin-emmc|\
+globalscale,espressobin-v7|\
+globalscale,espressobin-v7-emmc)
+	ucidef_set_interfaces_lan_wan "lan0 lan1" "wan"
+	;;
+linksys,caiman|\
+linksys,cobra|\
+linksys,mamba|\
+linksys,rango|\
+linksys,shelby|\
+linksys,venom)
+	ucidef_set_interfaces_lan_wan "eth0.1" "eth1.2"
+	ucidef_add_switch "switch0" \
+		"0:lan:4" "1:lan:3" "2:lan:2" "3:lan:1" "5@eth0" "4:wan" "6@eth1"
+	;;
+marvell,a385-db-ap)
+	ucidef_set_interfaces_lan_wan "eth0 eth1" "eth2"
+	;;
+marvell,armada8040-mcbin)
+	ucidef_set_interfaces_lan_wan "eth0 eth1 eth3" "eth2"
+	;;
+marvell,armada8040-db)
+	ucidef_set_interfaces_lan_wan "eth0 eth2 eth3" "eth1"
+	;;
+marvell,armada7040-db)
+	ucidef_set_interfaces_lan_wan "eth0 eth2" "eth1"
+	;;
+marvell,armada-3720-db)
+	ucidef_set_interfaces_lan_wan "eth1" "eth0"
+	;;
+marvell,axp-gp)
+	ucidef_set_interface_lan "eth0 eth1 eth2 eth3"
+	;;
+solidrun,clearfog*a1)
+	# eth0 is standalone ethernet
+	# eth1 is switch (-pro) or standalone ethernet (-base)
+	# eth2 is SFP
+	ucidef_set_interfaces_lan_wan "eth1" "eth0 eth2"
+
+	# if switch exists (clearfog-pro)
+	# switch port 5 is connected to eth1
+	swconfig list 2>&1 | grep -q switch0 && \
+		ucidef_add_switch "switch0" \
+			"0:lan:5" "1:lan:4" "2:lan:3" "3:lan:2" "4:lan:1" "5u@eth1" "6:lan:6"
+	;;
+*)
+	ucidef_set_interface_lan "eth0"
+	;;
+esac
+
+board_config_flush
+
+exit 0

+ 48 - 0
target/linux/mvebu/base-files/etc/diag.sh

@@ -0,0 +1,48 @@
+#!/bin/sh
+# Copyright (C) 2014-2016 OpenWrt.org
+# Copyright (C) 2016 LEDE-Project.org
+
+. /lib/functions.sh
+. /lib/functions/leds.sh
+
+get_status_led() {
+	case $(board_name) in
+	linksys,caiman)
+		status_led="caiman:white:power"
+		;;
+	linksys,cobra)
+		status_led="cobra:white:power"
+		;;
+	linksys,mamba)
+		status_led="mamba:white:power"
+		;;
+	linksys,rango)
+		status_led="rango:white:power"
+		;;
+	linksys,shelby)
+		status_led="shelby:white:power"
+		;;
+	linksys,venom)
+		status_led="venom:blue:power"
+		;;
+	esac
+}
+
+set_state() {
+	get_status_led
+
+	case "$1" in
+	preinit)
+		status_led_blink_preinit
+		;;
+	failsafe)
+		status_led_blink_failsafe
+		;;
+	preinit_regular)
+		status_led_blink_preinit_regular
+		;;
+	done)
+		status_led_on
+		;;
+	esac
+}

+ 41 - 0
target/linux/mvebu/base-files/etc/hotplug.d/ieee80211/00-wifi-config-migrate

@@ -0,0 +1,41 @@
+#!/bin/sh
+
+# The pcie-controller device was renamed to pcie in Linux kernel 4.14
+# commit 28fbb9c539e2 ("ARM: dts: marvell: fix PCI bus dtc warnings").
+# This script migrates the path in the UCI configuration from the old
+# name to the new name and also back, when am upgrade or downgrade is
+# done. It checks if the name exists before changing the configuration.
+# This has to be done before the 10-wifi-detect script from mac80211 is
+# executed because this would add the devices again under the new path
+# name.
+
+. /lib/functions.sh
+
+PATH_CHANGED=0
+
+rename_wifi_path() {
+	local path_old=$(uci get wireless.${1}.path)
+	local path_new=$(echo ${path_old} | sed "${2}")
+
+	if [ -e "/sys/devices/platform/${path_new}" ] && [ ${path_old} != ${path_new} ]
+	then 
+		uci set wireless.${1}.path=${path_new}
+		PATH_CHANGED=1
+	fi
+}
+
+rename_wifi_path_list() {
+	# migration from kernel 4.9 to 4.14
+	rename_wifi_path $1 "s/soc:pcie-controller/soc:pcie/"
+	# migration from kernel 4.14 to 4.9
+	rename_wifi_path $1 "s/soc:pcie/soc:pcie-controller/"
+}
+
+[ "${ACTION}" = "add" ] && {
+	[ ! -e /etc/config/wireless ] && return
+
+	config_load wireless
+	config_foreach rename_wifi_path_list wifi-device
+
+	[ "$PATH_CHANGED" = "1" ] && uci commit wireless
+}

+ 18 - 0
target/linux/mvebu/base-files/etc/init.d/bootcount

@@ -0,0 +1,18 @@
+#!/bin/sh /etc/rc.common
+
+START=99
+
+start() {
+	. /lib/functions.sh
+
+	case $(board_name) in
+	linksys,caiman |\
+	linksys,cobra |\
+	linksys,mamba |\
+	linksys,rango |\
+	linksys,shelby |\
+	linksys,venom)
+		mtd resetbc s_env || true
+		;;
+	esac
+}

+ 56 - 0
target/linux/mvebu/base-files/etc/uci-defaults/03_wireless

@@ -0,0 +1,56 @@
+#!/bin/sh
+#
+# Copyright (C) 2015 OpenWrt.org
+#
+
+[ ! -e /etc/config/wireless ] && exit 0
+
+. /lib/functions.sh
+. /lib/functions/system.sh
+
+board=$(board_name)
+
+case "$board" in
+linksys,caiman|linksys,cobra|linksys,mamba|linksys,shelby|linksys,venom)
+	SKU=$(strings /dev/mtd3|sed -ne 's/^cert_region=//p')
+	WIFIMAC2G=$(macaddr_add $(cat /sys/class/net/eth0/address) +1)
+	WIFIMAC5G=$(macaddr_add $WIFIMAC2G +1)
+	case "$SKU" in
+		AP)
+			REGD=CN
+		;;
+		AU)
+			REGD=AU
+		;;
+		CA)
+			REGD=CA
+		;;
+		EU)
+			REGD=DE
+		;;
+		US)
+			REGD=US
+		;;
+	esac
+
+	case "$board" in
+		linksys,mamba)
+			WIFIMAC0=$WIFIMAC2G
+			WIFIMAC1=$WIFIMAC5G
+		;;
+		*)
+			WIFIMAC0=$WIFIMAC5G
+			WIFIMAC1=$WIFIMAC2G
+		;;
+	esac
+
+	uci get wireless.radio0.country || uci set wireless.radio0.country=$REGD
+	uci get wireless.@wifi-iface[0].macaddr || uci set wireless.@wifi-iface[0].macaddr=$WIFIMAC0
+	uci get wireless.radio1.country || uci set wireless.radio1.country=$REGD
+	uci get wireless.@wifi-iface[1].macaddr || uci set wireless.@wifi-iface[1].macaddr=$WIFIMAC1
+	;;
+esac
+
+uci commit wireless
+
+exit 0

+ 23 - 0
target/linux/mvebu/base-files/etc/uci-defaults/04_mambafan

@@ -0,0 +1,23 @@
+#!/bin/sh
+#
+# Copyright (C) 2017 LEDE-Project.org
+#
+
+. /lib/functions.sh
+
+board=$(board_name)
+
+case "$board" in
+linksys,mamba)
+	# Set fan script execution in crontab
+	grep -s -q fan_ctrl.sh /etc/crontabs/root && exit 0
+
+	echo "# mamba fan script runs every 5 minutes" >> /etc/crontabs/root
+	echo "*/5 * * * * /sbin/fan_ctrl.sh" >> /etc/crontabs/root
+
+	# Execute one time after initial flash (instead of waiting 5 min for cron)
+	/sbin/fan_ctrl.sh
+	;;
+esac
+
+exit 0

+ 46 - 0
target/linux/mvebu/base-files/lib/preinit/06_set_iface_mac

@@ -0,0 +1,46 @@
+#
+# Copyright (C) 2014-2015 OpenWrt.org
+# Copyright (C) 2016 LEDE-Project.org
+#
+
+preinit_set_mac_address() {
+	local mac
+
+	. /lib/functions.sh
+
+	case $(board_name) in
+	linksys,caiman|linksys,cobra|linksys,rango|linksys,shelby|linksys,venom)
+		# rename interfaces back to the way they were with 4.4
+		case "$(readlink /sys/class/net/eth0)" in
+			*f1070000*)
+				ip link set eth0 name tmp0
+				ip link set eth1 name eth0
+				ip link set tmp0 name eth1
+			;;
+		esac
+
+		mac=$(mtd_get_mac_ascii devinfo hw_mac_addr)
+		mac_wan=$(macaddr_setbit_la "$mac")
+		ip link set dev eth1 address $mac 2>/dev/null
+		ip link set dev eth0 address $mac_wan 2>/dev/null
+		;;
+	linksys,mamba)
+		mac=$(mtd_get_mac_ascii devinfo hw_mac_addr)
+		ip link set dev eth0 address $mac 2>/dev/null
+		ip link set dev eth1 address $mac 2>/dev/null
+		;;
+	marvell,a385-db-ap|solidrun,clearfog*a1)
+		# rename interfaces back to the way they were with 4.4
+		case "$(readlink /sys/class/net/eth0)" in
+			*f1070000*)
+				ip link set eth0 name tmp0
+				ip link set eth1 name eth0
+				ip link set eth2 name eth1
+				ip link set tmp0 name eth2
+			;;
+		esac
+		;;
+	esac
+}
+
+boot_hook_add preinit_main preinit_set_mac_address

+ 26 - 0
target/linux/mvebu/base-files/lib/preinit/79_move_config

@@ -0,0 +1,26 @@
+#!/bin/sh
+# Copyright (C) 2015 OpenWrt.org
+
+. /lib/functions.sh
+. /lib/upgrade/common.sh
+
+move_config() {
+	local partdev
+
+	if export_bootdevice && export_partdevice partdev 1; then
+		case $(board_name) in
+			cznic,turris-omnia)
+			insmod nls_cp437
+			insmod nls_iso8859-1
+			insmod fat
+			insmod vfat
+			;;
+		esac
+		mkdir -p /boot
+		mount -o rw,noatime "/dev/$partdev" /boot
+		[ -f "/boot/$BACKUP_FILE" ] && mv -f "/boot/$BACKUP_FILE" /
+		umount /boot
+	fi
+}
+
+boot_hook_add preinit_mount_root move_config

+ 37 - 0
target/linux/mvebu/base-files/lib/preinit/81_linksys_syscfg

@@ -0,0 +1,37 @@
+#
+# Copyright (C) 2014-2016 OpenWrt.org
+# Copyright (C) 2016 LEDE-Project.org
+#
+
+preinit_mount_syscfg() {
+	. /lib/functions.sh
+	. /lib/upgrade/common.sh
+
+	case $(board_name) in
+	linksys,caiman|linksys,cobra|linksys,mamba|linksys,rango|linksys,shelby|linksys,venom)
+		needs_recovery=0
+		syscfg_part=$(grep syscfg /proc/mtd |cut -c4)
+		ubiattach -m $syscfg_part || needs_recovery=1
+		if [ $needs_recovery -eq 1 ]
+		then
+			echo "ubifs syscfg partition is damaged, reformatting"
+			ubidetach -m $syscfg_part
+			ubiformat -y -O 2048 -q /dev/mtd$syscfg_part
+			ubiattach -m $syscfg_part
+			ubimkvol /dev/ubi1 -n 0 -N syscfg -t dynamic --maxavsize
+		fi
+		mkdir /tmp/syscfg
+		mount -t ubifs ubi1:syscfg /tmp/syscfg
+		[ -f "/tmp/syscfg/$BACKUP_FILE" ] && {
+		echo "- config restore -"
+		cd /
+		mv "/tmp/syscfg/$BACKUP_FILE" /tmp
+		tar xzf "/tmp/$BACKUP_FILE"
+		rm -f "/tmp/$BACKUP_FILE"
+		sync
+		}
+		;;
+	esac
+}
+
+boot_hook_add preinit_main preinit_mount_syscfg

+ 98 - 0
target/linux/mvebu/base-files/lib/upgrade/linksys.sh

@@ -0,0 +1,98 @@
+#
+# Copyright (C) 2014-2015 OpenWrt.org
+#
+
+linksys_get_target_firmware() {
+
+	local cur_boot_part mtd_ubi0
+
+	cur_boot_part=`/usr/sbin/fw_printenv -n boot_part`
+	if [ -z "${cur_boot_part}" ] ; then
+		mtd_ubi0=$(cat /sys/devices/virtual/ubi/ubi0/mtd_num)
+		case $(egrep ^mtd${mtd_ubi0}: /proc/mtd | cut -d '"' -f 2) in
+		kernel1|rootfs1)
+			cur_boot_part=1
+			;;
+		kernel2|rootfs2)
+			cur_boot_part=2
+			;;
+		esac
+		>&2 printf "Current boot_part='%s' selected from ubi0/mtd_num='%s'" \
+			"${cur_boot_part}" "${mtd_ubi0}"
+	fi
+
+	case $cur_boot_part in
+	1)
+		fw_setenv -s - <<-EOF
+			boot_part 2
+			bootcmd "run altnandboot"
+		EOF
+		printf "kernel2"
+		return
+		;;
+	2)
+		fw_setenv -s - <<-EOF
+			boot_part 1
+			bootcmd "run nandboot"
+		EOF
+		printf "kernel1"
+		return
+		;;
+	*)
+		return
+		;;
+	esac
+}
+
+linksys_get_root_magic() {
+	(get_image "$@" | dd skip=786432 bs=4 count=1 | hexdump -v -n 4 -e '1/1 "%02x"') 2>/dev/null
+}
+
+platform_do_upgrade_linksys() {
+	local magic_long="$(get_magic_long "$1")"
+
+	mkdir -p /var/lock
+	local part_label="$(linksys_get_target_firmware)"
+	touch /var/lock/fw_printenv.lock
+
+	if [ ! -n "$part_label" ]
+	then
+		echo "cannot find target partition"
+		exit 1
+	fi
+
+	local target_mtd=$(find_mtd_part $part_label)
+
+	[ "$magic_long" = "73797375" ] && {
+		CI_KERNPART="$part_label"
+		if [ "$part_label" = "kernel1" ]
+		then
+			CI_UBIPART="rootfs1"
+		else
+			CI_UBIPART="rootfs2"
+		fi
+
+		nand_upgrade_tar "$1"
+	}
+	[ "$magic_long" = "27051956" -o "$magic_long" = "0000a0e1" ] && {
+		# check firmwares' rootfs types
+		local target_mtd=$(find_mtd_part $part_label)
+		local oldroot="$(linksys_get_root_magic $target_mtd)"
+		local newroot="$(linksys_get_root_magic "$1")"
+
+		if [ "$newroot" = "55424923" -a "$oldroot" = "55424923" ]
+		# we're upgrading from a firmware with UBI to one with UBI
+		then
+			# erase everything to be safe
+			mtd erase $part_label
+			get_image "$1" | mtd -n write - $part_label
+		else
+			get_image "$1" | mtd write - $part_label
+		fi
+	}
+}
+
+platform_copy_config_linksys() {
+	cp -f "$UPGRADE_BACKUP" "/tmp/syscfg/$BACKUP_FILE"
+	sync
+}

+ 46 - 0
target/linux/mvebu/base-files/lib/upgrade/platform.sh

@@ -0,0 +1,46 @@
+#
+# Copyright (C) 2014-2016 OpenWrt.org
+# Copyright (C) 2016 LEDE-Project.org
+#
+
+RAMFS_COPY_BIN='fw_printenv fw_setenv'
+RAMFS_COPY_DATA='/etc/fw_env.config /var/lock/fw_printenv.lock'
+REQUIRE_IMAGE_METADATA=1
+
+platform_check_image() {
+	case "$(board_name)" in
+	cznic,turris-omnia|globalscale,espressobin|globalscale,espressobin-emmc|globalscale,espressobin-v7|globalscale,espressobin-v7-emmc|\
+	marvell,armada8040-mcbin|solidrun,clearfog-base-a1|solidrun,clearfog-pro-a1)
+		platform_check_image_sdcard "$1"
+		;;
+	*)
+		return 0
+		;;
+	esac
+}
+
+platform_do_upgrade() {
+	case "$(board_name)" in
+	linksys,caiman|linksys,cobra|linksys,mamba|linksys,rango|linksys,shelby|linksys,venom)
+		platform_do_upgrade_linksys "$1"
+		;;
+	cznic,turris-omnia|globalscale,espressobin|globalscale,espressobin-emmc|globalscale,espressobin-v7|globalscale,espressobin-v7-emmc|\
+	marvell,armada8040-mcbin|solidrun,clearfog-base-a1|solidrun,clearfog-pro-a1)
+		platform_do_upgrade_sdcard "$1"
+		;;
+	*)
+		default_do_upgrade "$1"
+		;;
+	esac
+}
+platform_copy_config() {
+	case "$(board_name)" in
+	linksys,caiman|linksys,cobra|linksys,mamba|linksys,rango|linksys,shelby|linksys,venom)
+		platform_copy_config_linksys
+		;;
+	cznic,turris-omnia|globalscale,espressobin|globalscale,espressobin-emmc|globalscale,espressobin-v7|globalscale,espressobin-v7-emmc|\
+	marvell,armada8040-mcbin|solidrun,clearfog-base-a1|solidrun,clearfog-pro-a1)
+		platform_copy_config_sdcard
+		;;
+	esac
+}

+ 113 - 0
target/linux/mvebu/base-files/lib/upgrade/sdcard.sh

@@ -0,0 +1,113 @@
+get_magic_at() {
+	local file="$1"
+	local pos="$2"
+	get_image "$file" | dd bs=1 count=2 skip="$pos" 2>/dev/null | hexdump -v -n 2 -e '1/1 "%02x"'
+}
+
+platform_check_image_sdcard() {
+	local file="$1"
+	local magic diskdev partdev diff
+
+	magic=$(get_magic_at "$file" 510)
+	[ "$magic" != "55aa" ] && {
+		echo "Failed to verify MBR boot signature."
+		return 1
+	}
+
+	export_bootdevice && export_partdevice diskdev 0 || {
+		echo "Unable to determine upgrade device"
+	return 1
+	}
+
+	get_partitions "/dev/$diskdev" bootdisk
+
+	#extract the boot sector from the image
+	get_image "$@" | dd of=/tmp/image.bs count=1 bs=512b 2>/dev/null
+
+	get_partitions /tmp/image.bs image
+
+	#compare tables
+	diff="$(grep -F -x -v -f /tmp/partmap.bootdisk /tmp/partmap.image)"
+
+	rm -f /tmp/image.bs /tmp/partmap.bootdisk /tmp/partmap.image
+
+	if [ -n "$diff" ]; then
+		echo "Partition layout has changed. Full image will be written."
+		ask_bool 0 "Abort" && exit 1
+		return 0
+	fi
+}
+
+platform_do_upgrade_sdcard() {
+	local board=$(board_name)
+	local diskdev partdev diff
+
+	export_bootdevice && export_partdevice diskdev 0 || {
+		echo "Unable to determine upgrade device"
+	return 1
+	}
+
+	sync
+
+	if [ "$UPGRADE_OPT_SAVE_PARTITIONS" = "1" ]; then
+		get_partitions "/dev/$diskdev" bootdisk
+
+		#extract the boot sector from the image
+		get_image "$@" | dd of=/tmp/image.bs count=1 bs=512b
+
+		get_partitions /tmp/image.bs image
+
+		#compare tables
+		diff="$(grep -F -x -v -f /tmp/partmap.bootdisk /tmp/partmap.image)"
+	else
+		diff=1
+	fi
+
+	if [ -n "$diff" ]; then
+		get_image "$@" | dd of="/dev/$diskdev" bs=4096 conv=fsync
+
+		# Separate removal and addtion is necessary; otherwise, partition 1
+		# will be missing if it overlaps with the old partition 2
+		partx -d - "/dev/$diskdev"
+		partx -a - "/dev/$diskdev"
+	else
+		#write uboot image
+		get_image "$@" | dd of="$diskdev" bs=512 skip=1 seek=1 count=2048 conv=fsync
+		#iterate over each partition from the image and write it to the boot disk
+		while read part start size; do
+			if export_partdevice partdev $part; then
+				echo "Writing image to /dev/$partdev..."
+				get_image "$@" | dd of="/dev/$partdev" ibs="512" obs=1M skip="$start" count="$size" conv=fsync
+			else
+				echo "Unable to find partition $part device, skipped."
+			fi
+		done < /tmp/partmap.image
+
+		#copy partition uuid
+		echo "Writing new UUID to /dev/$diskdev..."
+		get_image "$@" | dd of="/dev/$diskdev" bs=1 skip=440 count=4 seek=440 conv=fsync
+	fi
+
+	case "$board" in
+	cznic,turris-omnia)
+		fw_setenv openwrt_bootargs 'earlyprintk console=ttyS0,115200 root=/dev/mmcblk0p2 rootfstype=auto rootwait'
+		fw_setenv openwrt_mmcload 'setenv bootargs "$openwrt_bootargs cfg80211.freg=$regdomain"; fatload mmc 0 0x01000000 zImage; fatload mmc 0 0x02000000 armada-385-turris-omnia.dtb'
+		fw_setenv factory_mmcload 'setenv bootargs "$bootargs cfg80211.freg=$regdomain"; btrload mmc 0 0x01000000 boot/zImage @; btrload mmc 0 0x02000000 boot/dtb @'
+		fw_setenv mmcboot 'run openwrt_mmcload || run factory_mmcload; bootz 0x01000000 - 0x02000000'
+		;;
+	esac
+
+	sleep 1
+}
+
+platform_copy_config_sdcard() {
+	local partdev
+
+	if export_partdevice partdev 1; then
+		mkdir -p /boot
+		[ -f /boot/kernel.img ] || mount -o rw,noatime /dev/$partdev /boot
+		cp -af "$UPGRADE_BACKUP" "/boot/$BACKUP_FILE"
+		sync
+		umount /boot
+	fi
+}

+ 28 - 0
target/linux/mvebu/base-files/sbin/fan_ctrl.sh

@@ -0,0 +1,28 @@
+#!/bin/sh
+
+CPU_TEMP=`cut -c1-2 /sys/class/hwmon/hwmon2/temp1_input`
+DDR_TEMP=`cut -c1-2 /sys/class/hwmon/hwmon1/temp1_input`
+WIFI_TEMP=`cut -c1-2 /sys/class/hwmon/hwmon1/temp2_input`
+
+CPU_LOW=85
+CPU_HIGH=95
+DDR_LOW=65
+DDR_HIGH=75
+WIFI_LOW=100
+WIFI_HIGH=115
+
+if [ -d /sys/devices/pwm_fan ];then
+	FAN_CTRL=/sys/devices/pwm_fan/hwmon/hwmon0/pwm1
+elif [ -d /sys/devices/platform/pwm_fan ];then
+	FAN_CTRL=/sys/devices/platform/pwm_fan/hwmon/hwmon0/pwm1
+else
+	exit 0
+fi
+
+if [ "$CPU_TEMP" -ge "$CPU_HIGH" -o "$DDR_TEMP" -ge "$DDR_HIGH" -o "$WIFI_TEMP" -ge "$WIFI_HIGH" ];then
+	echo "255" > $FAN_CTRL
+elif [ "$CPU_TEMP" -ge "$CPU_LOW" -o "$DDR_TEMP" -ge "$DDR_LOW" -o "$WIFI_TEMP" -ge "$WIFI_LOW" ];then
+	echo "100" > $FAN_CTRL
+else
+	echo "0" > $FAN_CTRL
+fi

+ 498 - 0
target/linux/mvebu/config-4.14

@@ -0,0 +1,498 @@
+CONFIG_AHCI_MVEBU=y
+CONFIG_ALIGNMENT_TRAP=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_ARCH_HAS_SET_MEMORY=y
+CONFIG_ARCH_HAS_SG_CHAIN=y
+CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y
+CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y
+CONFIG_ARCH_HAS_TICK_BROADCAST=y
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+CONFIG_ARCH_MULTIPLATFORM=y
+# CONFIG_ARCH_MULTI_CPU_AUTO is not set
+CONFIG_ARCH_MULTI_V6_V7=y
+CONFIG_ARCH_MULTI_V7=y
+CONFIG_ARCH_MVEBU=y
+CONFIG_ARCH_NR_GPIO=0
+CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y
+CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_ARM=y
+CONFIG_ARMADA_370_CLK=y
+CONFIG_ARMADA_370_XP_IRQ=y
+CONFIG_ARMADA_370_XP_TIMER=y
+CONFIG_ARMADA_38X_CLK=y
+CONFIG_ARMADA_THERMAL=y
+CONFIG_ARMADA_XP_CLK=y
+CONFIG_ARM_APPENDED_DTB=y
+# CONFIG_ARM_ARMADA_37XX_CPUFREQ is not set
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set
+# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER is not set
+CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE=y
+CONFIG_ARM_CPU_SUSPEND=y
+CONFIG_ARM_CRYPTO=y
+CONFIG_ARM_ERRATA_720789=y
+CONFIG_ARM_ERRATA_764369=y
+CONFIG_ARM_GIC=y
+CONFIG_ARM_GLOBAL_TIMER=y
+CONFIG_ARM_HAS_SG_CHAIN=y
+CONFIG_ARM_HEAVY_MB=y
+CONFIG_ARM_L1_CACHE_SHIFT=6
+CONFIG_ARM_L1_CACHE_SHIFT_6=y
+# CONFIG_ARM_LPAE is not set
+CONFIG_ARM_MVEBU_V7_CPUIDLE=y
+CONFIG_ARM_PATCH_IDIV=y
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+CONFIG_ARM_UNWIND=y
+CONFIG_ARM_VIRT_EXT=y
+CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH=y
+CONFIG_ATA=y
+CONFIG_ATAGS=y
+CONFIG_AUTO_ZRELADDR=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_MQ_PCI=y
+CONFIG_BLK_SCSI_REQUEST=y
+CONFIG_BOUNCE=y
+# CONFIG_CACHE_FEROCEON_L2 is not set
+CONFIG_CACHE_L2X0=y
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK=y
+CONFIG_CLKSRC_MMIO=y
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_COMMON_CLK=y
+CONFIG_CPUFREQ_DT=y
+CONFIG_CPUFREQ_DT_PLATDEV=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_GOV_ATTR_SET=y
+CONFIG_CPU_FREQ_GOV_COMMON=y
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_HAS_ASID=y
+# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_PJ4B=y
+CONFIG_CPU_PM=y
+CONFIG_CPU_RMAP=y
+CONFIG_CPU_SPECTRE=y
+CONFIG_CPU_THERMAL=y
+CONFIG_CPU_THUMB_CAPABLE=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_V7=y
+CONFIG_CRC16=y
+CONFIG_CRYPTO_ACOMP2=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_AES_ARM=y
+CONFIG_CRYPTO_AES_ARM_BS=y
+# CONFIG_CRYPTO_AES_ARM_CE is not set
+# CONFIG_CRYPTO_CHACHA20_NEON is not set
+CONFIG_CRYPTO_CRC32=y
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_CRC32_ARM_CE is not set
+CONFIG_CRYPTO_CRYPTD=y
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_DEV_MARVELL_CESA=y
+# CONFIG_CRYPTO_GHASH_ARM_CE is not set
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_HW=y
+CONFIG_CRYPTO_LZO=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_NULL2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA1_ARM=y
+# CONFIG_CRYPTO_SHA1_ARM_CE is not set
+CONFIG_CRYPTO_SHA1_ARM_NEON=y
+CONFIG_CRYPTO_SHA256_ARM=y
+# CONFIG_CRYPTO_SHA2_ARM_CE is not set
+CONFIG_CRYPTO_SHA512_ARM=y
+CONFIG_CRYPTO_SIMD=y
+CONFIG_CRYPTO_WORKQUEUE=y
+CONFIG_DCACHE_WORD_ACCESS=y
+CONFIG_DEBUG_ALIGN_RODATA=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_LL=y
+CONFIG_DEBUG_LL_INCLUDE="debug/8250.S"
+CONFIG_DEBUG_MVEBU_UART0=y
+# CONFIG_DEBUG_MVEBU_UART0_ALTERNATE is not set
+# CONFIG_DEBUG_MVEBU_UART1_ALTERNATE is not set
+CONFIG_DEBUG_UART_8250=y
+# CONFIG_DEBUG_UART_8250_FLOW_CONTROL is not set
+CONFIG_DEBUG_UART_8250_SHIFT=2
+# CONFIG_DEBUG_UART_8250_WORD is not set
+CONFIG_DEBUG_UART_PHYS=0xd0012000
+CONFIG_DEBUG_UART_VIRT=0xfec12000
+CONFIG_DEBUG_UNCOMPRESS=y
+CONFIG_DEBUG_USER=y
+CONFIG_DMADEVICES=y
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_ENGINE_RAID=y
+CONFIG_DMA_OF=y
+CONFIG_DTC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+CONFIG_EXT4_FS=y
+CONFIG_EXTCON=y
+# CONFIG_F2FS_CHECK_FS is not set
+CONFIG_F2FS_FS=y
+# CONFIG_F2FS_FS_SECURITY is not set
+CONFIG_F2FS_FS_XATTR=y
+CONFIG_F2FS_STAT_FS=y
+CONFIG_FIXED_PHY=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_FS_MBCACHE=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_GENERIC_ARCH_TOPOLOGY=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+CONFIG_GENERIC_CPU_AUTOPROBE=y
+CONFIG_GENERIC_EARLY_IOREMAP=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_GENERIC_IO=y
+CONFIG_GENERIC_IRQ_CHIP=y
+CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_GENERIC_MSI_IRQ=y
+CONFIG_GENERIC_MSI_IRQ_DOMAIN=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_PHY=y
+CONFIG_GENERIC_SCHED_CLOCK=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GLOB=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIOLIB_IRQCHIP=y
+CONFIG_GPIO_GENERIC=y
+CONFIG_GPIO_GENERIC_PLATFORM=y
+CONFIG_GPIO_MVEBU=y
+CONFIG_GPIO_PCA953X=y
+CONFIG_GPIO_PCA953X_IRQ=y
+CONFIG_GPIO_SYSFS=y
+# CONFIG_GRO_CELLS is not set
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_HARDEN_BRANCH_PREDICTOR=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_HAS_DMA=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+CONFIG_HAVE_ARCH_BITREVERSE=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_HAVE_ARCH_PFN_VALID=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_ARM_SCU=y
+CONFIG_HAVE_ARM_SMCCC=y
+CONFIG_HAVE_ARM_TWD=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y
+CONFIG_HAVE_EBPF_JIT=y
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_HAVE_IDE=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_HAVE_NET_DSA=y
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_SMP=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_UID16=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HIGHMEM=y
+# CONFIG_HIGHPTE is not set
+CONFIG_HOTPLUG_CPU=y
+CONFIG_HWBM=y
+CONFIG_HWMON=y
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_OMAP is not set
+CONFIG_HZ_FIXED=0
+CONFIG_HZ_PERIODIC=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MV64XXX=y
+# CONFIG_I2C_PXA is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_IOMMU_HELPER=y
+CONFIG_IRQCHIP=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_IRQ_DOMAIN_HIERARCHY=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_IRQ_WORK=y
+# CONFIG_IWMMXT is not set
+CONFIG_JBD2=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_PCA963X=y
+CONFIG_LEDS_TLC591XX=y
+CONFIG_LEDS_TRIGGER_DISK=y
+CONFIG_LIBFDT=y
+CONFIG_LOCK_SPIN_ON_OWNER=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_MACH_ARMADA_370=y
+# CONFIG_MACH_ARMADA_375 is not set
+CONFIG_MACH_ARMADA_38X=y
+# CONFIG_MACH_ARMADA_39X is not set
+CONFIG_MACH_ARMADA_XP=y
+# CONFIG_MACH_DOVE is not set
+CONFIG_MACH_MVEBU_ANY=y
+CONFIG_MACH_MVEBU_V7=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_MANGLE_BOOTARGS=y
+CONFIG_MARVELL_PHY=y
+CONFIG_MDIO_BUS=y
+CONFIG_MDIO_DEVICE=y
+CONFIG_MDIO_I2C=y
+CONFIG_MEMORY=y
+CONFIG_MIGHT_HAVE_CACHE_L2X0=y
+CONFIG_MIGHT_HAVE_PCI=y
+CONFIG_MIGRATION=y
+CONFIG_MMC=y
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_MVSDIO=y
+CONFIG_MMC_SDHCI=y
+# CONFIG_MMC_SDHCI_PCI is not set
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_PXAV3=y
+# CONFIG_MMC_TIFM_SD is not set
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_M25P80=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ECC=y
+CONFIG_MTD_NAND_PXA3xx=y
+CONFIG_MTD_SPI_NOR=y
+CONFIG_MTD_SPLIT_FIRMWARE=y
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_BEB_LIMIT=20
+CONFIG_MTD_UBI_BLOCK=y
+# CONFIG_MTD_UBI_FASTMAP is not set
+# CONFIG_MTD_UBI_GLUEBI is not set
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MULTI_IRQ_HANDLER=y
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+CONFIG_MVEBU_CLK_COMMON=y
+CONFIG_MVEBU_CLK_COREDIV=y
+CONFIG_MVEBU_CLK_CPU=y
+CONFIG_MVEBU_DEVBUS=y
+CONFIG_MVEBU_MBUS=y
+CONFIG_MVMDIO=y
+CONFIG_MVNETA=y
+CONFIG_MVNETA_BM=y
+CONFIG_MVNETA_BM_ENABLE=y
+CONFIG_MVPP2=y
+CONFIG_MVSW61XX_PHY=y
+CONFIG_MV_XOR=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_NEON=y
+CONFIG_NET_DSA=y
+CONFIG_NET_DSA_MV88E6XXX=y
+CONFIG_NET_DSA_MV88E6XXX_GLOBAL2=y
+CONFIG_NET_DSA_TAG_DSA=y
+CONFIG_NET_DSA_TAG_EDSA=y
+CONFIG_NET_FLOW_LIMIT=y
+CONFIG_NET_SWITCHDEV=y
+CONFIG_NLS=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_NO_BOOTMEM=y
+CONFIG_NR_CPUS=4
+CONFIG_OF=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_ADDRESS_PCI=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_GPIO=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_NET=y
+CONFIG_OF_PCI=y
+CONFIG_OF_PCI_IRQ=y
+CONFIG_OF_RESERVED_MEM=y
+CONFIG_OLD_SIGACTION=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_ORION_WATCHDOG=y
+CONFIG_OUTER_CACHE=y
+CONFIG_OUTER_CACHE_SYNC=y
+CONFIG_PADATA=y
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_DOMAINS_GENERIC=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_MSI_IRQ_DOMAIN=y
+CONFIG_PCI_MVEBU=y
+CONFIG_PERF_USE_VMALLOC=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_PHYLIB=y
+CONFIG_PHYLINK=y
+# CONFIG_PHY_MVEBU_CP110_COMPHY is not set
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_ARMADA_370=y
+CONFIG_PINCTRL_ARMADA_38X=y
+CONFIG_PINCTRL_ARMADA_XP=y
+CONFIG_PINCTRL_MVEBU=y
+# CONFIG_PINCTRL_SINGLE is not set
+CONFIG_PJ4B_ERRATA_4742=y
+# CONFIG_PL310_ERRATA_588369 is not set
+# CONFIG_PL310_ERRATA_727915 is not set
+CONFIG_PL310_ERRATA_753970=y
+# CONFIG_PL310_ERRATA_769419 is not set
+CONFIG_PLAT_ORION=y
+CONFIG_PM_OPP=y
+CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=11
+CONFIG_PWM=y
+CONFIG_PWM_SYSFS=y
+CONFIG_RATIONAL=y
+CONFIG_RCU_NEED_SEGCBLIST=y
+CONFIG_RCU_STALL_COMMON=y
+CONFIG_REGMAP=y
+CONFIG_REGMAP_I2C=y
+CONFIG_REGMAP_MMIO=y
+CONFIG_REGMAP_SPI=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_RFS_ACCEL=y
+CONFIG_RPS=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_ARMADA38X=y
+CONFIG_RTC_DRV_MV=y
+CONFIG_RTC_I2C_AND_SPI=y
+CONFIG_RTC_MC146818_LIB=y
+CONFIG_RWSEM_SPIN_ON_OWNER=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_SATA_AHCI_PLATFORM=y
+CONFIG_SATA_MV=y
+CONFIG_SATA_PMP=y
+# CONFIG_SCHED_INFO is not set
+CONFIG_SCSI=y
+CONFIG_SENSORS_PWM_FAN=y
+CONFIG_SENSORS_TMP421=y
+CONFIG_SERIAL_8250_DW=y
+CONFIG_SERIAL_8250_FSL=y
+CONFIG_SERIAL_MVEBU_CONSOLE=y
+CONFIG_SERIAL_MVEBU_UART=y
+CONFIG_SFP=y
+CONFIG_SG_POOL=y
+CONFIG_SMP=y
+CONFIG_SMP_ON_UP=y
+CONFIG_SOC_BUS=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_SPI=y
+# CONFIG_SPI_ARMADA_3700 is not set
+CONFIG_SPI_MASTER=y
+CONFIG_SPI_ORION=y
+CONFIG_SRAM=y
+CONFIG_SRAM_EXEC=y
+CONFIG_SRCU=y
+CONFIG_SWCONFIG=y
+CONFIG_SWIOTLB=y
+CONFIG_SWPHY=y
+CONFIG_SWP_EMULATE=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_THERMAL=y
+CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
+CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0
+CONFIG_THERMAL_GOV_STEP_WISE=y
+CONFIG_THERMAL_HWMON=y
+CONFIG_THERMAL_OF=y
+# CONFIG_THUMB2_KERNEL is not set
+CONFIG_TICK_CPU_ACCOUNTING=y
+CONFIG_TIMER_OF=y
+CONFIG_TIMER_PROBE=y
+CONFIG_TREE_RCU=y
+CONFIG_TREE_SRCU=y
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
+CONFIG_USB=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_HCD_ORION=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_LEDS_TRIGGER_USBPORT=y
+CONFIG_USB_PHY=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_MVEBU=y
+CONFIG_USB_XHCI_PCI=y
+CONFIG_USB_XHCI_PLATFORM=y
+CONFIG_USE_OF=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_WATCHDOG_CORE=y
+CONFIG_XPS=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_BCJ=y
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_ZLIB_INFLATE=y

+ 14 - 0
target/linux/mvebu/cortexa9/target.mk

@@ -0,0 +1,14 @@
+#
+# Copyright (C) 2017 Hauke Mehrtens
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+ARCH:=arm
+BOARDNAME:=Marvell Armada 37x/38x/XP
+CPU_TYPE:=cortex-a9
+CPU_SUBTYPE:=vfpv3-d16
+KERNELNAME:=zImage dtbs

+ 207 - 0
target/linux/mvebu/files-4.14/arch/arm/boot/dts/armada-385-linksys-venom.dts

@@ -0,0 +1,207 @@
+/*
+ * Device Tree file for the Linksys WRT32X (Venom)
+ *
+ * Copyright (C) 2017 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *
+ * 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 licensed under the terms of the GNU General Public
+ *     License version 2.  This program is licensed "as is" without
+ *     any warranty of any kind, whether express or implied.
+ *
+ * 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 "AS IS", 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.
+ */
+
+/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include "armada-385-linksys.dtsi"
+
+/ {
+	model = "Linksys WRT32X";
+	compatible = "linksys,venom", "linksys,armada385", "marvell,armada385",
+		     "marvell,armada380";
+
+	chosen {
+		bootargs = "console=ttyS0,115200";
+		stdout-path = "serial0:115200n8";
+		append-rootblock = "root=/dev/mtdblock";
+	};
+};
+
+	&expander0 {
+			wan_amber@0 {
+				label = "venom:amber:wan";
+				reg = <0x0>;
+			};
+
+			wan_blue@1 {
+				label = "venom:blue:wan";
+				reg = <0x1>;
+			};
+
+			usb2@5 {
+				label = "venom:blue:usb2";
+				reg = <0x5>;
+			};
+
+			usb3_1@6 {
+				label = "venom:blue:usb3_1";
+				reg = <0x6>;
+			};
+
+			usb3_2@7 {
+				label = "venom:blue:usb3_2";
+				reg = <0x7>;
+			};
+
+			wps_blue@8 {
+				label = "venom:blue:wps";
+				reg = <0x8>;
+			};
+
+			wps_amber@9 {
+				label = "venom:amber:wps";
+				reg = <0x9>;
+			};
+	};
+
+	&gpio_leds {
+			power {
+				gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>;
+				label = "venom:blue:power";
+			};
+
+			sata {
+				gpios = <&gpio1 21 GPIO_ACTIVE_LOW>;
+				label = "venom:blue:sata";
+			};
+
+			wlan_2g {
+				gpios = <&gpio1 13 GPIO_ACTIVE_LOW>;
+				label = "venom:blue:wlan_2g";
+			};
+
+			wlan_5g {
+				gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
+				label = "venom:blue:wlan_5g";
+			};
+	};
+
+	&gpio_leds_pins {
+			marvell,pins = "mpp21", "mpp45", "mpp46", "mpp56";
+	};
+
+	&nand {
+			/* Spansion S34ML02G2 256MiB, OEM Layout */
+			partition@0 {
+				label = "u-boot";
+				reg = <0x0000000 0x200000>;	/* 2MB */
+				read-only;
+			};
+
+			partition@200000 {
+				label = "u_env";
+				reg = <0x200000 0x20000>;	/* 128KB */
+			};
+
+			partition@220000 {
+				label = "s_env";
+				reg = <0x220000 0x40000>;	/* 256KB */
+			};
+
+			partition@180000 {
+				label = "unused_area";
+				reg = <0x260000 0x5c0000>;	/* 5.75MB */
+			};
+
+			partition@7e0000 {
+				label = "devinfo";
+				reg = <0x7e0000 0x40000>;	/* 256KB */
+				read-only;
+			};
+
+			/* kernel1 overlaps with rootfs1 by design */
+			partition@900000 {
+				label = "kernel1";
+				reg = <0x900000 0x7b00000>;	/* 123MB */
+			};
+
+			partition@c00000 {
+				label = "rootfs1";
+				reg = <0xc00000 0x7800000>;	/* 120MB */
+			};
+
+			/* kernel2 overlaps with rootfs2 by design */
+			partition@8400000 {
+				label = "kernel2";
+				reg = <0x8400000 0x7b00000>;	/* 123MB */
+			};
+
+			partition@8700000 {
+				label = "rootfs2";
+				reg = <0x8700000 0x7800000>;	/* 120MB */
+			};
+
+			/* last MB is for the BBT, not writable */
+			partition@ff00000 {
+				label = "BBT";
+				reg = <0xff00000 0x100000>;
+			};
+	};
+
+
+	&pcie1 {
+			mwlwifi {
+				marvell,chainmask = <4 4>;
+			};
+	};
+
+	&pcie2 {
+			mwlwifi {
+				marvell,chainmask = <4 4>;
+			};
+	};
+
+	&sdhci {
+		pinctrl-names = "default";
+		pinctrl-0 = <&sdhci_pins>;
+		no-1-8-v;
+		non-removable;
+		wp-inverted;
+		bus-width = <8>;
+		status = "okay";
+	};
+
+	&usb3_1_vbus {
+		gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>;
+	};
+
+	&usb3_1_vbus_pins {
+		marvell,pins = "mpp44";
+	};

+ 28 - 0
target/linux/mvebu/files-4.14/arch/arm64/boot/dts/marvell/armada-3720-espressobin-emmc.dts

@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Device Tree file for Globalscale Marvell ESPRESSOBin Board with eMMC
+ * Copyright (C) 2018 Marvell
+ *
+ * Romain Perier <romain.perier@free-electrons.com>
+ * Konstantin Porotchkin <kostap@marvell.com>
+ *
+ */
+
+#include "armada-3720-espressobin.dts"
+
+/ {
+	model = "Globalscale Marvell ESPRESSOBin Board (eMMC)";
+	compatible = "globalscale,espressobin-emmc", "globalscale,espressobin",
+		     "marvell,armada3720", "marvell,armada3710";
+};
+
+&sdhci0 {
+	status = "okay";
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+	mmccard: mmccard@0 {
+		compatible = "mmc-card";
+		reg = <0>;
+	};
+};

+ 43 - 0
target/linux/mvebu/files-4.14/arch/arm64/boot/dts/marvell/armada-3720-espressobin-v7-emmc.dts

@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Device Tree file for Globalscale Marvell ESPRESSOBin Board V7 with eMMC
+ * Copyright (C) 2018 Marvell
+ *
+ * Romain Perier <romain.perier@free-electrons.com>
+ * Konstantin Porotchkin <kostap@marvell.com>
+ *
+ */
+
+#include "armada-3720-espressobin.dts"
+
+/ {
+	model = "Globalscale Marvell ESPRESSOBin Board V7 (eMMC)";
+	compatible = "globalscale,espressobin-v7-emmc", "globalscale,espressobin-v7",
+		     "globalscale,espressobin", "marvell,armada3720",
+		     "marvell,armada3710";
+};
+
+&ports {
+	port@1 {
+		reg = <1>;
+		label = "lan1";
+		phy-handle = <&switch0phy0>;
+	};
+
+	port@3 {
+		reg = <3>;
+		label = "wan";
+		phy-handle = <&switch0phy2>;
+	};
+};
+
+&sdhci0 {
+	status = "okay";
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+	mmccard: mmccard@0 {
+		compatible = "mmc-card";
+		reg = <0>;
+	};
+};

+ 31 - 0
target/linux/mvebu/files-4.14/arch/arm64/boot/dts/marvell/armada-3720-espressobin-v7.dts

@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Device Tree file for Globalscale Marvell ESPRESSOBin Board V7
+ * Copyright (C) 2018 Marvell
+ *
+ * Romain Perier <romain.perier@free-electrons.com>
+ * Konstantin Porotchkin <kostap@marvell.com>
+ *
+ */
+
+#include "armada-3720-espressobin.dts"
+
+/ {
+	model = "Globalscale Marvell ESPRESSOBin Board V7";
+	compatible = "globalscale,espressobin-v7", "globalscale,espressobin",
+		     "marvell,armada3720", "marvell,armada3710";
+};
+
+&ports {
+	port@1 {
+		reg = <1>;
+		label = "lan1";
+		phy-handle = <&switch0phy0>;
+	};
+
+	port@3 {
+		reg = <3>;
+		label = "wan";
+		phy-handle = <&switch0phy2>;
+	};
+};

+ 114 - 0
target/linux/mvebu/image/Makefile

@@ -0,0 +1,114 @@
+#
+# Copyright (C) 2012-2016 OpenWrt.org
+# Copyright (C) 2016 LEDE-project.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+JFFS2_BLOCKSIZE = 128k
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/image.mk
+
+KERNEL_LOADADDR := 0x00008000
+
+SIGNATURE:=$(shell printf "%.8s" $(SOURCE_DATE_EPOCH))
+
+define Build/boot-scr
+	rm -f $@-boot.scr
+	sed \
+		-e 's#@ROOT@#$(SIGNATURE)#g' \
+		-e 's#@DTB@#$(firstword $(DEVICE_DTS))#g' \
+		$(BOOT_SCRIPT).bootscript > $@-new.bootscript
+	mkimage -A arm -O linux -T script -C none -a 0 -e 0 -d $@-new.bootscript $@-boot.scr
+endef
+
+define Build/boot-img
+	rm -f $@.boot
+	mkfs.fat -C $@.boot $$(( $(CONFIG_TARGET_KERNEL_PARTSIZE) * 1024 ))
+	$(foreach dts,$(DEVICE_DTS), mcopy -i $@.boot $(KDIR)/image-$(dts).dtb ::$(dts).dtb;)
+	mcopy -i $@.boot $(IMAGE_KERNEL) ::$(KERNEL_NAME)
+	-mcopy -i $@.boot $@-boot.scr ::boot.scr
+endef
+
+define Build/boot-img-ext4
+	rm -fR $@.boot
+	mkdir -p $@.boot
+	$(foreach dts,$(DEVICE_DTS), $(CP) $(KDIR)/image-$(dts).dtb $@.boot/$(dts).dtb;)
+	$(CP) $(IMAGE_KERNEL) $@.boot/$(KERNEL_NAME)
+	-$(CP) $@-boot.scr $@.boot/boot.scr
+	make_ext4fs -J -l $(CONFIG_TARGET_KERNEL_PARTSIZE)M $@.bootimg $@.boot
+endef
+
+define Build/sdcard-img
+	SIGNATURE="$(SIGNATURE)" \
+	./gen_mvebu_sdcard_img.sh $@ \
+		$(if $(UBOOT),$(STAGING_DIR_IMAGE)/$(UBOOT)) \
+		c $(CONFIG_TARGET_KERNEL_PARTSIZE) $@.boot \
+		83 $(CONFIG_TARGET_ROOTFS_PARTSIZE) $(IMAGE_ROOTFS)
+endef
+
+define Build/sdcard-img-ext4
+	SIGNATURE="$(SIGNATURE)" \
+	./gen_mvebu_sdcard_img.sh $@ \
+		$(if $(UBOOT),$(STAGING_DIR_IMAGE)/$(UBOOT)) \
+		83 $(CONFIG_TARGET_KERNEL_PARTSIZE) $@.bootimg \
+		83 $(CONFIG_TARGET_ROOTFS_PARTSIZE) $(IMAGE_ROOTFS)
+endef
+
+define Build/omnia-medkit-initramfs
+	$(TAR) -c -T /dev/null -f $@
+	rm -rf $(dir $(IMAGE_KERNEL))boot
+	mkdir -p $(dir $(IMAGE_KERNEL))boot/boot/
+	cp $(KDIR)/zImage-initramfs $(dir $(IMAGE_KERNEL))boot/boot/zImage
+	cp $(KDIR)/image-$(DEVICE_DTS).dtb $(dir $(IMAGE_KERNEL))boot/boot/dtb
+	$(TAR) -rp --numeric-owner --owner=0 --group=0 --sort=name \
+		$(if $(SOURCE_DATE_EPOCH),--mtime="@$(SOURCE_DATE_EPOCH)") \
+		--file=$@ -C $(dir $(IMAGE_KERNEL))boot/ .
+endef
+
+define Device/Default
+  PROFILES := Default
+  BOARD_NAME = $$(DEVICE_DTS)
+  KERNEL_NAME := zImage
+  KERNEL := kernel-bin | append-dtb | uImage none
+  IMAGES := sysupgrade.bin
+  IMAGE/factory.img := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-ubi | pad-to $$$$(PAGESIZE)
+  IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata
+  SUPPORTED_DEVICES = $(subst _,$(comma),$(1))
+  UBINIZE_OPTS := -E 5
+  UBOOT :=
+  BOOT_SCRIPT :=
+endef
+DEVICE_VARS += BOOT_SCRIPT UBOOT
+
+define Device/Default-arm64
+  BOOT_SCRIPT := generic-arm64
+  DTS_DIR := $(DTS_DIR)/marvell
+  IMAGES := sdcard.img.gz
+  IMAGE/sdcard.img.gz := boot-scr | boot-img-ext4 | sdcard-img-ext4 | gzip | append-metadata
+  KERNEL_NAME := Image
+  KERNEL := kernel-bin
+endef
+
+define Device/NAND-128K
+  BLOCKSIZE := 128k
+  PAGESIZE := 2048
+  SUBPAGESIZE := 512
+  VID_HDR_OFFSET := 2048
+endef
+
+define Device/NAND-256K
+  BLOCKSIZE := 256k
+  PAGESIZE := 4096
+endef
+
+define Device/NAND-512K
+  BLOCKSIZE := 512k
+  PAGESIZE := 4096
+endef
+
+include cortex-a9.mk
+
+$(eval $(call BuildImage))

+ 23 - 0
target/linux/mvebu/image/clearfog.bootscript

@@ -0,0 +1,23 @@
+# Standard Boot-Script
+# use only well-known variable names provided by U-Boot Distro boot
+# This script assumes that there is a boot partition,
+# and that the root partition is always the next one.
+
+# rootfs is always on the next partition
+setexpr openwrt_rootpart ${distro_bootpart} + 1
+
+# figure out partition uuid to pass to the kernel as root=
+part uuid ${devtype} ${devnum}:${openwrt_rootpart} uuid
+
+# generate bootargs (rootfs)
+setenv bootargs ${bootargs} root=PARTUUID=${uuid} rootfstype=auto rootwait
+
+# add console= option to bootargs, if any
+if test -n "${console}"; then
+	setenv bootargs ${bootargs} console=${console}
+fi
+
+echo "Booting Linux with ${bootargs}"
+load ${devtype} ${devnum}:${distro_bootpart} ${fdt_addr_r} @DTB@.dtb
+load ${devtype} ${devnum}:${distro_bootpart} ${kernel_addr_r} zImage
+bootz ${kernel_addr_r} - ${fdt_addr_r}

+ 46 - 0
target/linux/mvebu/image/cortex-a9.mk

@@ -0,0 +1,46 @@
+#
+# Copyright (C) 2012-2016 OpenWrt.org
+# Copyright (C) 2016 LEDE-project.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+ifeq ($(SUBTARGET),cortexa9)
+
+define Device/linksys
+  $(Device/NAND-128K)
+  DEVICE_TITLE := Linksys $(1)
+  DEVICE_PACKAGES := swconfig wpad-basic
+  IMAGES += factory.img
+  KERNEL_SIZE := 6144k
+endef
+
+define Device/linksys_wrt1900ac
+  $(call Device/linksys,WRT1900AC (Mamba))
+  DEVICE_DTS := armada-xp-linksys-mamba
+  DEVICE_PACKAGES := kmod-ath9k
+  KERNEL_SIZE := 3072k
+  SUPPORTED_DEVICES := armada-xp-linksys-mamba linksys,mamba
+endef
+TARGET_DEVICES += linksys_wrt1900ac
+
+define Device/cznic_turris-omnia
+  KERNEL_INSTALL := 1
+  KERNEL := kernel-bin
+  KERNEL_INITRAMFS := kernel-bin
+  DEVICE_TITLE := Turris Omnia
+  DEVICE_PACKAGES :=  \
+    mkf2fs e2fsprogs kmod-fs-vfat kmod-nls-cp437 kmod-nls-iso8859-1 \
+    wpad-basic kmod-ath9k partx-utils kmod-i2c-core kmod-i2c-mux \
+    kmod-i2c-mux-pca954x
+  IMAGES := $$(IMAGE_PREFIX)-sysupgrade.img.gz omnia-medkit-$$(IMAGE_PREFIX)-initramfs.tar.gz
+  IMAGE/$$(IMAGE_PREFIX)-sysupgrade.img.gz := boot-img | sdcard-img | gzip | append-metadata
+  IMAGE/omnia-medkit-$$(IMAGE_PREFIX)-initramfs.tar.gz := omnia-medkit-initramfs | gzip
+  IMAGE_NAME = $$(2)
+  DEVICE_DTS := armada-385-turris-omnia
+  SUPPORTED_DEVICES += armada-385-turris-omnia
+endef
+TARGET_DEVICES += cznic_turris-omnia
+
+endif

+ 84 - 0
target/linux/mvebu/image/gen_mvebu_sdcard_img.sh

@@ -0,0 +1,84 @@
+#!/usr/bin/env bash
+#
+# Copyright (C) 2016 Josua Mayer
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+#
+
+usage() {
+	echo "$0 <outfile> [<bootloader> <type_partitionN> <size_partitionN> <img_partitionN>]?"
+}
+
+# always require first 2 or 3 arguments
+# then in pairs up to 8 more for a total of up to 4 partitions
+if [ $# -lt 1 ] || [ $# -gt 14 ] || [ $((($# - 1) % 3)) -ne 0 ]; then
+	if [ $# -lt 2 ] || [ $# -gt 15 ] || [ $((($# - 2) % 3)) -ne 0 ]; then
+		usage
+		exit 1
+	else
+		BOOTLOADER="$2"
+	fi
+fi
+
+set -e
+
+# parameters
+OUTFILE="$1"; shift
+if [ -n "$BOOTLOADER" ]; then
+	shift
+fi
+
+# generate image file
+printf "Creating $OUTFILE from /dev/zero: "
+dd if=/dev/zero of="$OUTFILE" bs=512 count=1 >/dev/null
+printf "Done\n"
+
+while [ "$#" -ge 3 ]; do
+	ptgen_args="$ptgen_args -t $1 -p $(($2 * 1024 + 256))"
+	parts="$parts$3 "
+	shift; shift; shift
+done
+
+head=16
+sect=63
+
+# create real partition table using fdisk
+printf "Creating partition table: "
+set `ptgen -o "$OUTFILE" -h $head -s $sect -l 1024 -S 0x$SIGNATURE $ptgen_args`
+printf "Done\n"
+
+# install bootloader
+if [ -n "$BOOTLOADER" ]; then
+	printf "Writing bootloader: "
+	dd of="$OUTFILE" if="$BOOTLOADER" bs=512 seek=1 conv=notrunc 2>/dev/null
+	printf "Done\n"
+fi
+
+i=1
+while [ "$#" -ge 2 ]; do
+	img="${parts%% *}"
+	parts="${parts#* }"
+
+	printf "Writing %s to partition %i: " "$img" $i
+	(
+		cat "$img"
+		# add padding to avoid leaving behind old overlay fs data
+		dd if=/dev/zero bs=128k count=1 2>/dev/null
+	) | dd of="$OUTFILE" bs=512 seek=$(($1 / 512)) conv=notrunc 2>/dev/null
+	printf "Done\n"
+
+	let i=i+1
+	shift; shift
+done

+ 16 - 0
target/linux/mvebu/image/generic-arm64.bootscript

@@ -0,0 +1,16 @@
+setenv bootargs "root=PARTUUID=@ROOT@-02 rw rootwait"
+
+if test -n "${console}"; then
+	setenv bootargs "${bootargs} ${console}"
+fi
+
+if mmc dev 0; then
+	setenv mmcdev 0
+elif mmc dev 1; then
+	setenv mmcdev 1
+fi
+
+load mmc ${mmcdev}:1 ${fdt_addr} @DTB@.dtb
+load mmc ${mmcdev}:1 ${kernel_addr} Image
+
+booti ${kernel_addr} - ${fdt_addr}

+ 770 - 0
target/linux/mvebu/patches-4.14/002-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
+@@ -237,11 +237,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
+@@ -169,3 +169,205 @@
+ 		reg = <0x280000 0x680000>;   /* 6.5MiB */
+ 	};
+ };
++
++&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
+@@ -169,3 +169,205 @@
+ 		reg = <0x280000 0x680000>;   /* 6.5MiB */
+ 	};
+ };
++
++&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
+@@ -169,3 +169,205 @@
+ 		reg = <0x280000 0x680000>;   /* 6.5MiB */
+ 	};
+ };
++
++&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
+@@ -184,6 +184,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
+@@ -376,12 +376,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>;
++			};
++		};
+ 	};
+ };
+ 

+ 40 - 0
target/linux/mvebu/patches-4.14/003-add_switch_nodes.patch

@@ -0,0 +1,40 @@
+--- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts
++++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts
+@@ -361,6 +361,16 @@
+ 			};
+ 		};
+ 	};
++
++	mvsw61xx {
++		compatible = "marvell,88e6172";
++		status = "okay";
++		reg = <0x10>;
++
++		mii-bus = <&mdio>;
++		cpu-port-0 = <5>;
++		cpu-port-1 = <6>;
++	};
+ };
+ 
+ &pciec {
+--- a/arch/arm/boot/dts/armada-385-linksys.dtsi
++++ b/arch/arm/boot/dts/armada-385-linksys.dtsi
+@@ -113,6 +113,18 @@
+ 			linux,default-trigger = "disk-activity";
+ 		};
+ 	};
++
++	mvsw61xx {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		compatible = "marvell,88e6176";
++		status = "okay";
++		reg = <0x10>;
++
++		mii-bus = <&mdio>;
++		cpu-port-0 = <5>;
++		cpu-port-1 = <6>;
++	};
+ };
+ 
+ &ahci0 {

+ 39 - 0
target/linux/mvebu/patches-4.14/004-add_sata_disk_activity_trigger.patch

@@ -0,0 +1,39 @@
+From 172230195068703b78ad5733a09492f5d6814c09 Mon Sep 17 00:00:00 2001
+From: Ansuel Smith <ansuelsmth@gmail.com>
+Date: Tue, 28 Feb 2017 14:15:50 +0100
+Subject: [PATCH] ARM: dts: armada: Add default trigger for sata led
+
+In others board we have the sata led set to function
+with the sata led trigger by default.
+This patch makes the same for these board that have sata
+led but get disabled by not associating it to any trigger.
+
+Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
+Acked-by: Jason Cooper <jason@lakedaemon.net>
+Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
+---
+ arch/arm/boot/dts/armada-385-linksys-caiman.dts | 1 +
+ arch/arm/boot/dts/armada-385-linksys-cobra.dts  | 1 +
+ arch/arm/boot/dts/armada-xp-linksys-mamba.dts   | 1 +
+ 3 files changed, 3 insertions(+)
+
+--- a/arch/arm/boot/dts/armada-385-linksys-caiman.dts
++++ b/arch/arm/boot/dts/armada-385-linksys-caiman.dts
+@@ -100,6 +100,7 @@
+ 
+ 	sata {
+ 		label = "caiman:white:sata";
++		linux,default-trigger = "disk-activity";
+ 	};
+ };
+ 
+--- a/arch/arm/boot/dts/armada-385-linksys-cobra.dts
++++ b/arch/arm/boot/dts/armada-385-linksys-cobra.dts
+@@ -100,6 +100,7 @@
+ 
+ 	sata {
+ 		label = "cobra:white:sata";
++		linux,default-trigger = "disk-activity";
+ 	};
+ };
+ 

+ 17 - 0
target/linux/mvebu/patches-4.14/005-linksys_hardcode_nand_ecc_settings.patch

@@ -0,0 +1,17 @@
+Newer Linksys boards might come with a Winbond W29N02GV which can be
+configured in different ways. Make sure we configure it the same way
+as the older chips so everything keeps working.
+
+Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
+
+--- a/arch/arm/boot/dts/armada-385-linksys.dtsi
++++ b/arch/arm/boot/dts/armada-385-linksys.dtsi
+@@ -185,6 +185,8 @@
+ 	/* 128MiB or 256MiB */
+ 	status = "okay";
+ 	num-cs = <1>;
++	nand-ecc-strength = <4>;
++	nand-ecc-step-size = <512>;
+ 	marvell,nand-keep-config;
+ 	marvell,nand-enable-arbiter;
+ 	nand-on-flash-bbt;

+ 201 - 0
target/linux/mvebu/patches-4.14/006-mvebu-Mangle-bootloader-s-kernel-arguments.patch

@@ -0,0 +1,201 @@
+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 | 72 ++++++++++++++++++++++++++++++++-
+ init/main.c                             | 16 ++++++++
+ 3 files changed, 98 insertions(+), 1 deletion(-)
+
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -1934,6 +1934,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
+@@ -4,6 +4,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
+@@ -67,6 +69,65 @@ 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) return dest;
++
++		} 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) {
++		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;
++		}
++	} else {
++		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];
+@@ -86,12 +147,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';
+ 
+@@ -148,7 +218,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)
+@@ -187,6 +259,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
+@@ -95,6 +95,10 @@
+ #include <asm/sections.h>
+ #include <asm/cacheflush.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);
+@@ -573,6 +577,18 @@ asmlinkage __visible void __init start_k
+ 	page_alloc_init();
+ 
+ 	pr_notice("Kernel command line: %s\n", boot_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();

+ 60 - 0
target/linux/mvebu/patches-4.14/100-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/ofpart.c
++++ b/drivers/mtd/ofpart.c
+@@ -25,6 +25,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)
+@@ -33,6 +35,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;
+@@ -110,9 +113,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))
+@@ -219,6 +226,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);

+ 15 - 0
target/linux/mvebu/patches-4.14/102-revert_i2c_delay.patch

@@ -0,0 +1,15 @@
+--- a/arch/arm/boot/dts/armada-xp.dtsi
++++ b/arch/arm/boot/dts/armada-xp.dtsi
+@@ -274,12 +274,10 @@
+ };
+ 
+ &i2c0 {
+-	compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c";
+ 	reg = <0x11000 0x100>;
+ };
+ 
+ &i2c1 {
+-	compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c";
+ 	reg = <0x11100 0x100>;
+ };
+ 

+ 13 - 0
target/linux/mvebu/patches-4.14/103-remove-nand-driver-bug.patch

@@ -0,0 +1,13 @@
+Remove a BUG() call that would crash on a race condition that should
+otherwise be harmless.
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -727,7 +727,6 @@ static void handle_data_pio(struct pxa3x
+ 	default:
+ 		dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__,
+ 				info->state);
+-		BUG();
+ 	}
+ 
+ 	/* Update buffer pointers for multi-page read/write */

+ 10 - 0
target/linux/mvebu/patches-4.14/104-linksys_mamba_disable_keep_config.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
+@@ -200,7 +200,6 @@
+ 			nand@d0000 {
+ 				status = "okay";
+ 				num-cs = <1>;
+-				marvell,nand-keep-config;
+ 				marvell,nand-enable-arbiter;
+ 				nand-on-flash-bbt;
+ 				nand-ecc-strength = <4>;

+ 69 - 0
target/linux/mvebu/patches-4.14/110-pxa3xxx_revert_irq_thread.patch

@@ -0,0 +1,69 @@
+Revert "mtd: pxa3xx-nand: handle PIO in threaded interrupt"
+
+This reverts commit 24542257a3b987025d4b998ec2d15e556c98ad3f
+This upstream change has been causing spurious timeouts on accesses
+to the NAND flash if something else on the system is causing
+significant latency.
+
+Nothing guarantees that the thread will run in time, so the
+usual timeout is unreliable.
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -791,24 +791,11 @@ static void start_data_dma(struct pxa3xx
+ 		__func__, direction, info->dma_cookie, info->sg.length);
+ }
+ 
+-static irqreturn_t pxa3xx_nand_irq_thread(int irq, void *data)
+-{
+-	struct pxa3xx_nand_info *info = data;
+-
+-	handle_data_pio(info);
+-
+-	info->state = STATE_CMD_DONE;
+-	nand_writel(info, NDSR, NDSR_WRDREQ | NDSR_RDDREQ);
+-
+-	return IRQ_HANDLED;
+-}
+-
+ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
+ {
+ 	struct pxa3xx_nand_info *info = devid;
+ 	unsigned int status, is_completed = 0, is_ready = 0;
+ 	unsigned int ready, cmd_done;
+-	irqreturn_t ret = IRQ_HANDLED;
+ 
+ 	if (info->cs == 0) {
+ 		ready           = NDSR_FLASH_RDY;
+@@ -850,8 +837,7 @@ static irqreturn_t pxa3xx_nand_irq(int i
+ 		} else {
+ 			info->state = (status & NDSR_RDDREQ) ?
+ 				      STATE_PIO_READING : STATE_PIO_WRITING;
+-			ret = IRQ_WAKE_THREAD;
+-			goto NORMAL_IRQ_EXIT;
++			handle_data_pio(info);
+ 		}
+ 	}
+ 	if (status & cmd_done) {
+@@ -896,7 +882,7 @@ static irqreturn_t pxa3xx_nand_irq(int i
+ 	if (is_ready)
+ 		complete(&info->dev_ready);
+ NORMAL_IRQ_EXIT:
+-	return ret;
++	return IRQ_HANDLED;
+ }
+ 
+ static inline int is_buf_blank(uint8_t *buf, size_t len)
+@@ -1865,9 +1851,7 @@ static int alloc_nand_resource(struct pl
+ 	/* initialize all interrupts to be disabled */
+ 	disable_int(info, NDSR_MASK);
+ 
+-	ret = request_threaded_irq(irq, pxa3xx_nand_irq,
+-				   pxa3xx_nand_irq_thread, IRQF_ONESHOT,
+-				   pdev->name, info);
++	ret = request_irq(irq, pxa3xx_nand_irq, 0, pdev->name, info);
+ 	if (ret < 0) {
+ 		dev_err(&pdev->dev, "failed to request IRQ: %d\n", ret);
+ 		goto fail_free_buf;

+ 19 - 0
target/linux/mvebu/patches-4.14/205-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
+@@ -140,6 +140,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>;
++		};
+ 	};
+ };
+ 

+ 35 - 0
target/linux/mvebu/patches-4.14/206-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
+@@ -181,19 +181,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>;
+ 					};
+ 				};

+ 21 - 0
target/linux/mvebu/patches-4.14/210-clearfog_switch_node.patch

@@ -0,0 +1,21 @@
+--- a/arch/arm/boot/dts/armada-388-clearfog.dts
++++ b/arch/arm/boot/dts/armada-388-clearfog.dts
+@@ -129,6 +129,18 @@
+ 		};
+ 	};
+ 
++	mvsw61xx {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		compatible = "marvell,88e6176";
++		status = "okay";
++		reg = <0x4>;
++		is-indirect;
++
++		mii-bus = <&mdio>;
++		cpu-port-0 = <5>;
++	};
++
+ 	gpio-keys {
+ 		compatible = "gpio-keys";
+ 		pinctrl-0 = <&rear_button_pins>;

+ 30 - 0
target/linux/mvebu/patches-4.14/220-disable-untested-dsa-boards.patch

@@ -0,0 +1,30 @@
+--- a/arch/arm/boot/dts/armada-385-linksys.dtsi
++++ b/arch/arm/boot/dts/armada-385-linksys.dtsi
+@@ -196,6 +196,7 @@
+ 	status = "okay";
+ 
+ 	switch@0 {
++		status = "disabled";
+ 		compatible = "marvell,mv88e6085";
+ 		#address-cells = <1>;
+ 		#size-cells = <0>;
+--- a/arch/arm/boot/dts/armada-388-clearfog.dts
++++ b/arch/arm/boot/dts/armada-388-clearfog.dts
+@@ -202,6 +202,7 @@
+ 	status = "okay";
+ 
+ 	switch@4 {
++		status = "disabled";
+ 		compatible = "marvell,mv88e6085";
+ 		#address-cells = <1>;
+ 		#size-cells = <0>;
+--- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts
++++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts
+@@ -516,6 +516,7 @@
+ 	status = "okay";
+ 
+ 	switch@0 {
++		status = "disabled";
+ 		compatible = "marvell,mv88e6085";
+ 		#address-cells = <1>;
+ 		#size-cells = <0>;

+ 10 - 0
target/linux/mvebu/patches-4.14/230-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
+@@ -563,3 +563,7 @@
+ 		};
+ 	};
+ };
++
++&coherencyfab {
++	broken-idle;
++};

+ 35 - 0
target/linux/mvebu/patches-4.14/300-mvneta-tx-queue-workaround.patch

@@ -0,0 +1,35 @@
+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
+@@ -3960,6 +3960,15 @@ static int mvneta_ethtool_set_wol(struct
+ 	return ret;
+ }
+ 
++static u16 mvneta_select_queue(struct net_device *dev, struct sk_buff *skb,
++			       void *accel_priv,
++			       select_queue_fallback_t fallback)
++{
++	/* XXX: hardware queue scheduling is broken,
++	 * use only one queue until it is fixed */
++	return 0;
++}
++
+ static const struct net_device_ops mvneta_netdev_ops = {
+ 	.ndo_open            = mvneta_open,
+ 	.ndo_stop            = mvneta_stop,
+@@ -3970,6 +3979,7 @@ static const struct net_device_ops mvnet
+ 	.ndo_fix_features    = mvneta_fix_features,
+ 	.ndo_get_stats64     = mvneta_get_stats64,
+ 	.ndo_do_ioctl        = mvneta_ioctl,
++	.ndo_select_queue    = mvneta_select_queue,
+ };
+ 
+ static const struct ethtool_ops mvneta_eth_tool_ops = {

+ 40 - 0
target/linux/mvebu/patches-4.14/400-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;
+ }

+ 60 - 0
target/linux/mvebu/patches-4.14/401-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/host/pci-mvebu.c | 20 ++++++++++++++------
+ 1 file changed, 14 insertions(+), 6 deletions(-)
+
+--- a/drivers/pci/host/pci-mvebu.c
++++ b/drivers/pci/host/pci-mvebu.c
+@@ -1167,6 +1167,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);
+@@ -1174,7 +1175,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;
+@@ -1261,15 +1268,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;
+ 		}
+ 

+ 290 - 0
target/linux/mvebu/patches-4.14/402-sfp-display-SFP-module-information.patch

@@ -0,0 +1,290 @@
+From e76632d118659347d9261a4470d9f60bfbe0044c Mon Sep 17 00:00:00 2001
+From: Russell King <rmk+kernel@arm.linux.org.uk>
+Date: Sun, 13 Sep 2015 01:06:31 +0100
+Subject: sfp: display SFP module information
+
+Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
+---
+ drivers/net/phy/sfp.c | 254 +++++++++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 253 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/phy/sfp.c
++++ b/drivers/net/phy/sfp.c
+@@ -265,6 +265,184 @@ static unsigned int sfp_check(void *buf,
+ 	return check;
+ }
+ 
++static const char *sfp_link_len(char *buf, size_t size, unsigned int length,
++	unsigned int multiplier)
++{
++	if (length == 0)
++		return "unsupported/unspecified";
++
++	if (length == 255) {
++		*buf++ = '>';
++		size -= 1;
++		length -= 1;
++	}
++
++	length *= multiplier;
++
++	if (length >= 1000)
++		snprintf(buf, size, "%u.%0*ukm",
++			length / 1000,
++			multiplier > 100 ? 1 :
++			multiplier > 10 ? 2 : 3,
++			length % 1000);
++	else
++		snprintf(buf, size, "%um", length);
++
++	return buf;
++}
++
++struct bitfield {
++	unsigned int mask;
++	unsigned int val;
++	const char *str;
++};
++
++static const struct bitfield sfp_options[] = {
++	{
++		.mask = SFP_OPTIONS_HIGH_POWER_LEVEL,
++		.val = SFP_OPTIONS_HIGH_POWER_LEVEL,
++		.str = "hpl",
++	}, {
++		.mask = SFP_OPTIONS_PAGING_A2,
++		.val = SFP_OPTIONS_PAGING_A2,
++		.str = "paginga2",
++	}, {
++		.mask = SFP_OPTIONS_RETIMER,
++		.val = SFP_OPTIONS_RETIMER,
++		.str = "retimer",
++	}, {
++		.mask = SFP_OPTIONS_COOLED_XCVR,
++		.val = SFP_OPTIONS_COOLED_XCVR,
++		.str = "cooled",
++	}, {
++		.mask = SFP_OPTIONS_POWER_DECL,
++		.val = SFP_OPTIONS_POWER_DECL,
++		.str = "powerdecl",
++	}, {
++		.mask = SFP_OPTIONS_RX_LINEAR_OUT,
++		.val = SFP_OPTIONS_RX_LINEAR_OUT,
++		.str = "rxlinear",
++	}, {
++		.mask = SFP_OPTIONS_RX_DECISION_THRESH,
++		.val = SFP_OPTIONS_RX_DECISION_THRESH,
++		.str = "rxthresh",
++	}, {
++		.mask = SFP_OPTIONS_TUNABLE_TX,
++		.val = SFP_OPTIONS_TUNABLE_TX,
++		.str = "tunabletx",
++	}, {
++		.mask = SFP_OPTIONS_RATE_SELECT,
++		.val = SFP_OPTIONS_RATE_SELECT,
++		.str = "ratesel",
++	}, {
++		.mask = SFP_OPTIONS_TX_DISABLE,
++		.val = SFP_OPTIONS_TX_DISABLE,
++		.str = "txdisable",
++	}, {
++		.mask = SFP_OPTIONS_TX_FAULT,
++		.val = SFP_OPTIONS_TX_FAULT,
++		.str = "txfault",
++	}, {
++		.mask = SFP_OPTIONS_LOS_INVERTED,
++		.val = SFP_OPTIONS_LOS_INVERTED,
++		.str = "los-",
++	}, {
++		.mask = SFP_OPTIONS_LOS_NORMAL,
++		.val = SFP_OPTIONS_LOS_NORMAL,
++		.str = "los+",
++	}, { }
++};
++
++static const struct bitfield diagmon[] = {
++	{
++		.mask = SFP_DIAGMON_DDM,
++		.val = SFP_DIAGMON_DDM,
++		.str = "ddm",
++	}, {
++		.mask = SFP_DIAGMON_INT_CAL,
++		.val = SFP_DIAGMON_INT_CAL,
++		.str = "intcal",
++	}, {
++		.mask = SFP_DIAGMON_EXT_CAL,
++		.val = SFP_DIAGMON_EXT_CAL,
++		.str = "extcal",
++	}, {
++		.mask = SFP_DIAGMON_RXPWR_AVG,
++		.val = SFP_DIAGMON_RXPWR_AVG,
++		.str = "rxpwravg",
++	}, { }
++};
++
++static const char *sfp_bitfield(char *out, size_t outsz, const struct bitfield *bits, unsigned int val)
++{
++	char *p = out;
++	int n;
++
++	*p = '\0';
++	while (bits->mask) {
++		if ((val & bits->mask) == bits->val) {
++			n = snprintf(p, outsz, "%s%s",
++				     out != p ? ", " : "",
++				     bits->str);
++			if (n == outsz)
++				break;
++			p += n;
++			outsz -= n;
++		}
++		bits++;
++	}
++
++	return out;
++}
++
++static const char *sfp_connector(unsigned int connector)
++{
++	switch (connector) {
++	case SFP_CONNECTOR_UNSPEC:
++		return "unknown/unspecified";
++	case SFP_CONNECTOR_SC:
++		return "SC";
++	case SFP_CONNECTOR_FIBERJACK:
++		return "Fiberjack";
++	case SFP_CONNECTOR_LC:
++		return "LC";
++	case SFP_CONNECTOR_MT_RJ:
++		return "MT-RJ";
++	case SFP_CONNECTOR_MU:
++		return "MU";
++	case SFP_CONNECTOR_SG:
++		return "SG";
++	case SFP_CONNECTOR_OPTICAL_PIGTAIL:
++		return "Optical pigtail";
++	case SFP_CONNECTOR_HSSDC_II:
++		return "HSSDC II";
++	case SFP_CONNECTOR_COPPER_PIGTAIL:
++		return "Copper pigtail";
++	default:
++		return "unknown";
++	}
++}
++
++static const char *sfp_encoding(unsigned int encoding)
++{
++	switch (encoding) {
++	case SFP_ENCODING_UNSPEC:
++		return "unspecified";
++	case SFP_ENCODING_8472_64B66B:
++		return "64b66b";
++	case SFP_ENCODING_8B10B:
++		return "8b10b";
++	case SFP_ENCODING_4B5B:
++		return "4b5b";
++	case SFP_ENCODING_NRZ:
++		return "NRZ";
++	case SFP_ENCODING_8472_MANCHESTER:
++		return "MANCHESTER";
++	default:
++		return "unknown";
++	}
++}
++
+ /* Helpers */
+ static void sfp_module_tx_disable(struct sfp *sfp)
+ {
+@@ -433,6 +611,7 @@ static int sfp_sm_mod_probe(struct sfp *
+ 	char sn[17];
+ 	char date[9];
+ 	char rev[5];
++	char options[80];
+ 	u8 check;
+ 	int err;
+ 
+@@ -476,10 +655,83 @@ static int sfp_sm_mod_probe(struct sfp *
+ 	rev[4] = '\0';
+ 	memcpy(sn, sfp->id.ext.vendor_sn, 16);
+ 	sn[16] = '\0';
+-	memcpy(date, sfp->id.ext.datecode, 8);
++	date[0] = sfp->id.ext.datecode[4];
++	date[1] = sfp->id.ext.datecode[5];
++	date[2] = '-';
++	date[3] = sfp->id.ext.datecode[2];
++	date[4] = sfp->id.ext.datecode[3];
++	date[5] = '-';
++	date[6] = sfp->id.ext.datecode[0];
++	date[7] = sfp->id.ext.datecode[1];
+ 	date[8] = '\0';
+ 
+ 	dev_info(sfp->dev, "module %s %s rev %s sn %s dc %s\n", vendor, part, rev, sn, date);
++	dev_info(sfp->dev, "  %s connector, encoding %s, nominal bitrate %u.%uGbps +%u%% -%u%%\n",
++		 sfp_connector(sfp->id.base.connector),
++		 sfp_encoding(sfp->id.base.encoding),
++		 sfp->id.base.br_nominal / 10,
++		 sfp->id.base.br_nominal % 10,
++		 sfp->id.ext.br_max, sfp->id.ext.br_min);
++	dev_info(sfp->dev, "  1000BaseSX%c 1000BaseLX%c 1000BaseCX%c 1000BaseT%c 100BaseTLX%c 1000BaseFX%c BaseBX10%c BasePX%c\n",
++		 sfp->id.base.e1000_base_sx ? '+' : '-',
++		 sfp->id.base.e1000_base_lx ? '+' : '-',
++		 sfp->id.base.e1000_base_cx ? '+' : '-',
++		 sfp->id.base.e1000_base_t ? '+' : '-',
++		 sfp->id.base.e100_base_lx ? '+' : '-',
++		 sfp->id.base.e100_base_fx ? '+' : '-',
++		 sfp->id.base.e_base_bx10 ? '+' : '-',
++		 sfp->id.base.e_base_px ? '+' : '-');
++	dev_info(sfp->dev, "  10GBaseSR%c 10GBaseLR%c 10GBaseLRM%c 10GBaseER%c\n",
++		 sfp->id.base.e10g_base_sr ? '+' : '-',
++		 sfp->id.base.e10g_base_lr ? '+' : '-',
++		 sfp->id.base.e10g_base_lrm ? '+' : '-',
++		 sfp->id.base.e10g_base_er ? '+' : '-');
++
++	if (!sfp->id.base.sfp_ct_passive && !sfp->id.base.sfp_ct_active &&
++	    !sfp->id.base.e1000_base_t) {
++		char len_9um[16], len_om[16];
++
++		dev_info(sfp->dev, "  Wavelength %unm, fiber lengths:\n",
++			 be16_to_cpup(&sfp->id.base.optical_wavelength));
++
++		if (sfp->id.base.link_len[0] == 255)
++			strcpy(len_9um, ">254km");
++		else if (sfp->id.base.link_len[1] && sfp->id.base.link_len[1] != 255)
++			sprintf(len_9um, "%um",
++				sfp->id.base.link_len[1] * 100);
++		else if (sfp->id.base.link_len[0])
++			sprintf(len_9um, "%ukm", sfp->id.base.link_len[0]);
++		else if (sfp->id.base.link_len[1] == 255)
++			strcpy(len_9um, ">25.4km");
++		else
++			strcpy(len_9um, "unsupported");
++
++		dev_info(sfp->dev, "    9µm SM    : %s\n", len_9um);
++		dev_info(sfp->dev, " 62.5µm MM OM1: %s\n",
++			 sfp_link_len(len_om, sizeof(len_om),
++				      sfp->id.base.link_len[3], 10));
++		dev_info(sfp->dev, "   50µm MM OM2: %s\n",
++			 sfp_link_len(len_om, sizeof(len_om),
++				      sfp->id.base.link_len[2], 10));
++		dev_info(sfp->dev, "   50µm MM OM3: %s\n",
++			 sfp_link_len(len_om, sizeof(len_om),
++				      sfp->id.base.link_len[5], 10));
++		dev_info(sfp->dev, "   50µm MM OM4: %s\n",
++			 sfp_link_len(len_om, sizeof(len_om),
++				      sfp->id.base.link_len[4], 10));
++	} else {
++		char len[16];
++		dev_info(sfp->dev, "  Copper length: %s\n",
++			 sfp_link_len(len, sizeof(len),
++				      sfp->id.base.link_len[4], 1));
++	}
++
++	dev_info(sfp->dev, "  Options: %s\n",
++		 sfp_bitfield(options, sizeof(options), sfp_options,
++			      be16_to_cpu(sfp->id.ext.options)));
++	dev_info(sfp->dev, "  Diagnostics: %s\n",
++		 sfp_bitfield(options, sizeof(options), diagmon,
++			      sfp->id.ext.diagmon));
+ 
+ 	/* We only support SFP modules, not the legacy GBIC modules. */
+ 	if (sfp->id.base.phys_id != SFP_PHYS_ID_SFP ||

+ 979 - 0
target/linux/mvebu/patches-4.14/403-net-mvneta-convert-to-phylink.patch

@@ -0,0 +1,979 @@
+From 36f29e6cf8071fed3854d9825217ed2a3c83b990 Mon Sep 17 00:00:00 2001
+From: Russell King <rmk+kernel@arm.linux.org.uk>
+Date: Wed, 16 Sep 2015 21:27:10 +0100
+Subject: net: mvneta: convert to phylink
+
+Convert mvneta to use phylink, which models the MAC to PHY link in
+a generic, reusable form.
+
+Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
+
+- remove unused sync status
+---
+ drivers/net/ethernet/marvell/Kconfig  |   2 +-
+ drivers/net/ethernet/marvell/mvneta.c | 594 ++++++++++++++++++++--------------
+ 2 files changed, 349 insertions(+), 247 deletions(-)
+
+--- a/drivers/net/ethernet/marvell/Kconfig
++++ b/drivers/net/ethernet/marvell/Kconfig
+@@ -60,7 +60,7 @@ config MVNETA
+ 	depends on ARCH_MVEBU || COMPILE_TEST
+ 	depends on HAS_DMA
+ 	select MVMDIO
+-	select FIXED_PHY
++	select PHYLINK
+ 	---help---
+ 	  This driver supports the network interface units in the
+ 	  Marvell ARMADA XP, ARMADA 370, ARMADA 38x and
+--- a/drivers/net/ethernet/marvell/mvneta.c
++++ b/drivers/net/ethernet/marvell/mvneta.c
+@@ -28,7 +28,7 @@
+ #include <linux/of_mdio.h>
+ #include <linux/of_net.h>
+ #include <linux/phy.h>
+-#include <linux/phy_fixed.h>
++#include <linux/phylink.h>
+ #include <linux/platform_device.h>
+ #include <linux/skbuff.h>
+ #include <net/hwbm.h>
+@@ -189,6 +189,7 @@
+ #define MVNETA_GMAC_CTRL_0                       0x2c00
+ #define      MVNETA_GMAC_MAX_RX_SIZE_SHIFT       2
+ #define      MVNETA_GMAC_MAX_RX_SIZE_MASK        0x7ffc
++#define      MVNETA_GMAC0_PORT_1000BASE_X        BIT(1)
+ #define      MVNETA_GMAC0_PORT_ENABLE            BIT(0)
+ #define MVNETA_GMAC_CTRL_2                       0x2c08
+ #define      MVNETA_GMAC2_INBAND_AN_ENABLE       BIT(0)
+@@ -204,13 +205,19 @@
+ #define      MVNETA_GMAC_TX_FLOW_CTRL_ENABLE     BIT(5)
+ #define      MVNETA_GMAC_RX_FLOW_CTRL_ACTIVE     BIT(6)
+ #define      MVNETA_GMAC_TX_FLOW_CTRL_ACTIVE     BIT(7)
++#define      MVNETA_GMAC_AN_COMPLETE             BIT(11)
++#define      MVNETA_GMAC_SYNC_OK                 BIT(14)
+ #define MVNETA_GMAC_AUTONEG_CONFIG               0x2c0c
+ #define      MVNETA_GMAC_FORCE_LINK_DOWN         BIT(0)
+ #define      MVNETA_GMAC_FORCE_LINK_PASS         BIT(1)
+ #define      MVNETA_GMAC_INBAND_AN_ENABLE        BIT(2)
++#define      MVNETA_GMAC_AN_BYPASS_ENABLE        BIT(3)
++#define      MVNETA_GMAC_INBAND_RESTART_AN       BIT(4)
+ #define      MVNETA_GMAC_CONFIG_MII_SPEED        BIT(5)
+ #define      MVNETA_GMAC_CONFIG_GMII_SPEED       BIT(6)
+ #define      MVNETA_GMAC_AN_SPEED_EN             BIT(7)
++#define      MVNETA_GMAC_CONFIG_FLOW_CTRL        BIT(8)
++#define      MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL    BIT(9)
+ #define      MVNETA_GMAC_AN_FLOW_CTRL_EN         BIT(11)
+ #define      MVNETA_GMAC_CONFIG_FULL_DUPLEX      BIT(12)
+ #define      MVNETA_GMAC_AN_DUPLEX_EN            BIT(13)
+@@ -237,6 +244,12 @@
+ #define MVNETA_TXQ_TOKEN_SIZE_REG(q)             (0x3e40 + ((q) << 2))
+ #define      MVNETA_TXQ_TOKEN_SIZE_MAX           0x7fffffff
+ 
++#define MVNETA_LPI_CTRL_0                        0x2cc0
++#define MVNETA_LPI_CTRL_1                        0x2cc4
++#define      MVNETA_LPI_REQUEST_ENABLE           BIT(0)
++#define MVNETA_LPI_CTRL_2                        0x2cc8
++#define MVNETA_LPI_STATUS                        0x2ccc
++
+ #define MVNETA_CAUSE_TXQ_SENT_DESC_ALL_MASK	 0xff
+ 
+ /* Descriptor ring Macros */
+@@ -313,6 +326,11 @@
+ #define MVNETA_RX_GET_BM_POOL_ID(rxd) \
+ 	(((rxd)->status & MVNETA_RXD_BM_POOL_MASK) >> MVNETA_RXD_BM_POOL_SHIFT)
+ 
++enum {
++	ETHTOOL_STAT_EEE_WAKEUP,
++	ETHTOOL_MAX_STATS,
++};
++
+ struct mvneta_statistic {
+ 	unsigned short offset;
+ 	unsigned short type;
+@@ -321,6 +339,7 @@ struct mvneta_statistic {
+ 
+ #define T_REG_32	32
+ #define T_REG_64	64
++#define T_SW		1
+ 
+ static const struct mvneta_statistic mvneta_statistics[] = {
+ 	{ 0x3000, T_REG_64, "good_octets_received", },
+@@ -355,6 +374,7 @@ static const struct mvneta_statistic mvn
+ 	{ 0x304c, T_REG_32, "broadcast_frames_sent", },
+ 	{ 0x3054, T_REG_32, "fc_sent", },
+ 	{ 0x300c, T_REG_32, "internal_mac_transmit_err", },
++	{ ETHTOOL_STAT_EEE_WAKEUP, T_SW, "eee_wakeup_errors", },
+ };
+ 
+ struct mvneta_pcpu_stats {
+@@ -407,20 +427,19 @@ struct mvneta_port {
+ 	u16 tx_ring_size;
+ 	u16 rx_ring_size;
+ 
+-	struct mii_bus *mii_bus;
+-	phy_interface_t phy_interface;
+-	struct device_node *phy_node;
+-	unsigned int link;
+-	unsigned int duplex;
+-	unsigned int speed;
++	struct device_node *dn;
+ 	unsigned int tx_csum_limit;
+-	unsigned int use_inband_status:1;
++	struct phylink *phylink;
+ 
+ 	struct mvneta_bm *bm_priv;
+ 	struct mvneta_bm_pool *pool_long;
+ 	struct mvneta_bm_pool *pool_short;
+ 	int bm_win_id;
+ 
++	bool eee_enabled;
++	bool eee_active;
++	bool tx_lpi_enabled;
++
+ 	u64 ethtool_stats[ARRAY_SIZE(mvneta_statistics)];
+ 
+ 	u32 indir[MVNETA_RSS_LU_TABLE_SIZE];
+@@ -1215,10 +1234,6 @@ static void mvneta_port_disable(struct m
+ 	val &= ~MVNETA_GMAC0_PORT_ENABLE;
+ 	mvreg_write(pp, MVNETA_GMAC_CTRL_0, val);
+ 
+-	pp->link = 0;
+-	pp->duplex = -1;
+-	pp->speed = 0;
+-
+ 	udelay(200);
+ }
+ 
+@@ -1278,44 +1293,6 @@ static void mvneta_set_other_mcast_table
+ 		mvreg_write(pp, MVNETA_DA_FILT_OTH_MCAST + offset, val);
+ }
+ 
+-static void mvneta_set_autoneg(struct mvneta_port *pp, int enable)
+-{
+-	u32 val;
+-
+-	if (enable) {
+-		val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
+-		val &= ~(MVNETA_GMAC_FORCE_LINK_PASS |
+-			 MVNETA_GMAC_FORCE_LINK_DOWN |
+-			 MVNETA_GMAC_AN_FLOW_CTRL_EN);
+-		val |= MVNETA_GMAC_INBAND_AN_ENABLE |
+-		       MVNETA_GMAC_AN_SPEED_EN |
+-		       MVNETA_GMAC_AN_DUPLEX_EN;
+-		mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
+-
+-		val = mvreg_read(pp, MVNETA_GMAC_CLOCK_DIVIDER);
+-		val |= MVNETA_GMAC_1MS_CLOCK_ENABLE;
+-		mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, val);
+-
+-		val = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
+-		val |= MVNETA_GMAC2_INBAND_AN_ENABLE;
+-		mvreg_write(pp, MVNETA_GMAC_CTRL_2, val);
+-	} else {
+-		val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
+-		val &= ~(MVNETA_GMAC_INBAND_AN_ENABLE |
+-		       MVNETA_GMAC_AN_SPEED_EN |
+-		       MVNETA_GMAC_AN_DUPLEX_EN);
+-		mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
+-
+-		val = mvreg_read(pp, MVNETA_GMAC_CLOCK_DIVIDER);
+-		val &= ~MVNETA_GMAC_1MS_CLOCK_ENABLE;
+-		mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, val);
+-
+-		val = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
+-		val &= ~MVNETA_GMAC2_INBAND_AN_ENABLE;
+-		mvreg_write(pp, MVNETA_GMAC_CTRL_2, val);
+-	}
+-}
+-
+ static void mvneta_percpu_unmask_interrupt(void *arg)
+ {
+ 	struct mvneta_port *pp = arg;
+@@ -1468,7 +1445,6 @@ static void mvneta_defaults_set(struct m
+ 	val &= ~MVNETA_PHY_POLLING_ENABLE;
+ 	mvreg_write(pp, MVNETA_UNIT_CONTROL, val);
+ 
+-	mvneta_set_autoneg(pp, pp->use_inband_status);
+ 	mvneta_set_ucast_table(pp, -1);
+ 	mvneta_set_special_mcast_table(pp, -1);
+ 	mvneta_set_other_mcast_table(pp, -1);
+@@ -2693,26 +2669,11 @@ static irqreturn_t mvneta_percpu_isr(int
+ 	return IRQ_HANDLED;
+ }
+ 
+-static int mvneta_fixed_link_update(struct mvneta_port *pp,
+-				    struct phy_device *phy)
++static void mvneta_link_change(struct mvneta_port *pp)
+ {
+-	struct fixed_phy_status status;
+-	struct fixed_phy_status changed = {};
+ 	u32 gmac_stat = mvreg_read(pp, MVNETA_GMAC_STATUS);
+ 
+-	status.link = !!(gmac_stat & MVNETA_GMAC_LINK_UP);
+-	if (gmac_stat & MVNETA_GMAC_SPEED_1000)
+-		status.speed = SPEED_1000;
+-	else if (gmac_stat & MVNETA_GMAC_SPEED_100)
+-		status.speed = SPEED_100;
+-	else
+-		status.speed = SPEED_10;
+-	status.duplex = !!(gmac_stat & MVNETA_GMAC_FULL_DUPLEX);
+-	changed.link = 1;
+-	changed.speed = 1;
+-	changed.duplex = 1;
+-	fixed_phy_update_state(phy, &status, &changed);
+-	return 0;
++	phylink_mac_change(pp->phylink, !!(gmac_stat & MVNETA_GMAC_LINK_UP));
+ }
+ 
+ /* NAPI handler
+@@ -2728,7 +2689,6 @@ static int mvneta_poll(struct napi_struc
+ 	u32 cause_rx_tx;
+ 	int rx_queue;
+ 	struct mvneta_port *pp = netdev_priv(napi->dev);
+-	struct net_device *ndev = pp->dev;
+ 	struct mvneta_pcpu_port *port = this_cpu_ptr(pp->ports);
+ 
+ 	if (!netif_running(pp->dev)) {
+@@ -2742,12 +2702,11 @@ static int mvneta_poll(struct napi_struc
+ 		u32 cause_misc = mvreg_read(pp, MVNETA_INTR_MISC_CAUSE);
+ 
+ 		mvreg_write(pp, MVNETA_INTR_MISC_CAUSE, 0);
+-		if (pp->use_inband_status && (cause_misc &
+-				(MVNETA_CAUSE_PHY_STATUS_CHANGE |
+-				 MVNETA_CAUSE_LINK_CHANGE |
+-				 MVNETA_CAUSE_PSC_SYNC_CHANGE))) {
+-			mvneta_fixed_link_update(pp, ndev->phydev);
+-		}
++
++		if (cause_misc & (MVNETA_CAUSE_PHY_STATUS_CHANGE |
++				  MVNETA_CAUSE_LINK_CHANGE |
++				  MVNETA_CAUSE_PSC_SYNC_CHANGE))
++			mvneta_link_change(pp);
+ 	}
+ 
+ 	/* Release Tx descriptors */
+@@ -3060,7 +3019,6 @@ static int mvneta_setup_txqs(struct mvne
+ static void mvneta_start_dev(struct mvneta_port *pp)
+ {
+ 	int cpu;
+-	struct net_device *ndev = pp->dev;
+ 
+ 	mvneta_max_rx_size_set(pp, pp->pkt_size);
+ 	mvneta_txq_max_tx_size_set(pp, pp->pkt_size);
+@@ -3088,16 +3046,15 @@ static void mvneta_start_dev(struct mvne
+ 		    MVNETA_CAUSE_LINK_CHANGE |
+ 		    MVNETA_CAUSE_PSC_SYNC_CHANGE);
+ 
+-	phy_start(ndev->phydev);
++	phylink_start(pp->phylink);
+ 	netif_tx_start_all_queues(pp->dev);
+ }
+ 
+ static void mvneta_stop_dev(struct mvneta_port *pp)
+ {
+ 	unsigned int cpu;
+-	struct net_device *ndev = pp->dev;
+ 
+-	phy_stop(ndev->phydev);
++	phylink_stop(pp->phylink);
+ 
+ 	if (!pp->neta_armada3700) {
+ 		for_each_online_cpu(cpu) {
+@@ -3250,103 +3207,232 @@ static int mvneta_set_mac_addr(struct ne
+ 	return 0;
+ }
+ 
+-static void mvneta_adjust_link(struct net_device *ndev)
++static void mvneta_validate(struct net_device *ndev, unsigned long *supported,
++			    struct phylink_link_state *state)
++{
++	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
++
++	/* Allow all the expected bits */
++	phylink_set(mask, Autoneg);
++	phylink_set_port_modes(mask);
++
++	/* Asymmetric pause is unsupported */
++	phylink_set(mask, Pause);
++	/* Half-duplex at speeds higher than 100Mbit is unsupported */
++	phylink_set(mask, 1000baseT_Full);
++	phylink_set(mask, 1000baseX_Full);
++
++	if (state->interface != PHY_INTERFACE_MODE_1000BASEX) {
++		/* 10M and 100M are only supported in non-802.3z mode */
++		phylink_set(mask, 10baseT_Half);
++		phylink_set(mask, 10baseT_Full);
++		phylink_set(mask, 100baseT_Half);
++		phylink_set(mask, 100baseT_Full);
++	}
++
++	bitmap_and(supported, supported, mask,
++		   __ETHTOOL_LINK_MODE_MASK_NBITS);
++	bitmap_and(state->advertising, state->advertising, mask,
++		   __ETHTOOL_LINK_MODE_MASK_NBITS);
++}
++
++static int mvneta_mac_link_state(struct net_device *ndev,
++				 struct phylink_link_state *state)
+ {
+ 	struct mvneta_port *pp = netdev_priv(ndev);
+-	struct phy_device *phydev = ndev->phydev;
+-	int status_change = 0;
++	u32 gmac_stat;
+ 
+-	if (phydev->link) {
+-		if ((pp->speed != phydev->speed) ||
+-		    (pp->duplex != phydev->duplex)) {
+-			u32 val;
+-
+-			val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
+-			val &= ~(MVNETA_GMAC_CONFIG_MII_SPEED |
+-				 MVNETA_GMAC_CONFIG_GMII_SPEED |
+-				 MVNETA_GMAC_CONFIG_FULL_DUPLEX);
+-
+-			if (phydev->duplex)
+-				val |= MVNETA_GMAC_CONFIG_FULL_DUPLEX;
+-
+-			if (phydev->speed == SPEED_1000)
+-				val |= MVNETA_GMAC_CONFIG_GMII_SPEED;
+-			else if (phydev->speed == SPEED_100)
+-				val |= MVNETA_GMAC_CONFIG_MII_SPEED;
++	gmac_stat = mvreg_read(pp, MVNETA_GMAC_STATUS);
+ 
+-			mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
++	if (gmac_stat & MVNETA_GMAC_SPEED_1000)
++		state->speed = SPEED_1000;
++	else if (gmac_stat & MVNETA_GMAC_SPEED_100)
++		state->speed = SPEED_100;
++	else
++		state->speed = SPEED_10;
+ 
+-			pp->duplex = phydev->duplex;
+-			pp->speed  = phydev->speed;
+-		}
++	state->an_complete = !!(gmac_stat & MVNETA_GMAC_AN_COMPLETE);
++	state->link = !!(gmac_stat & MVNETA_GMAC_LINK_UP);
++	state->duplex = !!(gmac_stat & MVNETA_GMAC_FULL_DUPLEX);
++
++	state->pause = 0;
++	if (gmac_stat & MVNETA_GMAC_RX_FLOW_CTRL_ENABLE)
++		state->pause |= MLO_PAUSE_RX;
++	if (gmac_stat & MVNETA_GMAC_TX_FLOW_CTRL_ENABLE)
++		state->pause |= MLO_PAUSE_TX;
++
++	return 1;
++}
++
++static void mvneta_mac_an_restart(struct net_device *ndev)
++{
++	struct mvneta_port *pp = netdev_priv(ndev);
++	u32 gmac_an = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
++
++	mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG,
++		    gmac_an | MVNETA_GMAC_INBAND_RESTART_AN);
++	mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG,
++		    gmac_an & ~MVNETA_GMAC_INBAND_RESTART_AN);
++}
++
++static void mvneta_mac_config(struct net_device *ndev, unsigned int mode,
++	const struct phylink_link_state *state)
++{
++	struct mvneta_port *pp = netdev_priv(ndev);
++	u32 new_ctrl0, gmac_ctrl0 = mvreg_read(pp, MVNETA_GMAC_CTRL_0);
++	u32 new_ctrl2, gmac_ctrl2 = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
++	u32 new_clk, gmac_clk = mvreg_read(pp, MVNETA_GMAC_CLOCK_DIVIDER);
++	u32 new_an, gmac_an = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
++
++	new_ctrl0 = gmac_ctrl0 & ~MVNETA_GMAC0_PORT_1000BASE_X;
++	new_ctrl2 = gmac_ctrl2 & ~MVNETA_GMAC2_INBAND_AN_ENABLE;
++	new_clk = gmac_clk & ~MVNETA_GMAC_1MS_CLOCK_ENABLE;
++	new_an = gmac_an & ~(MVNETA_GMAC_INBAND_AN_ENABLE |
++			     MVNETA_GMAC_INBAND_RESTART_AN |
++			     MVNETA_GMAC_CONFIG_MII_SPEED |
++			     MVNETA_GMAC_CONFIG_GMII_SPEED |
++			     MVNETA_GMAC_AN_SPEED_EN |
++			     MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL |
++			     MVNETA_GMAC_CONFIG_FLOW_CTRL |
++			     MVNETA_GMAC_AN_FLOW_CTRL_EN |
++			     MVNETA_GMAC_CONFIG_FULL_DUPLEX |
++			     MVNETA_GMAC_AN_DUPLEX_EN);
++
++	if (phylink_test(state->advertising, Pause))
++		new_an |= MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL;
++	if (state->pause & MLO_PAUSE_TXRX_MASK)
++		new_an |= MVNETA_GMAC_CONFIG_FLOW_CTRL;
++
++	if (!phylink_autoneg_inband(mode)) {
++		/* Phy or fixed speed */
++		if (state->duplex)
++			new_an |= MVNETA_GMAC_CONFIG_FULL_DUPLEX;
++
++		if (state->speed == SPEED_1000)
++			new_an |= MVNETA_GMAC_CONFIG_GMII_SPEED;
++		else if (state->speed == SPEED_100)
++			new_an |= MVNETA_GMAC_CONFIG_MII_SPEED;
++	} else if (state->interface == PHY_INTERFACE_MODE_SGMII) {
++		/* SGMII mode receives the state from the PHY */
++		new_ctrl2 |= MVNETA_GMAC2_INBAND_AN_ENABLE;
++		new_clk |= MVNETA_GMAC_1MS_CLOCK_ENABLE;
++		new_an = (new_an & ~(MVNETA_GMAC_FORCE_LINK_DOWN |
++				     MVNETA_GMAC_FORCE_LINK_PASS)) |
++			 MVNETA_GMAC_INBAND_AN_ENABLE |
++			 MVNETA_GMAC_AN_SPEED_EN |
++			 MVNETA_GMAC_AN_DUPLEX_EN;
++	} else {
++		/* 802.3z negotiation - only 1000base-X */
++		new_ctrl0 |= MVNETA_GMAC0_PORT_1000BASE_X;
++		new_clk |= MVNETA_GMAC_1MS_CLOCK_ENABLE;
++		new_an = (new_an & ~(MVNETA_GMAC_FORCE_LINK_DOWN |
++				     MVNETA_GMAC_FORCE_LINK_PASS)) |
++			 MVNETA_GMAC_INBAND_AN_ENABLE |
++			 MVNETA_GMAC_CONFIG_GMII_SPEED |
++			 /* The MAC only supports FD mode */
++			 MVNETA_GMAC_CONFIG_FULL_DUPLEX;
++
++		if (state->pause & MLO_PAUSE_AN && state->an_enabled)
++			new_an |= MVNETA_GMAC_AN_FLOW_CTRL_EN;
++	}
++
++	/* Armada 370 documentation says we can only change the port mode
++	 * and in-band enable when the link is down, so force it down
++	 * while making these changes. We also do this for GMAC_CTRL2 */
++	if ((new_ctrl0 ^ gmac_ctrl0) & MVNETA_GMAC0_PORT_1000BASE_X ||
++	    (new_ctrl2 ^ gmac_ctrl2) & MVNETA_GMAC2_INBAND_AN_ENABLE ||
++	    (new_an  ^ gmac_an) & MVNETA_GMAC_INBAND_AN_ENABLE) {
++		mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG,
++			    (gmac_an & ~MVNETA_GMAC_FORCE_LINK_PASS) |
++			    MVNETA_GMAC_FORCE_LINK_DOWN);
++	}
++
++	if (new_ctrl0 != gmac_ctrl0)
++		mvreg_write(pp, MVNETA_GMAC_CTRL_0, new_ctrl0);
++	if (new_ctrl2 != gmac_ctrl2)
++		mvreg_write(pp, MVNETA_GMAC_CTRL_2, new_ctrl2);
++	if (new_clk != gmac_clk)
++		mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, new_clk);
++	if (new_an != gmac_an)
++		mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, new_an);
++}
++
++static void mvneta_set_eee(struct mvneta_port *pp, bool enable)
++{
++	u32 lpi_ctl1;
++
++	lpi_ctl1 = mvreg_read(pp, MVNETA_LPI_CTRL_1);
++	if (enable)
++		lpi_ctl1 |= MVNETA_LPI_REQUEST_ENABLE;
++	else
++		lpi_ctl1 &= ~MVNETA_LPI_REQUEST_ENABLE;
++	mvreg_write(pp, MVNETA_LPI_CTRL_1, lpi_ctl1);
++}
++
++static void mvneta_mac_link_down(struct net_device *ndev, unsigned int mode)
++{
++	struct mvneta_port *pp = netdev_priv(ndev);
++	u32 val;
++
++	mvneta_port_down(pp);
++
++	if (!phylink_autoneg_inband(mode)) {
++		val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
++		val &= ~MVNETA_GMAC_FORCE_LINK_PASS;
++		val |= MVNETA_GMAC_FORCE_LINK_DOWN;
++		mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
+ 	}
+ 
+-	if (phydev->link != pp->link) {
+-		if (!phydev->link) {
+-			pp->duplex = -1;
+-			pp->speed = 0;
+-		}
++	pp->eee_active = false;
++	mvneta_set_eee(pp, false);
++}
++
++static void mvneta_mac_link_up(struct net_device *ndev, unsigned int mode,
++			       struct phy_device *phy)
++{
++	struct mvneta_port *pp = netdev_priv(ndev);
++	u32 val;
+ 
+-		pp->link = phydev->link;
+-		status_change = 1;
++	if (!phylink_autoneg_inband(mode)) {
++		val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
++		val &= ~MVNETA_GMAC_FORCE_LINK_DOWN;
++		val |= MVNETA_GMAC_FORCE_LINK_PASS;
++		mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
+ 	}
+ 
+-	if (status_change) {
+-		if (phydev->link) {
+-			if (!pp->use_inband_status) {
+-				u32 val = mvreg_read(pp,
+-						  MVNETA_GMAC_AUTONEG_CONFIG);
+-				val &= ~MVNETA_GMAC_FORCE_LINK_DOWN;
+-				val |= MVNETA_GMAC_FORCE_LINK_PASS;
+-				mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG,
+-					    val);
+-			}
+-			mvneta_port_up(pp);
+-		} else {
+-			if (!pp->use_inband_status) {
+-				u32 val = mvreg_read(pp,
+-						  MVNETA_GMAC_AUTONEG_CONFIG);
+-				val &= ~MVNETA_GMAC_FORCE_LINK_PASS;
+-				val |= MVNETA_GMAC_FORCE_LINK_DOWN;
+-				mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG,
+-					    val);
+-			}
+-			mvneta_port_down(pp);
+-		}
+-		phy_print_status(phydev);
++	mvneta_port_up(pp);
++
++	if (phy && pp->eee_enabled) {
++		pp->eee_active = phy_init_eee(phy, 0) >= 0;
++		mvneta_set_eee(pp, pp->eee_active && pp->tx_lpi_enabled);
+ 	}
+ }
+ 
++static const struct phylink_mac_ops mvneta_phylink_ops = {
++	.validate = mvneta_validate,
++	.mac_link_state = mvneta_mac_link_state,
++	.mac_an_restart = mvneta_mac_an_restart,
++	.mac_config = mvneta_mac_config,
++	.mac_link_down = mvneta_mac_link_down,
++	.mac_link_up = mvneta_mac_link_up,
++};
++
+ static int mvneta_mdio_probe(struct mvneta_port *pp)
+ {
+-	struct phy_device *phy_dev;
+ 	struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
++	int err = phylink_of_phy_connect(pp->phylink, pp->dn);
++	if (err)
++		netdev_err(pp->dev, "could not attach PHY\n");
+ 
+-	phy_dev = of_phy_connect(pp->dev, pp->phy_node, mvneta_adjust_link, 0,
+-				 pp->phy_interface);
+-	if (!phy_dev) {
+-		netdev_err(pp->dev, "could not find the PHY\n");
+-		return -ENODEV;
+-	}
+-
+-	phy_ethtool_get_wol(phy_dev, &wol);
++	phylink_ethtool_get_wol(pp->phylink, &wol);
+ 	device_set_wakeup_capable(&pp->dev->dev, !!wol.supported);
+ 
+-	phy_dev->supported &= PHY_GBIT_FEATURES;
+-	phy_dev->advertising = phy_dev->supported;
+-
+-	pp->link    = 0;
+-	pp->duplex  = 0;
+-	pp->speed   = 0;
+-
+-	return 0;
++	return err;
+ }
+ 
+ static void mvneta_mdio_remove(struct mvneta_port *pp)
+ {
+-	struct net_device *ndev = pp->dev;
+-
+-	phy_disconnect(ndev->phydev);
++	phylink_disconnect_phy(pp->phylink);
+ }
+ 
+ /* Electing a CPU must be done in an atomic way: it should be done
+@@ -3625,10 +3711,9 @@ static int mvneta_stop(struct net_device
+ 
+ static int mvneta_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+ {
+-	if (!dev->phydev)
+-		return -ENOTSUPP;
++	struct mvneta_port *pp = netdev_priv(dev);
+ 
+-	return phy_mii_ioctl(dev->phydev, ifr, cmd);
++	return phylink_mii_ioctl(pp->phylink, ifr, cmd);
+ }
+ 
+ /* Ethtool methods */
+@@ -3639,44 +3724,25 @@ mvneta_ethtool_set_link_ksettings(struct
+ 				  const struct ethtool_link_ksettings *cmd)
+ {
+ 	struct mvneta_port *pp = netdev_priv(ndev);
+-	struct phy_device *phydev = ndev->phydev;
+ 
+-	if (!phydev)
+-		return -ENODEV;
+-
+-	if ((cmd->base.autoneg == AUTONEG_ENABLE) != pp->use_inband_status) {
+-		u32 val;
+-
+-		mvneta_set_autoneg(pp, cmd->base.autoneg == AUTONEG_ENABLE);
+-
+-		if (cmd->base.autoneg == AUTONEG_DISABLE) {
+-			val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
+-			val &= ~(MVNETA_GMAC_CONFIG_MII_SPEED |
+-				 MVNETA_GMAC_CONFIG_GMII_SPEED |
+-				 MVNETA_GMAC_CONFIG_FULL_DUPLEX);
+-
+-			if (phydev->duplex)
+-				val |= MVNETA_GMAC_CONFIG_FULL_DUPLEX;
++	return phylink_ethtool_ksettings_set(pp->phylink, cmd);
++}
+ 
+-			if (phydev->speed == SPEED_1000)
+-				val |= MVNETA_GMAC_CONFIG_GMII_SPEED;
+-			else if (phydev->speed == SPEED_100)
+-				val |= MVNETA_GMAC_CONFIG_MII_SPEED;
++/* Get link ksettings for ethtools */
++static int
++mvneta_ethtool_get_link_ksettings(struct net_device *ndev,
++				  struct ethtool_link_ksettings *cmd)
++{
++	struct mvneta_port *pp = netdev_priv(ndev);
+ 
+-			mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
+-		}
++	return phylink_ethtool_ksettings_get(pp->phylink, cmd);
++}
+ 
+-		pp->use_inband_status = (cmd->base.autoneg == AUTONEG_ENABLE);
+-		netdev_info(pp->dev, "autoneg status set to %i\n",
+-			    pp->use_inband_status);
+-
+-		if (netif_running(ndev)) {
+-			mvneta_port_down(pp);
+-			mvneta_port_up(pp);
+-		}
+-	}
++static int mvneta_ethtool_nway_reset(struct net_device *dev)
++{
++	struct mvneta_port *pp = netdev_priv(dev);
+ 
+-	return phy_ethtool_ksettings_set(ndev->phydev, cmd);
++	return phylink_ethtool_nway_reset(pp->phylink);
+ }
+ 
+ /* Set interrupt coalescing for ethtools */
+@@ -3768,6 +3834,22 @@ static int mvneta_ethtool_set_ringparam(
+ 	return 0;
+ }
+ 
++static void mvneta_ethtool_get_pauseparam(struct net_device *dev,
++					  struct ethtool_pauseparam *pause)
++{
++	struct mvneta_port *pp = netdev_priv(dev);
++
++	phylink_ethtool_get_pauseparam(pp->phylink, pause);
++}
++
++static int mvneta_ethtool_set_pauseparam(struct net_device *dev,
++					 struct ethtool_pauseparam *pause)
++{
++	struct mvneta_port *pp = netdev_priv(dev);
++
++	return phylink_ethtool_set_pauseparam(pp->phylink, pause);
++}
++
+ static void mvneta_ethtool_get_strings(struct net_device *netdev, u32 sset,
+ 				       u8 *data)
+ {
+@@ -3784,26 +3866,35 @@ static void mvneta_ethtool_update_stats(
+ {
+ 	const struct mvneta_statistic *s;
+ 	void __iomem *base = pp->base;
+-	u32 high, low, val;
+-	u64 val64;
++	u32 high, low;
++	u64 val;
+ 	int i;
+ 
+ 	for (i = 0, s = mvneta_statistics;
+ 	     s < mvneta_statistics + ARRAY_SIZE(mvneta_statistics);
+ 	     s++, i++) {
++		val = 0;
++
+ 		switch (s->type) {
+ 		case T_REG_32:
+ 			val = readl_relaxed(base + s->offset);
+-			pp->ethtool_stats[i] += val;
+ 			break;
+ 		case T_REG_64:
+ 			/* Docs say to read low 32-bit then high */
+ 			low = readl_relaxed(base + s->offset);
+ 			high = readl_relaxed(base + s->offset + 4);
+-			val64 = (u64)high << 32 | low;
+-			pp->ethtool_stats[i] += val64;
++			val = (u64)high << 32 | low;
++			break;
++		case T_SW:
++			switch (s->offset) {
++			case ETHTOOL_STAT_EEE_WAKEUP:
++				val = phylink_get_eee_err(pp->phylink);
++				break;
++			}
+ 			break;
+ 		}
++
++		pp->ethtool_stats[i] += val;
+ 	}
+ }
+ 
+@@ -3938,28 +4029,65 @@ static int mvneta_ethtool_get_rxfh(struc
+ static void mvneta_ethtool_get_wol(struct net_device *dev,
+ 				   struct ethtool_wolinfo *wol)
+ {
+-	wol->supported = 0;
+-	wol->wolopts = 0;
++	struct mvneta_port *pp = netdev_priv(dev);
+ 
+-	if (dev->phydev)
+-		phy_ethtool_get_wol(dev->phydev, wol);
++	phylink_ethtool_get_wol(pp->phylink, wol);
+ }
+ 
+ static int mvneta_ethtool_set_wol(struct net_device *dev,
+ 				  struct ethtool_wolinfo *wol)
+ {
++	struct mvneta_port *pp = netdev_priv(dev);
+ 	int ret;
+ 
+-	if (!dev->phydev)
+-		return -EOPNOTSUPP;
+-
+-	ret = phy_ethtool_set_wol(dev->phydev, wol);
++	ret = phylink_ethtool_set_wol(pp->phylink, wol);
+ 	if (!ret)
+ 		device_set_wakeup_enable(&dev->dev, !!wol->wolopts);
+ 
+ 	return ret;
+ }
+ 
++static int mvneta_ethtool_get_eee(struct net_device *dev,
++				  struct ethtool_eee *eee)
++{
++	struct mvneta_port *pp = netdev_priv(dev);
++	u32 lpi_ctl0;
++
++	lpi_ctl0 = mvreg_read(pp, MVNETA_LPI_CTRL_0);
++
++	eee->eee_enabled = pp->eee_enabled;
++	eee->eee_active = pp->eee_active;
++	eee->tx_lpi_enabled = pp->tx_lpi_enabled;
++	eee->tx_lpi_timer = (lpi_ctl0) >> 8; // * scale;
++
++	return phylink_ethtool_get_eee(pp->phylink, eee);
++}
++
++static int mvneta_ethtool_set_eee(struct net_device *dev,
++				  struct ethtool_eee *eee)
++{
++	struct mvneta_port *pp = netdev_priv(dev);
++	u32 lpi_ctl0;
++
++	/* The Armada 37x documents do not give limits for this other than
++	 * it being an 8-bit register. */
++	if (eee->tx_lpi_enabled &&
++	    (eee->tx_lpi_timer < 0 || eee->tx_lpi_timer > 255))
++		return -EINVAL;
++
++	lpi_ctl0 = mvreg_read(pp, MVNETA_LPI_CTRL_0);
++	lpi_ctl0 &= ~(0xff << 8);
++	lpi_ctl0 |= eee->tx_lpi_timer << 8;
++	mvreg_write(pp, MVNETA_LPI_CTRL_0, lpi_ctl0);
++
++	pp->eee_enabled = eee->eee_enabled;
++	pp->tx_lpi_enabled = eee->tx_lpi_enabled;
++
++	mvneta_set_eee(pp, eee->tx_lpi_enabled && eee->eee_enabled);
++
++	return phylink_ethtool_set_eee(pp->phylink, eee);
++}
++
+ static u16 mvneta_select_queue(struct net_device *dev, struct sk_buff *skb,
+ 			       void *accel_priv,
+ 			       select_queue_fallback_t fallback)
+@@ -3983,13 +4111,15 @@ static const struct net_device_ops mvnet
+ };
+ 
+ static const struct ethtool_ops mvneta_eth_tool_ops = {
+-	.nway_reset	= phy_ethtool_nway_reset,
++	.nway_reset	= mvneta_ethtool_nway_reset,
+ 	.get_link       = ethtool_op_get_link,
+ 	.set_coalesce   = mvneta_ethtool_set_coalesce,
+ 	.get_coalesce   = mvneta_ethtool_get_coalesce,
+ 	.get_drvinfo    = mvneta_ethtool_get_drvinfo,
+ 	.get_ringparam  = mvneta_ethtool_get_ringparam,
+ 	.set_ringparam	= mvneta_ethtool_set_ringparam,
++	.get_pauseparam	= mvneta_ethtool_get_pauseparam,
++	.set_pauseparam	= mvneta_ethtool_set_pauseparam,
+ 	.get_strings	= mvneta_ethtool_get_strings,
+ 	.get_ethtool_stats = mvneta_ethtool_get_stats,
+ 	.get_sset_count	= mvneta_ethtool_get_sset_count,
+@@ -3997,10 +4127,12 @@ static const struct ethtool_ops mvneta_e
+ 	.get_rxnfc	= mvneta_ethtool_get_rxnfc,
+ 	.get_rxfh	= mvneta_ethtool_get_rxfh,
+ 	.set_rxfh	= mvneta_ethtool_set_rxfh,
+-	.get_link_ksettings = phy_ethtool_get_link_ksettings,
++	.get_link_ksettings = mvneta_ethtool_get_link_ksettings,
+ 	.set_link_ksettings = mvneta_ethtool_set_link_ksettings,
+ 	.get_wol        = mvneta_ethtool_get_wol,
+ 	.set_wol        = mvneta_ethtool_set_wol,
++	.get_eee	= mvneta_ethtool_get_eee,
++	.set_eee	= mvneta_ethtool_set_eee,
+ };
+ 
+ /* Initialize hw */
+@@ -4145,14 +4277,13 @@ static int mvneta_probe(struct platform_
+ {
+ 	struct resource *res;
+ 	struct device_node *dn = pdev->dev.of_node;
+-	struct device_node *phy_node;
+ 	struct device_node *bm_node;
+ 	struct mvneta_port *pp;
+ 	struct net_device *dev;
++	struct phylink *phylink;
+ 	const char *dt_mac_addr;
+ 	char hw_mac_addr[ETH_ALEN];
+ 	const char *mac_from;
+-	const char *managed;
+ 	int tx_csum_limit;
+ 	int phy_mode;
+ 	int err;
+@@ -4168,31 +4299,11 @@ static int mvneta_probe(struct platform_
+ 		goto err_free_netdev;
+ 	}
+ 
+-	phy_node = of_parse_phandle(dn, "phy", 0);
+-	if (!phy_node) {
+-		if (!of_phy_is_fixed_link(dn)) {
+-			dev_err(&pdev->dev, "no PHY specified\n");
+-			err = -ENODEV;
+-			goto err_free_irq;
+-		}
+-
+-		err = of_phy_register_fixed_link(dn);
+-		if (err < 0) {
+-			dev_err(&pdev->dev, "cannot register fixed PHY\n");
+-			goto err_free_irq;
+-		}
+-
+-		/* In the case of a fixed PHY, the DT node associated
+-		 * to the PHY is the Ethernet MAC DT node.
+-		 */
+-		phy_node = of_node_get(dn);
+-	}
+-
+ 	phy_mode = of_get_phy_mode(dn);
+ 	if (phy_mode < 0) {
+ 		dev_err(&pdev->dev, "incorrect phy-mode\n");
+ 		err = -EINVAL;
+-		goto err_put_phy_node;
++		goto err_free_irq;
+ 	}
+ 
+ 	dev->tx_queue_len = MVNETA_MAX_TXD;
+@@ -4203,12 +4314,7 @@ static int mvneta_probe(struct platform_
+ 
+ 	pp = netdev_priv(dev);
+ 	spin_lock_init(&pp->lock);
+-	pp->phy_node = phy_node;
+-	pp->phy_interface = phy_mode;
+-
+-	err = of_property_read_string(dn, "managed", &managed);
+-	pp->use_inband_status = (err == 0 &&
+-				 strcmp(managed, "in-band-status") == 0);
++	pp->dn = dn;
+ 
+ 	pp->rxq_def = rxq_def;
+ 
+@@ -4230,7 +4336,7 @@ static int mvneta_probe(struct platform_
+ 		pp->clk = devm_clk_get(&pdev->dev, NULL);
+ 	if (IS_ERR(pp->clk)) {
+ 		err = PTR_ERR(pp->clk);
+-		goto err_put_phy_node;
++		goto err_free_irq;
+ 	}
+ 
+ 	clk_prepare_enable(pp->clk);
+@@ -4356,6 +4462,14 @@ static int mvneta_probe(struct platform_
+ 	/* 9676 == 9700 - 20 and rounding to 8 */
+ 	dev->max_mtu = 9676;
+ 
++	phylink = phylink_create(dev, dn, phy_mode, &mvneta_phylink_ops);
++	if (IS_ERR(phylink)) {
++		err = PTR_ERR(phylink);
++		goto err_netdev;
++	}
++
++	pp->phylink = phylink;
++
+ 	err = register_netdev(dev);
+ 	if (err < 0) {
+ 		dev_err(&pdev->dev, "failed to register\n");
+@@ -4367,14 +4481,6 @@ static int mvneta_probe(struct platform_
+ 
+ 	platform_set_drvdata(pdev, pp->dev);
+ 
+-	if (pp->use_inband_status) {
+-		struct phy_device *phy = of_phy_find_device(dn);
+-
+-		mvneta_fixed_link_update(pp, phy);
+-
+-		put_device(&phy->mdio.dev);
+-	}
+-
+ 	return 0;
+ 
+ err_netdev:
+@@ -4383,16 +4489,14 @@ err_netdev:
+ 		mvneta_bm_pool_destroy(pp->bm_priv, pp->pool_short,
+ 				       1 << pp->id);
+ 	}
++	if (pp->phylink)
++		phylink_destroy(pp->phylink);
+ 	free_percpu(pp->stats);
+ err_free_ports:
+ 	free_percpu(pp->ports);
+ err_clk:
+ 	clk_disable_unprepare(pp->clk_bus);
+ 	clk_disable_unprepare(pp->clk);
+-err_put_phy_node:
+-	of_node_put(phy_node);
+-	if (of_phy_is_fixed_link(dn))
+-		of_phy_deregister_fixed_link(dn);
+ err_free_irq:
+ 	irq_dispose_mapping(dev->irq);
+ err_free_netdev:
+@@ -4404,7 +4508,6 @@ err_free_netdev:
+ static int mvneta_remove(struct platform_device *pdev)
+ {
+ 	struct net_device  *dev = platform_get_drvdata(pdev);
+-	struct device_node *dn = pdev->dev.of_node;
+ 	struct mvneta_port *pp = netdev_priv(dev);
+ 
+ 	unregister_netdev(dev);
+@@ -4412,10 +4515,8 @@ static int mvneta_remove(struct platform
+ 	clk_disable_unprepare(pp->clk);
+ 	free_percpu(pp->ports);
+ 	free_percpu(pp->stats);
+-	if (of_phy_is_fixed_link(dn))
+-		of_phy_deregister_fixed_link(dn);
+ 	irq_dispose_mapping(dev->irq);
+-	of_node_put(pp->phy_node);
++	phylink_destroy(pp->phylink);
+ 	free_netdev(dev);
+ 
+ 	if (pp->bm_priv) {
+@@ -4467,9 +4568,6 @@ static int mvneta_resume(struct device *
+ 		return err;
+ 	}
+ 
+-	if (pp->use_inband_status)
+-		mvneta_fixed_link_update(pp, dev->phydev);
+-
+ 	netif_device_attach(dev);
+ 	if (netif_running(dev)) {
+ 		mvneta_open(dev);

+ 28 - 0
target/linux/mvebu/patches-4.14/404-net-mvneta-hack-fix-phy_interface.patch

@@ -0,0 +1,28 @@
+From acdfcc7ef78c46baca1439a1cac5b73008abc672 Mon Sep 17 00:00:00 2001
+From: Russell King <rmk+kernel@armlinux.org.uk>
+Date: Tue, 16 May 2017 11:55:58 +0100
+Subject: net: mvneta: hack fix phy_interface
+
+Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
+---
+ drivers/net/ethernet/marvell/mvneta.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/net/ethernet/marvell/mvneta.c
++++ b/drivers/net/ethernet/marvell/mvneta.c
+@@ -427,6 +427,7 @@ struct mvneta_port {
+ 	u16 tx_ring_size;
+ 	u16 rx_ring_size;
+ 
++	phy_interface_t phy_interface;
+ 	struct device_node *dn;
+ 	unsigned int tx_csum_limit;
+ 	struct phylink *phylink;
+@@ -4314,6 +4315,7 @@ static int mvneta_probe(struct platform_
+ 
+ 	pp = netdev_priv(dev);
+ 	spin_lock_init(&pp->lock);
++	pp->phy_interface = phy_mode;
+ 	pp->dn = dn;
+ 
+ 	pp->rxq_def = rxq_def;

+ 56 - 0
target/linux/mvebu/patches-4.14/405-net-mvneta-disable-MVNETA_CAUSE_PSC_SYNC_CHANGE-inte.patch

@@ -0,0 +1,56 @@
+From fde9e742a47606110232b7464608b6f9c0510938 Mon Sep 17 00:00:00 2001
+From: Russell King <rmk+kernel@armlinux.org.uk>
+Date: Sat, 24 Dec 2016 10:27:08 +0000
+Subject: net: mvneta: disable MVNETA_CAUSE_PSC_SYNC_CHANGE interrupt
+
+The PSC sync change interrupt can fire multiple times while the link is
+down.  As this isn't information we make use of, it's pointless having
+the interrupt enabled, so let's disable this interrupt.
+
+Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
+---
+ drivers/net/ethernet/marvell/mvneta.c | 12 ++++--------
+ 1 file changed, 4 insertions(+), 8 deletions(-)
+
+--- a/drivers/net/ethernet/marvell/mvneta.c
++++ b/drivers/net/ethernet/marvell/mvneta.c
+@@ -2705,8 +2705,7 @@ static int mvneta_poll(struct napi_struc
+ 		mvreg_write(pp, MVNETA_INTR_MISC_CAUSE, 0);
+ 
+ 		if (cause_misc & (MVNETA_CAUSE_PHY_STATUS_CHANGE |
+-				  MVNETA_CAUSE_LINK_CHANGE |
+-				  MVNETA_CAUSE_PSC_SYNC_CHANGE))
++				  MVNETA_CAUSE_LINK_CHANGE))
+ 			mvneta_link_change(pp);
+ 	}
+ 
+@@ -3044,8 +3043,7 @@ static void mvneta_start_dev(struct mvne
+ 
+ 	mvreg_write(pp, MVNETA_INTR_MISC_MASK,
+ 		    MVNETA_CAUSE_PHY_STATUS_CHANGE |
+-		    MVNETA_CAUSE_LINK_CHANGE |
+-		    MVNETA_CAUSE_PSC_SYNC_CHANGE);
++		    MVNETA_CAUSE_LINK_CHANGE);
+ 
+ 	phylink_start(pp->phylink);
+ 	netif_tx_start_all_queues(pp->dev);
+@@ -3541,8 +3539,7 @@ static int mvneta_cpu_online(unsigned in
+ 	on_each_cpu(mvneta_percpu_unmask_interrupt, pp, true);
+ 	mvreg_write(pp, MVNETA_INTR_MISC_MASK,
+ 		    MVNETA_CAUSE_PHY_STATUS_CHANGE |
+-		    MVNETA_CAUSE_LINK_CHANGE |
+-		    MVNETA_CAUSE_PSC_SYNC_CHANGE);
++		    MVNETA_CAUSE_LINK_CHANGE);
+ 	netif_tx_start_all_queues(pp->dev);
+ 	spin_unlock(&pp->lock);
+ 	return 0;
+@@ -3583,8 +3580,7 @@ static int mvneta_cpu_dead(unsigned int
+ 	on_each_cpu(mvneta_percpu_unmask_interrupt, pp, true);
+ 	mvreg_write(pp, MVNETA_INTR_MISC_MASK,
+ 		    MVNETA_CAUSE_PHY_STATUS_CHANGE |
+-		    MVNETA_CAUSE_LINK_CHANGE |
+-		    MVNETA_CAUSE_PSC_SYNC_CHANGE);
++		    MVNETA_CAUSE_LINK_CHANGE);
+ 	netif_tx_start_all_queues(pp->dev);
+ 	return 0;
+ }

+ 44 - 0
target/linux/mvebu/patches-4.14/406-net-mvneta-add-module-EEPROM-reading-support.patch

@@ -0,0 +1,44 @@
+From 2ff039aa4462c2104c210b7cf39691c612de8214 Mon Sep 17 00:00:00 2001
+From: Russell King <rmk+kernel@arm.linux.org.uk>
+Date: Thu, 1 Oct 2015 23:32:39 +0100
+Subject: net: mvneta: add module EEPROM reading support
+
+Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
+---
+ drivers/net/ethernet/marvell/mvneta.c | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+--- a/drivers/net/ethernet/marvell/mvneta.c
++++ b/drivers/net/ethernet/marvell/mvneta.c
+@@ -4044,6 +4044,22 @@ static int mvneta_ethtool_set_wol(struct
+ 	return ret;
+ }
+ 
++static int mvneta_ethtool_get_module_info(struct net_device *dev,
++					  struct ethtool_modinfo *modinfo)
++{
++	struct mvneta_port *pp = netdev_priv(dev);
++
++	return phylink_ethtool_get_module_info(pp->phylink, modinfo);
++}
++
++static int mvneta_ethtool_get_module_eeprom(struct net_device *dev,
++					    struct ethtool_eeprom *ee, u8 *buf)
++{
++	struct mvneta_port *pp = netdev_priv(dev);
++
++	return phylink_ethtool_get_module_eeprom(pp->phylink, ee, buf);
++}
++
+ static int mvneta_ethtool_get_eee(struct net_device *dev,
+ 				  struct ethtool_eee *eee)
+ {
+@@ -4128,6 +4144,8 @@ static const struct ethtool_ops mvneta_e
+ 	.set_link_ksettings = mvneta_ethtool_set_link_ksettings,
+ 	.get_wol        = mvneta_ethtool_get_wol,
+ 	.set_wol        = mvneta_ethtool_set_wol,
++	.get_module_info = mvneta_ethtool_get_module_info,
++	.get_module_eeprom = mvneta_ethtool_get_module_eeprom,
+ 	.get_eee	= mvneta_ethtool_get_eee,
+ 	.set_eee	= mvneta_ethtool_set_eee,
+ };

+ 80 - 0
target/linux/mvebu/patches-4.14/407-phy-fixed-phy-remove-fixed_phy_update_state.patch

@@ -0,0 +1,80 @@
+From 774ce2eda0a929f79ee398ba6d2d13fd406f31c4 Mon Sep 17 00:00:00 2001
+From: Russell King <rmk+kernel@arm.linux.org.uk>
+Date: Fri, 2 Oct 2015 22:46:54 +0100
+Subject: phy: fixed-phy: remove fixed_phy_update_state()
+
+mvneta is the only user of fixed_phy_update_state(), which has been
+converted to use phylink instead.  Remove fixed_phy_update_state().
+
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
+---
+ drivers/net/phy/fixed_phy.c | 31 -------------------------------
+ include/linux/phy_fixed.h   |  9 ---------
+ 2 files changed, 40 deletions(-)
+
+--- a/drivers/net/phy/fixed_phy.c
++++ b/drivers/net/phy/fixed_phy.c
+@@ -115,37 +115,6 @@ int fixed_phy_set_link_update(struct phy
+ }
+ EXPORT_SYMBOL_GPL(fixed_phy_set_link_update);
+ 
+-int fixed_phy_update_state(struct phy_device *phydev,
+-			   const struct fixed_phy_status *status,
+-			   const struct fixed_phy_status *changed)
+-{
+-	struct fixed_mdio_bus *fmb = &platform_fmb;
+-	struct fixed_phy *fp;
+-
+-	if (!phydev || phydev->mdio.bus != fmb->mii_bus)
+-		return -EINVAL;
+-
+-	list_for_each_entry(fp, &fmb->phys, node) {
+-		if (fp->addr == phydev->mdio.addr) {
+-			write_seqcount_begin(&fp->seqcount);
+-#define _UPD(x) if (changed->x) \
+-	fp->status.x = status->x
+-			_UPD(link);
+-			_UPD(speed);
+-			_UPD(duplex);
+-			_UPD(pause);
+-			_UPD(asym_pause);
+-#undef _UPD
+-			fixed_phy_update(fp);
+-			write_seqcount_end(&fp->seqcount);
+-			return 0;
+-		}
+-	}
+-
+-	return -ENOENT;
+-}
+-EXPORT_SYMBOL(fixed_phy_update_state);
+-
+ int fixed_phy_add(unsigned int irq, int phy_addr,
+ 		  struct fixed_phy_status *status,
+ 		  int link_gpio)
+--- a/include/linux/phy_fixed.h
++++ b/include/linux/phy_fixed.h
+@@ -24,9 +24,6 @@ extern void fixed_phy_unregister(struct
+ extern int fixed_phy_set_link_update(struct phy_device *phydev,
+ 			int (*link_update)(struct net_device *,
+ 					   struct fixed_phy_status *));
+-extern int fixed_phy_update_state(struct phy_device *phydev,
+-			   const struct fixed_phy_status *status,
+-			   const struct fixed_phy_status *changed);
+ #else
+ static inline int fixed_phy_add(unsigned int irq, int phy_id,
+ 				struct fixed_phy_status *status,
+@@ -50,12 +47,6 @@ static inline int fixed_phy_set_link_upd
+ {
+ 	return -ENODEV;
+ }
+-static inline int fixed_phy_update_state(struct phy_device *phydev,
+-			   const struct fixed_phy_status *status,
+-			   const struct fixed_phy_status *changed)
+-{
+-	return -ENODEV;
+-}
+ #endif /* CONFIG_FIXED_PHY */
+ 
+ #endif /* __PHY_FIXED_H */

+ 181 - 0
target/linux/mvebu/patches-4.14/408-sfp-move-module-eeprom-ethtool-access-into-netdev-co.patch

@@ -0,0 +1,181 @@
+From c47beb7e3f8575dfd7d58240a72c4e4e66ce5449 Mon Sep 17 00:00:00 2001
+From: Russell King <rmk+kernel@armlinux.org.uk>
+Date: Fri, 14 Apr 2017 15:26:32 +0100
+Subject: sfp: move module eeprom ethtool access into netdev core ethtool
+
+Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
+---
+ drivers/net/ethernet/marvell/mvneta.c | 18 ------------------
+ drivers/net/phy/phylink.c             | 28 ----------------------------
+ drivers/net/phy/sfp-bus.c             |  6 ++----
+ include/linux/netdevice.h             |  2 ++
+ include/linux/phylink.h               |  3 ---
+ net/core/ethtool.c                    |  7 +++++++
+ 6 files changed, 11 insertions(+), 53 deletions(-)
+
+--- a/drivers/net/ethernet/marvell/mvneta.c
++++ b/drivers/net/ethernet/marvell/mvneta.c
+@@ -4044,22 +4044,6 @@ static int mvneta_ethtool_set_wol(struct
+ 	return ret;
+ }
+ 
+-static int mvneta_ethtool_get_module_info(struct net_device *dev,
+-					  struct ethtool_modinfo *modinfo)
+-{
+-	struct mvneta_port *pp = netdev_priv(dev);
+-
+-	return phylink_ethtool_get_module_info(pp->phylink, modinfo);
+-}
+-
+-static int mvneta_ethtool_get_module_eeprom(struct net_device *dev,
+-					    struct ethtool_eeprom *ee, u8 *buf)
+-{
+-	struct mvneta_port *pp = netdev_priv(dev);
+-
+-	return phylink_ethtool_get_module_eeprom(pp->phylink, ee, buf);
+-}
+-
+ static int mvneta_ethtool_get_eee(struct net_device *dev,
+ 				  struct ethtool_eee *eee)
+ {
+@@ -4144,8 +4128,6 @@ static const struct ethtool_ops mvneta_e
+ 	.set_link_ksettings = mvneta_ethtool_set_link_ksettings,
+ 	.get_wol        = mvneta_ethtool_get_wol,
+ 	.set_wol        = mvneta_ethtool_set_wol,
+-	.get_module_info = mvneta_ethtool_get_module_info,
+-	.get_module_eeprom = mvneta_ethtool_get_module_eeprom,
+ 	.get_eee	= mvneta_ethtool_get_eee,
+ 	.set_eee	= mvneta_ethtool_set_eee,
+ };
+--- a/drivers/net/phy/phylink.c
++++ b/drivers/net/phy/phylink.c
+@@ -1060,34 +1060,6 @@ int phylink_ethtool_set_pauseparam(struc
+ }
+ EXPORT_SYMBOL_GPL(phylink_ethtool_set_pauseparam);
+ 
+-int phylink_ethtool_get_module_info(struct phylink *pl,
+-				    struct ethtool_modinfo *modinfo)
+-{
+-	int ret = -EOPNOTSUPP;
+-
+-	WARN_ON(!lockdep_rtnl_is_held());
+-
+-	if (pl->sfp_bus)
+-		ret = sfp_get_module_info(pl->sfp_bus, modinfo);
+-
+-	return ret;
+-}
+-EXPORT_SYMBOL_GPL(phylink_ethtool_get_module_info);
+-
+-int phylink_ethtool_get_module_eeprom(struct phylink *pl,
+-				      struct ethtool_eeprom *ee, u8 *buf)
+-{
+-	int ret = -EOPNOTSUPP;
+-
+-	WARN_ON(!lockdep_rtnl_is_held());
+-
+-	if (pl->sfp_bus)
+-		ret = sfp_get_module_eeprom(pl->sfp_bus, ee, buf);
+-
+-	return ret;
+-}
+-EXPORT_SYMBOL_GPL(phylink_ethtool_get_module_eeprom);
+-
+ int phylink_init_eee(struct phylink *pl, bool clk_stop_enable)
+ {
+ 	int ret = -EPROTONOSUPPORT;
+--- a/drivers/net/phy/sfp-bus.c
++++ b/drivers/net/phy/sfp-bus.c
+@@ -279,6 +279,7 @@ static int sfp_register_bus(struct sfp_b
+ 	bus->socket_ops->attach(bus->sfp);
+ 	if (bus->started)
+ 		bus->socket_ops->start(bus->sfp);
++	bus->netdev->sfp_bus = bus;
+ 	bus->registered = true;
+ 	return 0;
+ }
+@@ -294,14 +295,13 @@ static void sfp_unregister_bus(struct sf
+ 		if (bus->phydev && ops && ops->disconnect_phy)
+ 			ops->disconnect_phy(bus->upstream);
+ 	}
++	bus->netdev->sfp_bus = NULL;
+ 	bus->registered = false;
+ }
+ 
+ 
+ int sfp_get_module_info(struct sfp_bus *bus, struct ethtool_modinfo *modinfo)
+ {
+-	if (!bus->registered)
+-		return -ENOIOCTLCMD;
+ 	return bus->socket_ops->module_info(bus->sfp, modinfo);
+ }
+ EXPORT_SYMBOL_GPL(sfp_get_module_info);
+@@ -309,8 +309,6 @@ EXPORT_SYMBOL_GPL(sfp_get_module_info);
+ int sfp_get_module_eeprom(struct sfp_bus *bus, struct ethtool_eeprom *ee,
+ 	u8 *data)
+ {
+-	if (!bus->registered)
+-		return -ENOIOCTLCMD;
+ 	return bus->socket_ops->module_eeprom(bus->sfp, ee, data);
+ }
+ EXPORT_SYMBOL_GPL(sfp_get_module_eeprom);
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -57,6 +57,7 @@ struct device;
+ struct phy_device;
+ struct dsa_switch_tree;
+ 
++struct sfp_bus;
+ /* 802.11 specific */
+ struct wireless_dev;
+ /* 802.15.4 specific */
+@@ -1940,6 +1941,7 @@ struct net_device {
+ 	struct netprio_map __rcu *priomap;
+ #endif
+ 	struct phy_device	*phydev;
++	struct sfp_bus		*sfp_bus;
+ 	struct lock_class_key	*qdisc_tx_busylock;
+ 	struct lock_class_key	*qdisc_running_key;
+ 	bool			proto_down;
+--- a/include/linux/phylink.h
++++ b/include/linux/phylink.h
+@@ -125,9 +125,6 @@ void phylink_ethtool_get_pauseparam(stru
+ 				    struct ethtool_pauseparam *);
+ int phylink_ethtool_set_pauseparam(struct phylink *,
+ 				   struct ethtool_pauseparam *);
+-int phylink_ethtool_get_module_info(struct phylink *, struct ethtool_modinfo *);
+-int phylink_ethtool_get_module_eeprom(struct phylink *,
+-				      struct ethtool_eeprom *, u8 *);
+ int phylink_init_eee(struct phylink *, bool);
+ int phylink_get_eee_err(struct phylink *);
+ int phylink_ethtool_get_eee(struct phylink *, struct ethtool_eee *);
+--- a/net/core/ethtool.c
++++ b/net/core/ethtool.c
+@@ -22,6 +22,7 @@
+ #include <linux/bitops.h>
+ #include <linux/uaccess.h>
+ #include <linux/vmalloc.h>
++#include <linux/sfp.h>
+ #include <linux/slab.h>
+ #include <linux/rtnetlink.h>
+ #include <linux/sched/signal.h>
+@@ -2214,6 +2215,9 @@ static int __ethtool_get_module_info(str
+ 	const struct ethtool_ops *ops = dev->ethtool_ops;
+ 	struct phy_device *phydev = dev->phydev;
+ 
++	if (dev->sfp_bus)
++		return sfp_get_module_info(dev->sfp_bus, modinfo);
++
+ 	if (phydev && phydev->drv && phydev->drv->module_info)
+ 		return phydev->drv->module_info(phydev, modinfo);
+ 
+@@ -2248,6 +2252,9 @@ static int __ethtool_get_module_eeprom(s
+ 	const struct ethtool_ops *ops = dev->ethtool_ops;
+ 	struct phy_device *phydev = dev->phydev;
+ 
++	if (dev->sfp_bus)
++		return sfp_get_module_eeprom(dev->sfp_bus, ee, data);
++
+ 	if (phydev && phydev->drv && phydev->drv->module_eeprom)
+ 		return phydev->drv->module_eeprom(phydev, ee, data);
+ 

+ 34 - 0
target/linux/mvebu/patches-4.14/409-sfp-use-netdev-sfp_bus-for-start-stop.patch

@@ -0,0 +1,34 @@
+From 883dc66755313e133a787eba4dfde313fe33525b Mon Sep 17 00:00:00 2001
+From: Russell King <rmk+kernel@armlinux.org.uk>
+Date: Fri, 14 Apr 2017 16:41:55 +0100
+Subject: sfp: use netdev sfp_bus for start/stop
+
+Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
+---
+ drivers/net/phy/phylink.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/phy/phylink.c
++++ b/drivers/net/phy/phylink.c
+@@ -777,8 +777,8 @@ void phylink_start(struct phylink *pl)
+ 	clear_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state);
+ 	phylink_run_resolve(pl);
+ 
+-	if (pl->sfp_bus)
+-		sfp_upstream_start(pl->sfp_bus);
++	if (pl->netdev->sfp_bus)
++		sfp_upstream_start(pl->netdev->sfp_bus);
+ 	if (pl->phydev)
+ 		phy_start(pl->phydev);
+ }
+@@ -790,8 +790,8 @@ void phylink_stop(struct phylink *pl)
+ 
+ 	if (pl->phydev)
+ 		phy_stop(pl->phydev);
+-	if (pl->sfp_bus)
+-		sfp_upstream_stop(pl->sfp_bus);
++	if (pl->netdev->sfp_bus)
++		sfp_upstream_stop(pl->netdev->sfp_bus);
+ 
+ 	phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_STOPPED);
+ }

+ 132 - 0
target/linux/mvebu/patches-4.14/410-sfp-hack-allow-marvell-10G-phy-support-to-use-SFP.patch

@@ -0,0 +1,132 @@
+From 4a4aca08b11501cb1b2c509113bbb65eb66a1f45 Mon Sep 17 00:00:00 2001
+From: Russell King <rmk+kernel@armlinux.org.uk>
+Date: Fri, 14 Apr 2017 14:21:25 +0100
+Subject: sfp: hack: allow marvell 10G phy support to use SFP
+
+Allow the Marvell 10G PHY to register with the SFP bus, so that SFP+
+cages can work.  This bypasses phylink, meaning that socket status
+is not taken into account for the link state.  Also, the tx-disable
+signal must be commented out in DT for this to work...
+
+Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
+---
+ drivers/net/phy/marvell10g.c | 54 +++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 53 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/phy/marvell10g.c
++++ b/drivers/net/phy/marvell10g.c
+@@ -15,8 +15,10 @@
+  * If both the fiber and copper ports are connected, the first to gain
+  * link takes priority and the other port is completely locked out.
+  */
++#include <linux/of.h>
+ #include <linux/phy.h>
+ #include <linux/marvell_phy.h>
++#include <linux/sfp.h>
+ 
+ enum {
+ 	MV_PMA_BOOT		= 0xc050,
+@@ -41,6 +43,11 @@ enum {
+ 	MV_AN_RESULT_SPD_10000	= BIT(15),
+ };
+ 
++struct mv3310_priv {
++	struct device_node *sfp_node;
++	struct sfp_bus *sfp_bus;
++};
++
+ static int mv3310_modify(struct phy_device *phydev, int devad, u16 reg,
+ 			 u16 mask, u16 bits)
+ {
+@@ -59,8 +66,25 @@ static int mv3310_modify(struct phy_devi
+ 	return ret < 0 ? ret : 1;
+ }
+ 
++static int mv3310_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
++{
++	struct phy_device *phydev = upstream;
++	struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
++
++	if (sfp_parse_interface(priv->sfp_bus, id) != PHY_INTERFACE_MODE_10GKR) {
++		dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n");
++		return -EINVAL;
++	}
++	return 0;
++}
++
++static const struct sfp_upstream_ops mv3310_sfp_ops = {
++	.module_insert = mv3310_sfp_insert,
++};
++
+ static int mv3310_probe(struct phy_device *phydev)
+ {
++	struct mv3310_priv *priv;
+ 	u32 mmd_mask = MDIO_DEVS_PMAPMD | MDIO_DEVS_AN;
+ 	int ret;
+ 
+@@ -78,9 +102,27 @@ static int mv3310_probe(struct phy_devic
+ 		return -ENODEV;
+ 	}
+ 
++	priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
++	if (!priv)
++		return -ENOMEM;
++
++	dev_set_drvdata(&phydev->mdio.dev, priv);
++
++	if (phydev->mdio.dev.of_node)
++		priv->sfp_node = of_parse_phandle(phydev->mdio.dev.of_node,
++						  "sfp", 0);
++
+ 	return 0;
+ }
+ 
++static void mv3310_remove(struct phy_device *phydev)
++{
++	struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
++
++	if (priv->sfp_bus)
++		sfp_unregister_upstream(priv->sfp_bus);
++}
++
+ /*
+  * Resetting the MV88X3310 causes it to become non-responsive.  Avoid
+  * setting the reset bit(s).
+@@ -92,6 +134,7 @@ static int mv3310_soft_reset(struct phy_
+ 
+ static int mv3310_config_init(struct phy_device *phydev)
+ {
++	struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
+ 	__ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = { 0, };
+ 	u32 mask;
+ 	int val;
+@@ -180,6 +223,14 @@ static int mv3310_config_init(struct phy
+ 	phydev->supported &= mask;
+ 	phydev->advertising &= phydev->supported;
+ 
++	/* Would be nice to do this in the probe function, but unfortunately,
++	 * phylib doesn't have phydev->attached_dev set there.
++	 */
++	if (priv->sfp_node && !priv->sfp_bus)
++		priv->sfp_bus = sfp_register_upstream(priv->sfp_node,
++						      phydev->attached_dev,
++						      phydev, &mv3310_sfp_ops);
++
+ 	return 0;
+ }
+ 
+@@ -363,12 +414,13 @@ static struct phy_driver mv3310_drivers[
+ 				  SUPPORTED_FIBRE |
+ 				  SUPPORTED_10000baseT_Full |
+ 				  SUPPORTED_Backplane,
+-		.probe		= mv3310_probe,
+ 		.soft_reset	= mv3310_soft_reset,
+ 		.config_init	= mv3310_config_init,
++		.probe		= mv3310_probe,
+ 		.config_aneg	= mv3310_config_aneg,
+ 		.aneg_done	= mv3310_aneg_done,
+ 		.read_status	= mv3310_read_status,
++		.remove		= mv3310_remove,
+ 	},
+ };
+ 

+ 24 - 0
target/linux/mvebu/patches-4.14/411-sfp-add-sfp-compatible.patch

@@ -0,0 +1,24 @@
+From 3344f73509a34d2124b716efc79cd9787773018b Mon Sep 17 00:00:00 2001
+From: Russell King <rmk+kernel@armlinux.org.uk>
+Date: Fri, 14 Apr 2017 20:17:13 +0100
+Subject: sfp: add sfp+ compatible
+
+Add a compatible for SFP+ cages.  SFP+ cages are backwards compatible,
+but the ethernet device behind them may not support the slower speeds
+of SFP modules.
+
+Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
+---
+ drivers/net/phy/sfp.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/phy/sfp.c
++++ b/drivers/net/phy/sfp.c
+@@ -1168,6 +1168,7 @@ static int sfp_remove(struct platform_de
+ 
+ static const struct of_device_id sfp_of_match[] = {
+ 	{ .compatible = "sff,sfp", },
++	{ .compatible = "sff,sfp+", },
+ 	{ },
+ };
+ MODULE_DEVICE_TABLE(of, sfp_of_match);

+ 87 - 0
target/linux/mvebu/patches-4.14/412-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
+@@ -48,6 +48,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 = <&microsom_sdhci_pins>;
++				pinctrl-names = "default";
++				status = "okay";
++				wp-inverted;
++			};
++		};
++	};
++};

+ 42 - 0
target/linux/mvebu/patches-4.14/413-ARM-dts-armada388-clearfog-increase-speed-of-i2c0-to.patch

@@ -0,0 +1,42 @@
+From 6e127081e669cf163a818dc04d590790e4ed9527 Mon Sep 17 00:00:00 2001
+From: Russell King <rmk+kernel@armlinux.org.uk>
+Date: Tue, 29 Nov 2016 20:06:44 +0000
+Subject: ARM: dts: armada388-clearfog: increase speed of i2c0 to 400kHz
+
+All the devices on I2C0 support fast mode, so increase the bus speed
+to match.  The Armada 388 is known to have a timing issue when in
+standard mode, which we believe causes the ficticious device at 0x64
+to appear.
+
+Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
+---
+ arch/arm/boot/dts/armada-388-clearfog.dtsi | 7 ++-----
+ 1 file changed, 2 insertions(+), 5 deletions(-)
+
+--- a/arch/arm/boot/dts/armada-388-clearfog.dtsi
++++ b/arch/arm/boot/dts/armada-388-clearfog.dtsi
+@@ -143,8 +143,7 @@
+ };
+ 
+ &i2c0 {
+-	/* Is there anything on this? */
+-	clock-frequency = <100000>;
++	clock-frequency = <400000>;
+ 	pinctrl-0 = <&i2c0_pins>;
+ 	pinctrl-names = "default";
+ 	status = "okay";
+@@ -239,13 +238,11 @@
+ 		};
+ 	};
+ 
+-	/* The MCP3021 is 100kHz clock only */
++	/* The MCP3021 supports standard and fast modes */
+ 	mikrobus_adc: mcp3021@4c {
+ 		compatible = "microchip,mcp3021";
+ 		reg = <0x4c>;
+ 	};
+-
+-	/* Also something at 0x64 */
+ };
+ 
+ &i2c1 {

+ 81 - 0
target/linux/mvebu/patches-4.14/414-ARM-dts-armada388-clearfog-add-SFP-module-support.patch

@@ -0,0 +1,81 @@
+From 74fa68669c88f73bceff523cb764297b7d1e132b Mon Sep 17 00:00:00 2001
+From: Russell King <rmk+kernel@arm.linux.org.uk>
+Date: Tue, 29 Nov 2016 10:13:44 +0000
+Subject: ARM: dts: armada388-clearfog: add SFP module support
+
+Add SFP module support for Clearfog using the SFP phylink support.
+
+Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
+---
+ arch/arm/boot/dts/armada-388-clearfog.dtsi | 44 ++++++++----------------------
+ 1 file changed, 11 insertions(+), 33 deletions(-)
+
+--- a/arch/arm/boot/dts/armada-388-clearfog.dtsi
++++ b/arch/arm/boot/dts/armada-388-clearfog.dtsi
+@@ -117,6 +117,15 @@
+ 			};
+ 		};
+ 	};
++
++	sfp: sfp {
++		compatible = "sff,sfp";
++		i2c-bus = <&i2c1>;
++		los-gpio = <&expander0 12 GPIO_ACTIVE_HIGH>;
++		mod-def0-gpio = <&expander0 15 GPIO_ACTIVE_LOW>;
++		tx-disable-gpio = <&expander0 14 GPIO_ACTIVE_HIGH>;
++		tx-fault-gpio = <&expander0 13 GPIO_ACTIVE_HIGH>;
++	};
+ };
+ 
+ &eth1 {
+@@ -133,13 +142,10 @@
+ 	bm,pool-long = <3>;
+ 	bm,pool-short = <1>;
+ 	buffer-manager = <&bm>;
++	managed = "in-band-status";
+ 	phy-mode = "sgmii";
++	sfp = <&sfp>;
+ 	status = "okay";
+-
+-	fixed-link {
+-		speed = <1000>;
+-		full-duplex;
+-	};
+ };
+ 
+ &i2c0 {
+@@ -208,34 +214,6 @@
+ 			output-low;
+ 			line-name = "m.2 devslp";
+ 		};
+-		sfp_los {
+-			/* SFP loss of signal */
+-			gpio-hog;
+-			gpios = <12 GPIO_ACTIVE_HIGH>;
+-			input;
+-			line-name = "sfp-los";
+-		};
+-		sfp_tx_fault {
+-			/* SFP laser fault */
+-			gpio-hog;
+-			gpios = <13 GPIO_ACTIVE_HIGH>;
+-			input;
+-			line-name = "sfp-tx-fault";
+-		};
+-		sfp_tx_disable {
+-			/* SFP transmit disable */
+-			gpio-hog;
+-			gpios = <14 GPIO_ACTIVE_HIGH>;
+-			output-low;
+-			line-name = "sfp-tx-disable";
+-		};
+-		sfp_mod_def0 {
+-			/* SFP module present */
+-			gpio-hog;
+-			gpios = <15 GPIO_ACTIVE_LOW>;
+-			input;
+-			line-name = "sfp-mod-def0";
+-		};
+ 	};
+ 
+ 	/* The MCP3021 supports standard and fast modes */

+ 124 - 0
target/linux/mvebu/patches-4.14/415-ARM-dts-armada388-clearfog-document-MPP-usage.patch

@@ -0,0 +1,124 @@
+From 09a0122c74ec076e08512f1b00b7ccb8a450282f Mon Sep 17 00:00:00 2001
+From: Russell King <rmk+kernel@arm.linux.org.uk>
+Date: Tue, 29 Nov 2016 10:15:43 +0000
+Subject: ARM: dts: armada388-clearfog: document MPP usage
+
+Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
+---
+ arch/arm/boot/dts/armada-388-clearfog-base.dts | 51 ++++++++++++++++++++++++++
+ arch/arm/boot/dts/armada-388-clearfog.dts      | 50 +++++++++++++++++++++++++
+ 2 files changed, 101 insertions(+)
+
+--- a/arch/arm/boot/dts/armada-388-clearfog-base.dts
++++ b/arch/arm/boot/dts/armada-388-clearfog-base.dts
+@@ -108,3 +108,54 @@
+ 		marvell,function = "gpio";
+ 	};
+ };
++
++/*
++MPP
++18: pu	gpio		pca9655 int
++19:	gpio		phy reset
++20: pu	gpio		sd0 detect
++21:	sd0:cmd
++22: pd	gpio		mikro int
++23:
++
++24:	ua1:rxd		mikro rx
++25:	ua1:txd		mikro tx
++26: pu	i2c1:sck
++27: pu	i2c1:sda
++28:	sd0:clk
++29: pd	gpio		mikro rst
++30:
++31:
++
++32:
++33:
++34:
++35:
++36:
++37:	sd0:d3
++38:	sd0:d0
++39:	sd0:d1
++
++40:	sd0:d2
++41:
++42:
++43:	spi1:cs2	mikro cs
++44:	gpio		rear button sw3
++45:	ref:clk_out0	phy#0 clock
++46:	ref:clk_out1	phy#1 clock
++47:
++
++48:	gpio		J18 spare gpio
++49:	gpio		U10 I2C_IRQ(GNSS)
++50:	gpio		board id?
++51:
++52:
++53:
++54:	gpio		mikro pwm
++55:
++
++56: pu	spi1:mosi	mikro mosi
++57: pd	spi1:sck	mikro sck
++58:	spi1:miso	mikro miso
++59:
++*/
+--- a/arch/arm/boot/dts/armada-388-clearfog.dts
++++ b/arch/arm/boot/dts/armada-388-clearfog.dts
+@@ -290,3 +290,53 @@
+ 	 */
+ 	pinctrl-0 = <&spi1_pins &clearfog_spi1_cs_pins &mikro_spi_pins>;
+ };
++/*
+++#define A38x_CUSTOMER_BOARD_1_MPP16_23         0x00400011
++MPP18: gpio		? (pca9655 int?)
++MPP19: gpio		? (clkreq?)
++MPP20: gpio		? (sd0 detect)
++MPP21: sd0:cmd		x sd0
++MPP22: gpio		x mikro int
++MPP23: gpio		x switch irq
+++#define A38x_CUSTOMER_BOARD_1_MPP24_31         0x22043333
++MPP24: ua1:rxd		x mikro rx
++MPP25: ua1:txd		x mikro tx
++MPP26: i2c1:sck		x mikro sck
++MPP27: i2c1:sda		x mikro sda
++MPP28: sd0:clk		x sd0
++MPP29: gpio		x mikro rst
++MPP30: ge1:txd2		? (config)
++MPP31: ge1:txd3		? (config)
+++#define A38x_CUSTOMER_BOARD_1_MPP32_39         0x44400002
++MPP32: ge1:txctl	? (unused)
++MPP33: gpio		? (pic_com0)
++MPP34: gpio		x rear button (pic_com1)
++MPP35: gpio		? (pic_com2)
++MPP36: gpio		? (unused)
++MPP37: sd0:d3		x sd0
++MPP38: sd0:d0		x sd0
++MPP39: sd0:d1		x sd0
+++#define A38x_CUSTOMER_BOARD_1_MPP40_47         0x41144004
++MPP40: sd0:d2		x sd0
++MPP41: gpio		x switch reset
++MPP42: gpio		? sw1-1
++MPP43: spi1:cs2		x mikro cs
++MPP44: sata3:prsnt	? (unused)
++MPP45: ref:clk_out0	?
++MPP46: ref:clk_out1	x switch clk
++MPP47: 4		? (unused)
+++#define A38x_CUSTOMER_BOARD_1_MPP48_55         0x40333333
++MPP48: tdm:pclk
++MPP49: tdm:fsync
++MPP50: tdm:drx
++MPP51: tdm:dtx
++MPP52: tdm:int
++MPP53: tdm:rst
++MPP54: gpio		? (pwm)
++MPP55: spi1:cs1		x slic
+++#define A38x_CUSTOMER_BOARD_1_MPP56_63         0x00004444
++MPP56: spi1:mosi	x mikro mosi
++MPP57: spi1:sck		x mikro sck
++MPP58: spi1:miso	x mikro miso
++MPP59: spi1:cs0		x w25q32
++*/

+ 143 - 0
target/linux/mvebu/patches-4.14/420-rtc-armada38x-add-support-for-trimming-the-RTC.patch

@@ -0,0 +1,143 @@
+commit f94ffbc2c2a4128c4412bb483d0807722dfb682b
+Author: Russell King <rmk+kernel@armlinux.org.uk>
+Date:   Fri Sep 29 11:23:31 2017 +0100
+
+    rtc: armada38x: add support for trimming the RTC
+    
+    Add support for trimming the RTC using the offset mechanism.  This RTC
+    supports two modes: low update mode and high update mode.  Low update
+    mode has finer precision than high update mode, so we use the low mode
+    where possible.
+    
+    Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
+    Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
+
+--- a/drivers/rtc/rtc-armada38x.c
++++ b/drivers/rtc/rtc-armada38x.c
+@@ -28,6 +28,8 @@
+ #define RTC_IRQ_AL_EN		    BIT(0)
+ #define RTC_IRQ_FREQ_EN		    BIT(1)
+ #define RTC_IRQ_FREQ_1HZ	    BIT(2)
++#define RTC_CCR		    0x18
++#define RTC_CCR_MODE		    BIT(15)
+ 
+ #define RTC_TIME	    0xC
+ #define RTC_ALARM1	    0x10
+@@ -343,18 +345,117 @@ static irqreturn_t armada38x_rtc_alarm_i
+ 	return IRQ_HANDLED;
+ }
+ 
++/*
++ * The information given in the Armada 388 functional spec is complex.
++ * They give two different formulas for calculating the offset value,
++ * but when considering "Offset" as an 8-bit signed integer, they both
++ * reduce down to (we shall rename "Offset" as "val" here):
++ *
++ *   val = (f_ideal / f_measured - 1) / resolution   where f_ideal = 32768
++ *
++ * Converting to time, f = 1/t:
++ *   val = (t_measured / t_ideal - 1) / resolution   where t_ideal = 1/32768
++ *
++ *   =>  t_measured / t_ideal = val * resolution + 1
++ *
++ * "offset" in the RTC interface is defined as:
++ *   t = t0 * (1 + offset * 1e-9)
++ * where t is the desired period, t0 is the measured period with a zero
++ * offset, which is t_measured above. With t0 = t_measured and t = t_ideal,
++ *   offset = (t_ideal / t_measured - 1) / 1e-9
++ *
++ *   => t_ideal / t_measured = offset * 1e-9 + 1
++ *
++ * so:
++ *
++ *   offset * 1e-9 + 1 = 1 / (val * resolution + 1)
++ *
++ * We want "resolution" to be an integer, so resolution = R * 1e-9, giving
++ *   offset = 1e18 / (val * R + 1e9) - 1e9
++ *   val = (1e18 / (offset + 1e9) - 1e9) / R
++ * with a common transformation:
++ *   f(x) = 1e18 / (x + 1e9) - 1e9
++ *   offset = f(val * R)
++ *   val = f(offset) / R
++ *
++ * Armada 38x supports two modes, fine mode (954ppb) and coarse mode (3815ppb).
++ */
++static long armada38x_ppb_convert(long ppb)
++{
++	long div = ppb + 1000000000L;
++
++	return div_s64(1000000000000000000LL + div / 2, div) - 1000000000L;
++}
++
++static int armada38x_rtc_read_offset(struct device *dev, long *offset)
++{
++	struct armada38x_rtc *rtc = dev_get_drvdata(dev);
++	unsigned long ccr, flags;
++	long ppb_cor;
++
++	spin_lock_irqsave(&rtc->lock, flags);
++	ccr = rtc->data->read_rtc_reg(rtc, RTC_CCR);
++	spin_unlock_irqrestore(&rtc->lock, flags);
++
++	ppb_cor = (ccr & RTC_CCR_MODE ? 3815 : 954) * (s8)ccr;
++	/* ppb_cor + 1000000000L can never be zero */
++	*offset = armada38x_ppb_convert(ppb_cor);
++
++	return 0;
++}
++
++static int armada38x_rtc_set_offset(struct device *dev, long offset)
++{
++	struct armada38x_rtc *rtc = dev_get_drvdata(dev);
++	unsigned long ccr = 0;
++	long ppb_cor, off;
++
++	/*
++	 * The maximum ppb_cor is -128 * 3815 .. 127 * 3815, but we
++	 * need to clamp the input.  This equates to -484270 .. 488558.
++	 * Not only is this to stop out of range "off" but also to
++	 * avoid the division by zero in armada38x_ppb_convert().
++	 */
++	offset = clamp(offset, -484270L, 488558L);
++
++	ppb_cor = armada38x_ppb_convert(offset);
++
++	/*
++	 * Use low update mode where possible, which gives a better
++	 * resolution of correction.
++	 */
++	off = DIV_ROUND_CLOSEST(ppb_cor, 954);
++	if (off > 127 || off < -128) {
++		ccr = RTC_CCR_MODE;
++		off = DIV_ROUND_CLOSEST(ppb_cor, 3815);
++	}
++
++	/*
++	 * Armada 388 requires a bit pattern in bits 14..8 depending on
++	 * the sign bit: { 0, ~S, S, S, S, S, S }
++	 */
++	ccr |= (off & 0x3fff) ^ 0x2000;
++	rtc_delayed_write(ccr, rtc, RTC_CCR);
++
++	return 0;
++}
++
+ static const struct rtc_class_ops armada38x_rtc_ops = {
+ 	.read_time = armada38x_rtc_read_time,
+ 	.set_time = armada38x_rtc_set_time,
+ 	.read_alarm = armada38x_rtc_read_alarm,
+ 	.set_alarm = armada38x_rtc_set_alarm,
+ 	.alarm_irq_enable = armada38x_rtc_alarm_irq_enable,
++	.read_offset = armada38x_rtc_read_offset,
++	.set_offset = armada38x_rtc_set_offset,
+ };
+ 
+ static const struct rtc_class_ops armada38x_rtc_ops_noirq = {
+ 	.read_time = armada38x_rtc_read_time,
+ 	.set_time = armada38x_rtc_set_time,
+ 	.read_alarm = armada38x_rtc_read_alarm,
++	.read_offset = armada38x_rtc_read_offset,
++	.set_offset = armada38x_rtc_set_offset,
+ };
+ 
+ static const struct armada38x_rtc_data armada38x_data = {

+ 73 - 0
target/linux/mvebu/patches-4.14/421-rtc-armada38x-reset-after-rtc-power-loss.patch

@@ -0,0 +1,73 @@
+From 1a990fefb641398fb580a0ea0be99b0ff27cbb9b Mon Sep 17 00:00:00 2001
+From: Baruch Siach <baruch@tkos.co.il>
+Date: Thu, 21 Jun 2018 20:40:23 +0300
+Subject: [PATCH] rtc: armada38x: reset after rtc power loss
+
+When the RTC block looses power it needs a reset sequence to make it
+usable again. Otherwise, writes to the time register have no effect.
+
+This reset sequence combines information from the mvebu_rtc driver in
+the Marvell provided U-Boot, and the SolidRun provided U-Boot repo.
+
+Tested on the Armada 388 based SolidRun Clearfog Base.
+
+Signed-off-by: Baruch Siach <baruch@tkos.co.il>
+Acked-by: Gregory CLEMENT <gregory.clement@bootlin.com>
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+---
+ drivers/rtc/rtc-armada38x.c | 23 +++++++++++++++++++++++
+ 1 file changed, 23 insertions(+)
+
+--- a/drivers/rtc/rtc-armada38x.c
++++ b/drivers/rtc/rtc-armada38x.c
+@@ -30,6 +30,8 @@
+ #define RTC_IRQ_FREQ_1HZ	    BIT(2)
+ #define RTC_CCR		    0x18
+ #define RTC_CCR_MODE		    BIT(15)
++#define RTC_CONF_TEST	    0x1C
++#define RTC_NOMINAL_TIMING	    BIT(13)
+ 
+ #define RTC_TIME	    0xC
+ #define RTC_ALARM1	    0x10
+@@ -75,6 +77,7 @@ struct armada38x_rtc {
+ 	void __iomem	    *regs_soc;
+ 	spinlock_t	    lock;
+ 	int		    irq;
++	bool		    initialized;
+ 	struct value_to_freq *val_to_freq;
+ 	struct armada38x_rtc_data *data;
+ };
+@@ -226,6 +229,23 @@ static int armada38x_rtc_read_time(struc
+ 	return 0;
+ }
+ 
++static void armada38x_rtc_reset(struct armada38x_rtc *rtc)
++{
++	u32 reg;
++
++	reg = rtc->data->read_rtc_reg(rtc, RTC_CONF_TEST);
++	/* If bits [7:0] are non-zero, assume RTC was uninitialized */
++	if (reg & 0xff) {
++		rtc_delayed_write(0, rtc, RTC_CONF_TEST);
++		msleep(500); /* Oscillator startup time */
++		rtc_delayed_write(0, rtc, RTC_TIME);
++		rtc_delayed_write(SOC_RTC_ALARM1 | SOC_RTC_ALARM2, rtc,
++				  RTC_STATUS);
++		rtc_delayed_write(RTC_NOMINAL_TIMING, rtc, RTC_CCR);
++	}
++	rtc->initialized = true;
++}
++
+ static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm)
+ {
+ 	struct armada38x_rtc *rtc = dev_get_drvdata(dev);
+@@ -237,6 +257,9 @@ static int armada38x_rtc_set_time(struct
+ 	if (ret)
+ 		goto out;
+ 
++	if (!rtc->initialized)
++		armada38x_rtc_reset(rtc);
++
+ 	spin_lock_irqsave(&rtc->lock, flags);
+ 	rtc_delayed_write(time, rtc, RTC_TIME);
+ 	spin_unlock_irqrestore(&rtc->lock, flags);

+ 28 - 0
target/linux/mvebu/patches-4.14/423-ARM-dts-armada-385-linksys-Disable-internal-RTC.patch

@@ -0,0 +1,28 @@
+From e1cac198fea08c31ec204bed84c279ab05d20389 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Sat, 17 Mar 2018 15:22:25 +0100
+Subject: ARM: dts: armada-385-linksys: Disable internal RTC
+
+The internal RTC does not work correctly on these Linksys boards based
+on Marvell SoCs. For me it only shows Wed Dec 31 23:59:59 1969 and for
+others it is off by 3 minutes in 10 minutes running, this was reported
+by multiple users. On the Linksys Mamba device the device tree comment
+says that no crystal is connected to the internal RTC, this is probably
+also true for the other devices.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ arch/arm/boot/dts/armada-385-linksys.dtsi | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/arch/arm/boot/dts/armada-385-linksys.dtsi
++++ b/arch/arm/boot/dts/armada-385-linksys.dtsi
+@@ -304,3 +304,8 @@
+ 	status = "okay";
+ 	usb-phy = <&usb3_1_phy>;
+ };
++
++&rtc {
++	/* No crystal connected to the internal RTC */
++	status = "disabled";
++};

+ 94 - 0
target/linux/mvebu/patches-4.14/450-reprobe_sfp_phy.patch

@@ -0,0 +1,94 @@
+From 28baa5e2635285b178326b301f534ed95c65dd01 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Thu, 29 Sep 2016 11:44:39 +0200
+Subject: [PATCH] sfp: retry phy probe if unsuccessful
+
+Some phys seem to take longer than 50 ms to come out of reset, so retry
+until we find a phy.
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ drivers/net/phy/sfp.c | 38 +++++++++++++++++++++++++-------------
+ 1 file changed, 25 insertions(+), 13 deletions(-)
+
+--- a/drivers/net/phy/sfp.c
++++ b/drivers/net/phy/sfp.c
+@@ -506,7 +506,7 @@ static void sfp_sm_phy_detach(struct sfp
+ 	sfp->mod_phy = NULL;
+ }
+ 
+-static void sfp_sm_probe_phy(struct sfp *sfp)
++static int sfp_sm_probe_phy(struct sfp *sfp)
+ {
+ 	struct phy_device *phy;
+ 	int err;
+@@ -516,11 +516,11 @@ static void sfp_sm_probe_phy(struct sfp
+ 	phy = mdiobus_scan(sfp->i2c_mii, SFP_PHY_ADDR);
+ 	if (phy == ERR_PTR(-ENODEV)) {
+ 		dev_info(sfp->dev, "no PHY detected\n");
+-		return;
++		return -EAGAIN;
+ 	}
+ 	if (IS_ERR(phy)) {
+ 		dev_err(sfp->dev, "mdiobus scan returned %ld\n", PTR_ERR(phy));
+-		return;
++		return PTR_ERR(phy);
+ 	}
+ 
+ 	err = sfp_add_phy(sfp->sfp_bus, phy);
+@@ -528,11 +528,13 @@ static void sfp_sm_probe_phy(struct sfp
+ 		phy_device_remove(phy);
+ 		phy_device_free(phy);
+ 		dev_err(sfp->dev, "sfp_add_phy failed: %d\n", err);
+-		return;
++		return err;
+ 	}
+ 
+ 	sfp->mod_phy = phy;
+ 	phy_start(phy);
++
++	return 0;
+ }
+ 
+ static void sfp_sm_link_up(struct sfp *sfp)
+@@ -578,14 +580,9 @@ static void sfp_sm_fault(struct sfp *sfp
+ 
+ static void sfp_sm_mod_init(struct sfp *sfp)
+ {
+-	sfp_module_tx_enable(sfp);
++	int ret = 0;
+ 
+-	/* Wait t_init before indicating that the link is up, provided the
+-	 * current state indicates no TX_FAULT.  If TX_FAULT clears before
+-	 * this time, that's fine too.
+-	 */
+-	sfp_sm_next(sfp, SFP_S_INIT, T_INIT_JIFFIES);
+-	sfp->sm_retries = 5;
++	sfp_module_tx_enable(sfp);
+ 
+ 	/* Setting the serdes link mode is guesswork: there's no
+ 	 * field in the EEPROM which indicates what mode should
+@@ -599,7 +596,22 @@ static void sfp_sm_mod_init(struct sfp *
+ 	if (sfp->id.base.e1000_base_t ||
+ 	    sfp->id.base.e100_base_lx ||
+ 	    sfp->id.base.e100_base_fx)
+-		sfp_sm_probe_phy(sfp);
++		ret = sfp_sm_probe_phy(sfp);
++
++	if (!ret) {
++		/* Wait t_init before indicating that the link is up, provided
++		 * the current state indicates no TX_FAULT.  If TX_FAULT clears
++		 * this time, that's fine too.
++		 */
++		sfp_sm_next(sfp, SFP_S_INIT, T_INIT_JIFFIES);
++		sfp->sm_retries = 5;
++		return;
++	}
++
++	if (ret == -EAGAIN)
++		sfp_sm_set_timer(sfp, T_PROBE_RETRY);
++	else
++		sfp_sm_next(sfp, SFP_S_TX_DISABLE, 0);
+ }
+ 
+ static int sfp_sm_mod_probe(struct sfp *sfp)

+ 70 - 0
target/linux/mvebu/patches-4.14/501-spi-a3700-Change-SPI-mode-before-asserting-chip-sele.patch

@@ -0,0 +1,70 @@
+From dd7aa8d4b53b3484ba31ba56f3ff1be7deb38530 Mon Sep 17 00:00:00 2001
+From: Maxime Chevallier <maxime.chevallier@smile.fr>
+Date: Tue, 10 Oct 2017 10:43:18 +0200
+Subject: spi: a3700: Change SPI mode before asserting chip-select
+
+The spi device mode should be configured in the controller before the
+chip-select is asserted, so that a clock polarity configuration change
+is not interpreted as a clock tick by the device.
+
+This patch moves the mode setting to the 'prepare_message' function
+instead of the 'transfer_one' function.
+
+By doing so, this patch also removes redundant code in
+a3700_spi_clock_set.
+
+This was tested on EspressoBin board, with spidev.
+
+Signed-off-by: Maxime Chevallier <maxime.chevallier@smile.fr>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ drivers/spi/spi-armada-3700.c | 17 ++++-------------
+ 1 file changed, 4 insertions(+), 13 deletions(-)
+
+--- a/drivers/spi/spi-armada-3700.c
++++ b/drivers/spi/spi-armada-3700.c
+@@ -214,7 +214,7 @@ static void a3700_spi_mode_set(struct a3
+ }
+ 
+ static void a3700_spi_clock_set(struct a3700_spi *a3700_spi,
+-				unsigned int speed_hz, u16 mode)
++				unsigned int speed_hz)
+ {
+ 	u32 val;
+ 	u32 prescale;
+@@ -239,17 +239,6 @@ static void a3700_spi_clock_set(struct a
+ 		val |= A3700_SPI_CLK_CAPT_EDGE;
+ 		spireg_write(a3700_spi, A3700_SPI_IF_TIME_REG, val);
+ 	}
+-
+-	val = spireg_read(a3700_spi, A3700_SPI_IF_CFG_REG);
+-	val &= ~(A3700_SPI_CLK_POL | A3700_SPI_CLK_PHA);
+-
+-	if (mode & SPI_CPOL)
+-		val |= A3700_SPI_CLK_POL;
+-
+-	if (mode & SPI_CPHA)
+-		val |= A3700_SPI_CLK_PHA;
+-
+-	spireg_write(a3700_spi, A3700_SPI_IF_CFG_REG, val);
+ }
+ 
+ static void a3700_spi_bytelen_set(struct a3700_spi *a3700_spi, unsigned int len)
+@@ -431,7 +420,7 @@ static void a3700_spi_transfer_setup(str
+ 
+ 	a3700_spi = spi_master_get_devdata(spi->master);
+ 
+-	a3700_spi_clock_set(a3700_spi, xfer->speed_hz, spi->mode);
++	a3700_spi_clock_set(a3700_spi, xfer->speed_hz);
+ 
+ 	byte_len = xfer->bits_per_word >> 3;
+ 
+@@ -592,6 +581,8 @@ static int a3700_spi_prepare_message(str
+ 
+ 	a3700_spi_bytelen_set(a3700_spi, 4);
+ 
++	a3700_spi_mode_set(a3700_spi, spi->mode);
++
+ 	return 0;
+ }
+ 

+ 27 - 0
target/linux/mvebu/patches-4.14/502-arm64-dts-marvell-armada-37xx-add-UART-clock.patch

@@ -0,0 +1,27 @@
+From 2ff0d0b5bb397c3dc5c9b97bd0f20948f0b77740 Mon Sep 17 00:00:00 2001
+From: Miquel Raynal <miquel.raynal@free-electrons.com>
+Date: Fri, 13 Oct 2017 11:01:57 +0200
+Subject: arm64: dts: marvell: armada-37xx: add UART clock
+
+Add the missing clock property to armada-3700 UART node.
+
+This clock will be used to derive the prescaler value to comply with
+the requested baudrate.
+
+Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com>
+Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
+Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
+---
+ arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
++++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
+@@ -135,6 +135,7 @@
+ 			uart0: serial@12000 {
+ 				compatible = "marvell,armada-3700-uart";
+ 				reg = <0x12000 0x200>;
++				clocks = <&xtalclk>;
+ 				interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+ 				status = "disabled";
+ 			};

+ 78 - 0
target/linux/mvebu/patches-4.14/503-clk-mvebu-armada-37xx-periph-cosmetic-changes.patch

@@ -0,0 +1,78 @@
+From adf4e289dd7f801c3fe12e0e6b491e11e548cd3d Mon Sep 17 00:00:00 2001
+From: Gregory CLEMENT <gregory.clement@free-electrons.com>
+Date: Thu, 30 Nov 2017 14:40:27 +0100
+Subject: clk: mvebu: armada-37xx-periph: cosmetic changes
+
+This patches fixes few cosmetic issues such as alignment, blank lines
+and required space.
+
+Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+---
+ drivers/clk/mvebu/armada-37xx-periph.c | 17 +++++++++--------
+ 1 file changed, 9 insertions(+), 8 deletions(-)
+
+--- a/drivers/clk/mvebu/armada-37xx-periph.c
++++ b/drivers/clk/mvebu/armada-37xx-periph.c
+@@ -79,6 +79,7 @@ static const struct clk_div_table clk_ta
+ 	{ .val = 1, .div = 4, },
+ 	{ .val = 0, .div = 0, }, /* last entry */
+ };
++
+ static const struct clk_ops clk_double_div_ops;
+ 
+ #define PERIPH_GATE(_name, _bit)		\
+@@ -217,7 +218,7 @@ PERIPH_CLK_FULL(counter, 23, 20, DIV_SEL
+ PERIPH_CLK_FULL_DD(eip97, 24, 24, DIV_SEL2, DIV_SEL2, 22, 19);
+ PERIPH_CLK_MUX_DIV(cpu, 22, DIV_SEL0, 28, clk_table6);
+ 
+-static struct clk_periph_data data_nb[] ={
++static struct clk_periph_data data_nb[] = {
+ 	REF_CLK_FULL_DD(mmc),
+ 	REF_CLK_FULL_DD(sata_host),
+ 	REF_CLK_FULL_DD(sec_at),
+@@ -281,7 +282,7 @@ static unsigned int get_div(void __iomem
+ }
+ 
+ static unsigned long clk_double_div_recalc_rate(struct clk_hw *hw,
+-		unsigned long parent_rate)
++						unsigned long parent_rate)
+ {
+ 	struct clk_double_div *double_div = to_clk_double_div(hw);
+ 	unsigned int div;
+@@ -303,6 +304,7 @@ static const struct of_device_id armada_
+ 	.data = data_sb, },
+ 	{ }
+ };
++
+ static int armada_3700_add_composite_clk(const struct clk_periph_data *data,
+ 					 void __iomem *reg, spinlock_t *lock,
+ 					 struct device *dev, struct clk_hw **hw)
+@@ -355,9 +357,9 @@ static int armada_3700_add_composite_clk
+ 	}
+ 
+ 	*hw = clk_hw_register_composite(dev, data->name, data->parent_names,
+-				       data->num_parents, mux_hw,
+-				       mux_ops, rate_hw, rate_ops,
+-				       gate_hw, gate_ops, CLK_IGNORE_UNUSED);
++					data->num_parents, mux_hw,
++					mux_ops, rate_hw, rate_ops,
++					gate_hw, gate_ops, CLK_IGNORE_UNUSED);
+ 
+ 	if (IS_ERR(*hw))
+ 		return PTR_ERR(*hw);
+@@ -406,12 +408,11 @@ static int armada_3700_periph_clock_prob
+ 		if (armada_3700_add_composite_clk(&data[i], reg,
+ 						  &driver_data->lock, dev, hw))
+ 			dev_err(dev, "Can't register periph clock %s\n",
+-			       data[i].name);
+-
++				data[i].name);
+ 	}
+ 
+ 	ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get,
+-				  driver_data->hw_data);
++				     driver_data->hw_data);
+ 	if (ret) {
+ 		for (i = 0; i < num_periph; i++)
+ 			clk_hw_unregister(driver_data->hw_data->hws[i]);

+ 178 - 0
target/linux/mvebu/patches-4.14/504-clk-mvebu-armada-37xx-periph-prepare-cpu-clk-to-be-u.patch

@@ -0,0 +1,178 @@
+From 9818a7a4fd10f72537cdf2a5ec3402f2c245ea24 Mon Sep 17 00:00:00 2001
+From: Gregory CLEMENT <gregory.clement@free-electrons.com>
+Date: Thu, 30 Nov 2017 14:40:28 +0100
+Subject: clk: mvebu: armada-37xx-periph: prepare cpu clk to be
+ used with DVFS
+
+When DVFS will be enabled then the cpu clk will use a different set of
+register at run time. That means that we won't be able to use the common
+callback and need to use our own ones.
+
+This patch prepares this change by switching on our own set of callbacks
+without modifying the behavior of the clocks.
+
+Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+---
+ drivers/clk/mvebu/armada-37xx-periph.c | 82 ++++++++++++++++++++++++++++++----
+ 1 file changed, 73 insertions(+), 9 deletions(-)
+
+--- a/drivers/clk/mvebu/armada-37xx-periph.c
++++ b/drivers/clk/mvebu/armada-37xx-periph.c
+@@ -46,7 +46,17 @@ struct clk_double_div {
+ 	u8 shift2;
+ };
+ 
++struct clk_pm_cpu {
++	struct clk_hw hw;
++	void __iomem *reg_mux;
++	u8 shift_mux;
++	u32 mask_mux;
++	void __iomem *reg_div;
++	u8 shift_div;
++};
++
+ #define to_clk_double_div(_hw) container_of(_hw, struct clk_double_div, hw)
++#define to_clk_pm_cpu(_hw) container_of(_hw, struct clk_pm_cpu, hw)
+ 
+ struct clk_periph_data {
+ 	const char *name;
+@@ -55,6 +65,7 @@ struct clk_periph_data {
+ 	struct clk_hw *mux_hw;
+ 	struct clk_hw *rate_hw;
+ 	struct clk_hw *gate_hw;
++	struct clk_hw *muxrate_hw;
+ 	bool is_double_div;
+ };
+ 
+@@ -81,6 +92,7 @@ static const struct clk_div_table clk_ta
+ };
+ 
+ static const struct clk_ops clk_double_div_ops;
++static const struct clk_ops clk_pm_cpu_ops;
+ 
+ #define PERIPH_GATE(_name, _bit)		\
+ struct clk_gate gate_##_name = {		\
+@@ -122,6 +134,18 @@ struct clk_divider rate_##_name = {		\
+ 	}					\
+ };
+ 
++#define PERIPH_PM_CPU(_name, _shift1, _reg, _shift2)	\
++struct clk_pm_cpu muxrate_##_name = {		\
++	.reg_mux = (void *)TBG_SEL,		\
++	.mask_mux = 3,				\
++	.shift_mux = _shift1,			\
++	.reg_div = (void *)_reg,		\
++	.shift_div = _shift2,			\
++	.hw.init = &(struct clk_init_data){	\
++		.ops =  &clk_pm_cpu_ops,	\
++	}					\
++};
++
+ #define PERIPH_CLK_FULL_DD(_name, _bit, _shift, _reg1, _reg2, _shift1, _shift2)\
+ static PERIPH_GATE(_name, _bit);			    \
+ static PERIPH_MUX(_name, _shift);			    \
+@@ -136,10 +160,6 @@ static PERIPH_DIV(_name, _reg, _shift1,
+ static PERIPH_GATE(_name, _bit);			\
+ static PERIPH_DIV(_name, _reg, _shift, _table);
+ 
+-#define PERIPH_CLK_MUX_DIV(_name, _shift,  _reg, _shift_div, _table)	\
+-static PERIPH_MUX(_name, _shift);			    \
+-static PERIPH_DIV(_name, _reg, _shift_div, _table);
+-
+ #define PERIPH_CLK_MUX_DD(_name, _shift, _reg1, _reg2, _shift1, _shift2)\
+ static PERIPH_MUX(_name, _shift);			    \
+ static PERIPH_DOUBLEDIV(_name, _reg1, _reg2, _shift1, _shift2);
+@@ -180,13 +200,12 @@ static PERIPH_DOUBLEDIV(_name, _reg1, _r
+ 	  .rate_hw = &rate_##_name.hw,				\
+ 	}
+ 
+-#define REF_CLK_MUX_DIV(_name)				\
++#define REF_CLK_PM_CPU(_name)				\
+ 	{ .name = #_name,				\
+ 	  .parent_names = (const char *[]){ "TBG-A-P",	\
+ 	      "TBG-B-P", "TBG-A-S", "TBG-B-S"},		\
+ 	  .num_parents = 4,				\
+-	  .mux_hw = &mux_##_name.hw,			\
+-	  .rate_hw = &rate_##_name.hw,			\
++	  .muxrate_hw = &muxrate_##_name.hw,		\
+ 	}
+ 
+ #define REF_CLK_MUX_DD(_name)				\
+@@ -216,7 +235,7 @@ PERIPH_CLK_FULL_DD(ddr_fclk, 21, 16, DIV
+ PERIPH_CLK_FULL(trace, 22, 18, DIV_SEL0, 20, clk_table6);
+ PERIPH_CLK_FULL(counter, 23, 20, DIV_SEL0, 23, clk_table6);
+ PERIPH_CLK_FULL_DD(eip97, 24, 24, DIV_SEL2, DIV_SEL2, 22, 19);
+-PERIPH_CLK_MUX_DIV(cpu, 22, DIV_SEL0, 28, clk_table6);
++static PERIPH_PM_CPU(cpu, 22, DIV_SEL0, 28);
+ 
+ static struct clk_periph_data data_nb[] = {
+ 	REF_CLK_FULL_DD(mmc),
+@@ -235,7 +254,7 @@ static struct clk_periph_data data_nb[]
+ 	REF_CLK_FULL(trace),
+ 	REF_CLK_FULL(counter),
+ 	REF_CLK_FULL_DD(eip97),
+-	REF_CLK_MUX_DIV(cpu),
++	REF_CLK_PM_CPU(cpu),
+ 	{ },
+ };
+ 
+@@ -297,6 +316,37 @@ static const struct clk_ops clk_double_d
+ 	.recalc_rate = clk_double_div_recalc_rate,
+ };
+ 
++static u8 clk_pm_cpu_get_parent(struct clk_hw *hw)
++{
++	struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
++	int num_parents = clk_hw_get_num_parents(hw);
++	u32 val;
++
++	val = readl(pm_cpu->reg_mux) >> pm_cpu->shift_mux;
++	val &= pm_cpu->mask_mux;
++
++	if (val >= num_parents)
++		return -EINVAL;
++
++	return val;
++}
++
++static unsigned long clk_pm_cpu_recalc_rate(struct clk_hw *hw,
++					    unsigned long parent_rate)
++{
++	struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
++	unsigned int div;
++
++	div = get_div(pm_cpu->reg_div, pm_cpu->shift_div);
++
++	return DIV_ROUND_UP_ULL((u64)parent_rate, div);
++}
++
++static const struct clk_ops clk_pm_cpu_ops = {
++	.get_parent = clk_pm_cpu_get_parent,
++	.recalc_rate = clk_pm_cpu_recalc_rate,
++};
++
+ static const struct of_device_id armada_3700_periph_clock_of_match[] = {
+ 	{ .compatible = "marvell,armada-3700-periph-clock-nb",
+ 	  .data = data_nb, },
+@@ -356,6 +406,20 @@ static int armada_3700_add_composite_clk
+ 		}
+ 	}
+ 
++	if (data->muxrate_hw) {
++		struct clk_pm_cpu *pmcpu_clk;
++		struct clk_hw *muxrate_hw = data->muxrate_hw;
++
++		pmcpu_clk =  to_clk_pm_cpu(muxrate_hw);
++		pmcpu_clk->reg_mux = reg + (u64)pmcpu_clk->reg_mux;
++		pmcpu_clk->reg_div = reg + (u64)pmcpu_clk->reg_div;
++
++		mux_hw = muxrate_hw;
++		rate_hw = muxrate_hw;
++		mux_ops = muxrate_hw->init->ops;
++		rate_ops = muxrate_hw->init->ops;
++	}
++
+ 	*hw = clk_hw_register_composite(dev, data->name, data->parent_names,
+ 					data->num_parents, mux_hw,
+ 					mux_ops, rate_hw, rate_ops,

+ 315 - 0
target/linux/mvebu/patches-4.14/505-clk-mvebu-armada-37xx-periph-add-DVFS-support-for-cp.patch

@@ -0,0 +1,315 @@
+From 2089dc33ea0e3917465929d4020fbff3d6dbf7f4 Mon Sep 17 00:00:00 2001
+From: Gregory CLEMENT <gregory.clement@free-electrons.com>
+Date: Thu, 30 Nov 2017 14:40:29 +0100
+Subject: clk: mvebu: armada-37xx-periph: add DVFS support for cpu clocks
+
+When DVFS is enabled the CPU clock setting is done using an other set of
+registers.
+
+These Power Management registers are exposed through a syscon as they
+will also be used by other drivers such as the cpufreq.
+
+This patch add the possibility to modify the CPU frequency using the
+associate load level matching the target frequency. Then all the
+frequency switch is handle by the hardware.
+
+Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
+[sboyd@codeaurora.org: Grow a local variable for regmap pointer
+to keep lines shorter]
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+---
+ drivers/clk/mvebu/armada-37xx-periph.c | 221 ++++++++++++++++++++++++++++++++-
+ 1 file changed, 217 insertions(+), 4 deletions(-)
+
+--- a/drivers/clk/mvebu/armada-37xx-periph.c
++++ b/drivers/clk/mvebu/armada-37xx-periph.c
+@@ -21,9 +21,11 @@
+  */
+ 
+ #include <linux/clk-provider.h>
++#include <linux/mfd/syscon.h>
+ #include <linux/of.h>
+ #include <linux/of_device.h>
+ #include <linux/platform_device.h>
++#include <linux/regmap.h>
+ #include <linux/slab.h>
+ 
+ #define TBG_SEL		0x0
+@@ -33,6 +35,26 @@
+ #define CLK_SEL		0x10
+ #define CLK_DIS		0x14
+ 
++#define LOAD_LEVEL_NR	4
++
++#define ARMADA_37XX_NB_L0L1	0x18
++#define ARMADA_37XX_NB_L2L3	0x1C
++#define		ARMADA_37XX_NB_TBG_DIV_OFF	13
++#define		ARMADA_37XX_NB_TBG_DIV_MASK	0x7
++#define		ARMADA_37XX_NB_CLK_SEL_OFF	11
++#define		ARMADA_37XX_NB_CLK_SEL_MASK	0x1
++#define		ARMADA_37XX_NB_TBG_SEL_OFF	9
++#define		ARMADA_37XX_NB_TBG_SEL_MASK	0x3
++#define		ARMADA_37XX_NB_CONFIG_SHIFT	16
++#define ARMADA_37XX_NB_DYN_MOD	0x24
++#define		ARMADA_37XX_NB_DFS_EN	31
++#define ARMADA_37XX_NB_CPU_LOAD	0x30
++#define		ARMADA_37XX_NB_CPU_LOAD_MASK	0x3
++#define		ARMADA_37XX_DVFS_LOAD_0		0
++#define		ARMADA_37XX_DVFS_LOAD_1		1
++#define		ARMADA_37XX_DVFS_LOAD_2		2
++#define		ARMADA_37XX_DVFS_LOAD_3		3
++
+ struct clk_periph_driver_data {
+ 	struct clk_hw_onecell_data *hw_data;
+ 	spinlock_t lock;
+@@ -53,6 +75,7 @@ struct clk_pm_cpu {
+ 	u32 mask_mux;
+ 	void __iomem *reg_div;
+ 	u8 shift_div;
++	struct regmap *nb_pm_base;
+ };
+ 
+ #define to_clk_double_div(_hw) container_of(_hw, struct clk_double_div, hw)
+@@ -316,14 +339,94 @@ static const struct clk_ops clk_double_d
+ 	.recalc_rate = clk_double_div_recalc_rate,
+ };
+ 
++static void armada_3700_pm_dvfs_update_regs(unsigned int load_level,
++					    unsigned int *reg,
++					    unsigned int *offset)
++{
++	if (load_level <= ARMADA_37XX_DVFS_LOAD_1)
++		*reg = ARMADA_37XX_NB_L0L1;
++	else
++		*reg = ARMADA_37XX_NB_L2L3;
++
++	if (load_level == ARMADA_37XX_DVFS_LOAD_0 ||
++	    load_level ==  ARMADA_37XX_DVFS_LOAD_2)
++		*offset += ARMADA_37XX_NB_CONFIG_SHIFT;
++}
++
++static bool armada_3700_pm_dvfs_is_enabled(struct regmap *base)
++{
++	unsigned int val, reg = ARMADA_37XX_NB_DYN_MOD;
++
++	if (IS_ERR(base))
++		return false;
++
++	regmap_read(base, reg, &val);
++
++	return !!(val & BIT(ARMADA_37XX_NB_DFS_EN));
++}
++
++static unsigned int armada_3700_pm_dvfs_get_cpu_div(struct regmap *base)
++{
++	unsigned int reg = ARMADA_37XX_NB_CPU_LOAD;
++	unsigned int offset = ARMADA_37XX_NB_TBG_DIV_OFF;
++	unsigned int load_level, div;
++
++	/*
++	 * This function is always called after the function
++	 * armada_3700_pm_dvfs_is_enabled, so no need to check again
++	 * if the base is valid.
++	 */
++	regmap_read(base, reg, &load_level);
++
++	/*
++	 * The register and the offset inside this register accessed to
++	 * read the current divider depend on the load level
++	 */
++	load_level &= ARMADA_37XX_NB_CPU_LOAD_MASK;
++	armada_3700_pm_dvfs_update_regs(load_level, &reg, &offset);
++
++	regmap_read(base, reg, &div);
++
++	return (div >> offset) & ARMADA_37XX_NB_TBG_DIV_MASK;
++}
++
++static unsigned int armada_3700_pm_dvfs_get_cpu_parent(struct regmap *base)
++{
++	unsigned int reg = ARMADA_37XX_NB_CPU_LOAD;
++	unsigned int offset = ARMADA_37XX_NB_TBG_SEL_OFF;
++	unsigned int load_level, sel;
++
++	/*
++	 * This function is always called after the function
++	 * armada_3700_pm_dvfs_is_enabled, so no need to check again
++	 * if the base is valid
++	 */
++	regmap_read(base, reg, &load_level);
++
++	/*
++	 * The register and the offset inside this register accessed to
++	 * read the current divider depend on the load level
++	 */
++	load_level &= ARMADA_37XX_NB_CPU_LOAD_MASK;
++	armada_3700_pm_dvfs_update_regs(load_level, &reg, &offset);
++
++	regmap_read(base, reg, &sel);
++
++	return (sel >> offset) & ARMADA_37XX_NB_TBG_SEL_MASK;
++}
++
+ static u8 clk_pm_cpu_get_parent(struct clk_hw *hw)
+ {
+ 	struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
+ 	int num_parents = clk_hw_get_num_parents(hw);
+ 	u32 val;
+ 
+-	val = readl(pm_cpu->reg_mux) >> pm_cpu->shift_mux;
+-	val &= pm_cpu->mask_mux;
++	if (armada_3700_pm_dvfs_is_enabled(pm_cpu->nb_pm_base)) {
++		val = armada_3700_pm_dvfs_get_cpu_parent(pm_cpu->nb_pm_base);
++	} else {
++		val = readl(pm_cpu->reg_mux) >> pm_cpu->shift_mux;
++		val &= pm_cpu->mask_mux;
++	}
+ 
+ 	if (val >= num_parents)
+ 		return -EINVAL;
+@@ -331,19 +434,124 @@ static u8 clk_pm_cpu_get_parent(struct c
+ 	return val;
+ }
+ 
++static int clk_pm_cpu_set_parent(struct clk_hw *hw, u8 index)
++{
++	struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
++	struct regmap *base = pm_cpu->nb_pm_base;
++	int load_level;
++
++	/*
++	 * We set the clock parent only if the DVFS is available but
++	 * not enabled.
++	 */
++	if (IS_ERR(base) || armada_3700_pm_dvfs_is_enabled(base))
++		return -EINVAL;
++
++	/* Set the parent clock for all the load level */
++	for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) {
++		unsigned int reg, mask,  val,
++			offset = ARMADA_37XX_NB_TBG_SEL_OFF;
++
++		armada_3700_pm_dvfs_update_regs(load_level, &reg, &offset);
++
++		val = index << offset;
++		mask = ARMADA_37XX_NB_TBG_SEL_MASK << offset;
++		regmap_update_bits(base, reg, mask, val);
++	}
++	return 0;
++}
++
+ static unsigned long clk_pm_cpu_recalc_rate(struct clk_hw *hw,
+ 					    unsigned long parent_rate)
+ {
+ 	struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
+ 	unsigned int div;
+ 
+-	div = get_div(pm_cpu->reg_div, pm_cpu->shift_div);
+-
++	if (armada_3700_pm_dvfs_is_enabled(pm_cpu->nb_pm_base))
++		div = armada_3700_pm_dvfs_get_cpu_div(pm_cpu->nb_pm_base);
++	else
++		div = get_div(pm_cpu->reg_div, pm_cpu->shift_div);
+ 	return DIV_ROUND_UP_ULL((u64)parent_rate, div);
+ }
+ 
++static long clk_pm_cpu_round_rate(struct clk_hw *hw, unsigned long rate,
++				  unsigned long *parent_rate)
++{
++	struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
++	struct regmap *base = pm_cpu->nb_pm_base;
++	unsigned int div = *parent_rate / rate;
++	unsigned int load_level;
++	/* only available when DVFS is enabled */
++	if (!armada_3700_pm_dvfs_is_enabled(base))
++		return -EINVAL;
++
++	for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) {
++		unsigned int reg, val, offset = ARMADA_37XX_NB_TBG_DIV_OFF;
++
++		armada_3700_pm_dvfs_update_regs(load_level, &reg, &offset);
++
++		regmap_read(base, reg, &val);
++
++		val >>= offset;
++		val &= ARMADA_37XX_NB_TBG_DIV_MASK;
++		if (val == div)
++			/*
++			 * We found a load level matching the target
++			 * divider, switch to this load level and
++			 * return.
++			 */
++			return *parent_rate / div;
++	}
++
++	/* We didn't find any valid divider */
++	return -EINVAL;
++}
++
++static int clk_pm_cpu_set_rate(struct clk_hw *hw, unsigned long rate,
++			       unsigned long parent_rate)
++{
++	struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
++	struct regmap *base = pm_cpu->nb_pm_base;
++	unsigned int div = parent_rate / rate;
++	unsigned int load_level;
++
++	/* only available when DVFS is enabled */
++	if (!armada_3700_pm_dvfs_is_enabled(base))
++		return -EINVAL;
++
++	for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) {
++		unsigned int reg, mask, val,
++			offset = ARMADA_37XX_NB_TBG_DIV_OFF;
++
++		armada_3700_pm_dvfs_update_regs(load_level, &reg, &offset);
++
++		regmap_read(base, reg, &val);
++		val >>= offset;
++		val &= ARMADA_37XX_NB_TBG_DIV_MASK;
++
++		if (val == div) {
++			/*
++			 * We found a load level matching the target
++			 * divider, switch to this load level and
++			 * return.
++			 */
++			reg = ARMADA_37XX_NB_CPU_LOAD;
++			mask = ARMADA_37XX_NB_CPU_LOAD_MASK;
++			regmap_update_bits(base, reg, mask, load_level);
++
++			return rate;
++		}
++	}
++
++	/* We didn't find any valid divider */
++	return -EINVAL;
++}
++
+ static const struct clk_ops clk_pm_cpu_ops = {
+ 	.get_parent = clk_pm_cpu_get_parent,
++	.set_parent = clk_pm_cpu_set_parent,
++	.round_rate = clk_pm_cpu_round_rate,
++	.set_rate = clk_pm_cpu_set_rate,
+ 	.recalc_rate = clk_pm_cpu_recalc_rate,
+ };
+ 
+@@ -409,6 +617,7 @@ static int armada_3700_add_composite_clk
+ 	if (data->muxrate_hw) {
+ 		struct clk_pm_cpu *pmcpu_clk;
+ 		struct clk_hw *muxrate_hw = data->muxrate_hw;
++		struct regmap *map;
+ 
+ 		pmcpu_clk =  to_clk_pm_cpu(muxrate_hw);
+ 		pmcpu_clk->reg_mux = reg + (u64)pmcpu_clk->reg_mux;
+@@ -418,6 +627,10 @@ static int armada_3700_add_composite_clk
+ 		rate_hw = muxrate_hw;
+ 		mux_ops = muxrate_hw->init->ops;
+ 		rate_ops = muxrate_hw->init->ops;
++
++		map = syscon_regmap_lookup_by_compatible(
++				"marvell,armada-3700-nb-pm");
++		pmcpu_clk->nb_pm_base = map;
+ 	}
+ 
+ 	*hw = clk_hw_register_composite(dev, data->name, data->parent_names,

+ 297 - 0
target/linux/mvebu/patches-4.14/506-cpufreq-Add-DVFS-support-for-Armada-37xx.patch

@@ -0,0 +1,297 @@
+From 92ce45fb875d7c3e021cc454482fe0687ff54f29 Mon Sep 17 00:00:00 2001
+From: Gregory CLEMENT <gregory.clement@free-electrons.com>
+Date: Thu, 14 Dec 2017 16:00:05 +0100
+Subject: cpufreq: Add DVFS support for Armada 37xx
+
+This patch adds DVFS support for the Armada 37xx SoCs
+
+There are up to four CPU frequency loads for Armada 37xx controlled by
+the hardware.
+
+This driver associates the CPU load level to a frequency, then the
+hardware will switch while selecting a load level.
+
+The hardware also can associate a voltage for each level (AVS support)
+but it is not yet supported
+
+Tested-by: Andre Heider <a.heider@gmail.com>
+Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
+Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+---
+ drivers/cpufreq/Kconfig.arm           |   7 +
+ drivers/cpufreq/Makefile              |   1 +
+ drivers/cpufreq/armada-37xx-cpufreq.c | 241 ++++++++++++++++++++++++++++++++++
+ 3 files changed, 249 insertions(+)
+ create mode 100644 drivers/cpufreq/armada-37xx-cpufreq.c
+
+--- a/drivers/cpufreq/Kconfig.arm
++++ b/drivers/cpufreq/Kconfig.arm
+@@ -2,6 +2,13 @@
+ # ARM CPU Frequency scaling drivers
+ #
+ 
++config ARM_ARMADA_37XX_CPUFREQ
++	tristate "Armada 37xx CPUFreq support"
++	depends on ARCH_MVEBU
++	help
++	  This adds the CPUFreq driver support for Marvell Armada 37xx SoCs.
++	  The Armada 37xx PMU supports 4 frequency and VDD levels.
++
+ # big LITTLE core layer and glue drivers
+ config ARM_BIG_LITTLE_CPUFREQ
+ 	tristate "Generic ARM big LITTLE CPUfreq driver"
+--- a/drivers/cpufreq/Makefile
++++ b/drivers/cpufreq/Makefile
+@@ -52,6 +52,7 @@ obj-$(CONFIG_ARM_BIG_LITTLE_CPUFREQ)	+=
+ # LITTLE drivers, so that it is probed last.
+ obj-$(CONFIG_ARM_DT_BL_CPUFREQ)		+= arm_big_little_dt.o
+ 
++obj-$(CONFIG_ARM_ARMADA_37XX_CPUFREQ)	+= armada-37xx-cpufreq.o
+ obj-$(CONFIG_ARM_BRCMSTB_AVS_CPUFREQ)	+= brcmstb-avs-cpufreq.o
+ obj-$(CONFIG_ARCH_DAVINCI)		+= davinci-cpufreq.o
+ obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ)	+= exynos5440-cpufreq.o
+--- /dev/null
++++ b/drivers/cpufreq/armada-37xx-cpufreq.c
+@@ -0,0 +1,241 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * CPU frequency scaling support for Armada 37xx platform.
++ *
++ * Copyright (C) 2017 Marvell
++ *
++ * Gregory CLEMENT <gregory.clement@free-electrons.com>
++ */
++
++#include <linux/clk.h>
++#include <linux/cpu.h>
++#include <linux/cpufreq.h>
++#include <linux/err.h>
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <linux/mfd/syscon.h>
++#include <linux/module.h>
++#include <linux/of_address.h>
++#include <linux/of_device.h>
++#include <linux/of_irq.h>
++#include <linux/platform_device.h>
++#include <linux/pm_opp.h>
++#include <linux/regmap.h>
++#include <linux/slab.h>
++
++/* Power management in North Bridge register set */
++#define ARMADA_37XX_NB_L0L1	0x18
++#define ARMADA_37XX_NB_L2L3	0x1C
++#define  ARMADA_37XX_NB_TBG_DIV_OFF	13
++#define  ARMADA_37XX_NB_TBG_DIV_MASK	0x7
++#define  ARMADA_37XX_NB_CLK_SEL_OFF	11
++#define  ARMADA_37XX_NB_CLK_SEL_MASK	0x1
++#define  ARMADA_37XX_NB_CLK_SEL_TBG	0x1
++#define  ARMADA_37XX_NB_TBG_SEL_OFF	9
++#define  ARMADA_37XX_NB_TBG_SEL_MASK	0x3
++#define  ARMADA_37XX_NB_VDD_SEL_OFF	6
++#define  ARMADA_37XX_NB_VDD_SEL_MASK	0x3
++#define  ARMADA_37XX_NB_CONFIG_SHIFT	16
++#define ARMADA_37XX_NB_DYN_MOD	0x24
++#define  ARMADA_37XX_NB_CLK_SEL_EN	BIT(26)
++#define  ARMADA_37XX_NB_TBG_EN		BIT(28)
++#define  ARMADA_37XX_NB_DIV_EN		BIT(29)
++#define  ARMADA_37XX_NB_VDD_EN		BIT(30)
++#define  ARMADA_37XX_NB_DFS_EN		BIT(31)
++#define ARMADA_37XX_NB_CPU_LOAD 0x30
++#define  ARMADA_37XX_NB_CPU_LOAD_MASK	0x3
++#define  ARMADA_37XX_DVFS_LOAD_0	0
++#define  ARMADA_37XX_DVFS_LOAD_1	1
++#define  ARMADA_37XX_DVFS_LOAD_2	2
++#define  ARMADA_37XX_DVFS_LOAD_3	3
++
++/*
++ * On Armada 37xx the Power management manages 4 level of CPU load,
++ * each level can be associated with a CPU clock source, a CPU
++ * divider, a VDD level, etc...
++ */
++#define LOAD_LEVEL_NR	4
++
++struct armada_37xx_dvfs {
++	u32 cpu_freq_max;
++	u8 divider[LOAD_LEVEL_NR];
++};
++
++static struct armada_37xx_dvfs armada_37xx_dvfs[] = {
++	{.cpu_freq_max = 1200*1000*1000, .divider = {1, 2, 4, 6} },
++	{.cpu_freq_max = 1000*1000*1000, .divider = {1, 2, 4, 5} },
++	{.cpu_freq_max = 800*1000*1000,  .divider = {1, 2, 3, 4} },
++	{.cpu_freq_max = 600*1000*1000,  .divider = {2, 4, 5, 6} },
++};
++
++static struct armada_37xx_dvfs *armada_37xx_cpu_freq_info_get(u32 freq)
++{
++	int i;
++
++	for (i = 0; i < ARRAY_SIZE(armada_37xx_dvfs); i++) {
++		if (freq == armada_37xx_dvfs[i].cpu_freq_max)
++			return &armada_37xx_dvfs[i];
++	}
++
++	pr_err("Unsupported CPU frequency %d MHz\n", freq/1000000);
++	return NULL;
++}
++
++/*
++ * Setup the four level managed by the hardware. Once the four level
++ * will be configured then the DVFS will be enabled.
++ */
++static void __init armada37xx_cpufreq_dvfs_setup(struct regmap *base,
++						 struct clk *clk, u8 *divider)
++{
++	int load_lvl;
++	struct clk *parent;
++
++	for (load_lvl = 0; load_lvl < LOAD_LEVEL_NR; load_lvl++) {
++		unsigned int reg, mask, val, offset = 0;
++
++		if (load_lvl <= ARMADA_37XX_DVFS_LOAD_1)
++			reg = ARMADA_37XX_NB_L0L1;
++		else
++			reg = ARMADA_37XX_NB_L2L3;
++
++		if (load_lvl == ARMADA_37XX_DVFS_LOAD_0 ||
++		    load_lvl == ARMADA_37XX_DVFS_LOAD_2)
++			offset += ARMADA_37XX_NB_CONFIG_SHIFT;
++
++		/* Set cpu clock source, for all the level we use TBG */
++		val = ARMADA_37XX_NB_CLK_SEL_TBG << ARMADA_37XX_NB_CLK_SEL_OFF;
++		mask = (ARMADA_37XX_NB_CLK_SEL_MASK
++			<< ARMADA_37XX_NB_CLK_SEL_OFF);
++
++		/*
++		 * Set cpu divider based on the pre-computed array in
++		 * order to have balanced step.
++		 */
++		val |= divider[load_lvl] << ARMADA_37XX_NB_TBG_DIV_OFF;
++		mask |= (ARMADA_37XX_NB_TBG_DIV_MASK
++			<< ARMADA_37XX_NB_TBG_DIV_OFF);
++
++		/* Set VDD divider which is actually the load level. */
++		val |= load_lvl << ARMADA_37XX_NB_VDD_SEL_OFF;
++		mask |= (ARMADA_37XX_NB_VDD_SEL_MASK
++			<< ARMADA_37XX_NB_VDD_SEL_OFF);
++
++		val <<= offset;
++		mask <<= offset;
++
++		regmap_update_bits(base, reg, mask, val);
++	}
++
++	/*
++	 * Set cpu clock source, for all the level we keep the same
++	 * clock source that the one already configured. For this one
++	 * we need to use the clock framework
++	 */
++	parent = clk_get_parent(clk);
++	clk_set_parent(clk, parent);
++}
++
++static void __init armada37xx_cpufreq_disable_dvfs(struct regmap *base)
++{
++	unsigned int reg = ARMADA_37XX_NB_DYN_MOD,
++		mask = ARMADA_37XX_NB_DFS_EN;
++
++	regmap_update_bits(base, reg, mask, 0);
++}
++
++static void __init armada37xx_cpufreq_enable_dvfs(struct regmap *base)
++{
++	unsigned int val, reg = ARMADA_37XX_NB_CPU_LOAD,
++		mask = ARMADA_37XX_NB_CPU_LOAD_MASK;
++
++	/* Start with the highest load (0) */
++	val = ARMADA_37XX_DVFS_LOAD_0;
++	regmap_update_bits(base, reg, mask, val);
++
++	/* Now enable DVFS for the CPUs */
++	reg = ARMADA_37XX_NB_DYN_MOD;
++	mask =	ARMADA_37XX_NB_CLK_SEL_EN | ARMADA_37XX_NB_TBG_EN |
++		ARMADA_37XX_NB_DIV_EN | ARMADA_37XX_NB_VDD_EN |
++		ARMADA_37XX_NB_DFS_EN;
++
++	regmap_update_bits(base, reg, mask, mask);
++}
++
++static int __init armada37xx_cpufreq_driver_init(void)
++{
++	struct armada_37xx_dvfs *dvfs;
++	struct platform_device *pdev;
++	unsigned int cur_frequency;
++	struct regmap *nb_pm_base;
++	struct device *cpu_dev;
++	int load_lvl, ret;
++	struct clk *clk;
++
++	nb_pm_base =
++		syscon_regmap_lookup_by_compatible("marvell,armada-3700-nb-pm");
++
++	if (IS_ERR(nb_pm_base))
++		return -ENODEV;
++
++	/* Before doing any configuration on the DVFS first, disable it */
++	armada37xx_cpufreq_disable_dvfs(nb_pm_base);
++
++	/*
++	 * On CPU 0 register the operating points supported (which are
++	 * the nominal CPU frequency and full integer divisions of
++	 * it).
++	 */
++	cpu_dev = get_cpu_device(0);
++	if (!cpu_dev) {
++		dev_err(cpu_dev, "Cannot get CPU\n");
++		return -ENODEV;
++	}
++
++	clk = clk_get(cpu_dev, 0);
++	if (IS_ERR(clk)) {
++		dev_err(cpu_dev, "Cannot get clock for CPU0\n");
++		return PTR_ERR(clk);
++	}
++
++	/* Get nominal (current) CPU frequency */
++	cur_frequency = clk_get_rate(clk);
++	if (!cur_frequency) {
++		dev_err(cpu_dev, "Failed to get clock rate for CPU\n");
++		return -EINVAL;
++	}
++
++	dvfs = armada_37xx_cpu_freq_info_get(cur_frequency);
++	if (!dvfs)
++		return -EINVAL;
++
++	armada37xx_cpufreq_dvfs_setup(nb_pm_base, clk, dvfs->divider);
++
++	for (load_lvl = ARMADA_37XX_DVFS_LOAD_0; load_lvl < LOAD_LEVEL_NR;
++	     load_lvl++) {
++		unsigned long freq = cur_frequency / dvfs->divider[load_lvl];
++
++		ret = dev_pm_opp_add(cpu_dev, freq, 0);
++		if (ret) {
++			/* clean-up the already added opp before leaving */
++			while (load_lvl-- > ARMADA_37XX_DVFS_LOAD_0) {
++				freq = cur_frequency / dvfs->divider[load_lvl];
++				dev_pm_opp_remove(cpu_dev, freq);
++			}
++			return ret;
++		}
++	}
++
++	/* Now that everything is setup, enable the DVFS at hardware level */
++	armada37xx_cpufreq_enable_dvfs(nb_pm_base);
++
++	pdev = platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
++
++	return PTR_ERR_OR_ZERO(pdev);
++}
++/* late_initcall, to guarantee the driver is loaded after A37xx clock driver */
++late_initcall(armada37xx_cpufreq_driver_init);
++
++MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
++MODULE_DESCRIPTION("Armada 37xx cpufreq driver");
++MODULE_LICENSE("GPL");

+ 48 - 0
target/linux/mvebu/patches-4.14/507-arm64-dts-marvell-armada-37xx-add-nodes-allowing-cpu.patch

@@ -0,0 +1,48 @@
+From e8d66e7927b2a15310df0eb44a67d120ea147a59 Mon Sep 17 00:00:00 2001
+From: Gregory CLEMENT <gregory.clement@free-electrons.com>
+Date: Thu, 14 Dec 2017 16:00:06 +0100
+Subject: arm64: dts: marvell: armada-37xx: add nodes allowing cpufreq
+ support
+
+In order to be able to use cpu freq, we need to associate a clock to each
+CPU and to expose the power management registers.
+
+Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
+---
+ arch/arm64/boot/dts/marvell/armada-372x.dtsi | 1 +
+ arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 7 +++++++
+ 2 files changed, 8 insertions(+)
+
+--- a/arch/arm64/boot/dts/marvell/armada-372x.dtsi
++++ b/arch/arm64/boot/dts/marvell/armada-372x.dtsi
+@@ -56,6 +56,7 @@
+ 			device_type = "cpu";
+ 			compatible = "arm,cortex-a53","arm,armv8";
+ 			reg = <0x1>;
++			clocks = <&nb_periph_clk 16>;
+ 			enable-method = "psci";
+ 		};
+ 	};
+--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
++++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
+@@ -64,6 +64,7 @@
+ 			device_type = "cpu";
+ 			compatible = "arm,cortex-a53", "arm,armv8";
+ 			reg = <0>;
++			clocks = <&nb_periph_clk 16>;
+ 			enable-method = "psci";
+ 		};
+ 	};
+@@ -219,6 +220,12 @@
+ 				};
+ 			};
+ 
++			nb_pm: syscon@14000 {
++				compatible = "marvell,armada-3700-nb-pm",
++					     "syscon";
++				reg = <0x14000 0x60>;
++			};
++
+ 			pinctrl_sb: pinctrl@18800 {
+ 				compatible = "marvell,armada3710-sb-pinctrl",
+ 					     "syscon", "simple-mfd";

+ 56 - 0
target/linux/mvebu/patches-4.14/508-arm64-dts-armada-3720-espressobin-wire-up-spi-flash.patch

@@ -0,0 +1,56 @@
+From bffed3d4abcd32ba6d492a9bd7ebe81dc92eaa9a Mon Sep 17 00:00:00 2001
+From: Ellie Reeves <ellierevves@gmail.com>
+Date: Sun, 25 Mar 2018 21:57:36 +0200
+Subject: [PATCH] arm64: dts: armada-3720-espressobin: wire up spi flash
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This is the storage the machine boots from by default. The partitioning
+is taken from the U-Boot that is shipped with the board. There is some
+more space on the flash that isn't used.
+
+Tested-by: Gregory CLEMENT <gregory.clement@bootlin.com>
+Signed-off-by: Ellie Reeves <ellierevves@gmail.com>
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Signed-off-by: Gregory CLEMENT <gregory.clement@bootlin.com>
+---
+ .../dts/marvell/armada-3720-espressobin.dts   | 27 +++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+--- a/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts
++++ b/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts
+@@ -96,6 +96,33 @@
+ 	status = "okay";
+ };
+ 
++&spi0 {
++	status = "okay";
++
++	flash@0 {
++		reg = <0>;
++		compatible = "winbond,w25q32dw", "jedec,spi-flash";
++		spi-max-frequency = <104000000>;
++		m25p,fast-read;
++
++		partitions {
++			compatible = "fixed-partitions";
++			#address-cells = <1>;
++			#size-cells = <1>;
++
++			partition@0 {
++				label = "uboot";
++				reg = <0 0x180000>;
++			};
++
++			partition@180000 {
++				label = "ubootenv";
++				reg = <0x180000 0x10000>;
++			};
++		};
++	};
++};
++
+ /* Exported on the micro USB connector J5 through an FTDI */
+ &uart0 {
+ 	status = "okay";

+ 35 - 0
target/linux/mvebu/patches-4.14/509-cpufreq-armada-37xx-Fix-clock-leak.patch

@@ -0,0 +1,35 @@
+From bbcc328561040292f7d6796954d478e4a2335e6f Mon Sep 17 00:00:00 2001
+From: Gregory CLEMENT <gregory.clement@bootlin.com>
+Date: Wed, 4 Apr 2018 16:44:44 +0200
+Subject: [PATCH] cpufreq: armada-37xx: Fix clock leak
+
+There was no clk_put() balancing the clk_get(). This commit fixes it.
+
+Fixes: 92ce45fb875d (cpufreq: Add DVFS support for Armada 37xx)
+Cc: 4.16+ <stable@vger.kernel.org> # 4.16+
+Reported-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
+Signed-off-by: Gregory CLEMENT <gregory.clement@bootlin.com>
+Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+---
+ drivers/cpufreq/armada-37xx-cpufreq.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/cpufreq/armada-37xx-cpufreq.c
++++ b/drivers/cpufreq/armada-37xx-cpufreq.c
+@@ -202,6 +202,7 @@ static int __init armada37xx_cpufreq_dri
+ 	cur_frequency = clk_get_rate(clk);
+ 	if (!cur_frequency) {
+ 		dev_err(cpu_dev, "Failed to get clock rate for CPU\n");
++		clk_put(clk);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -210,6 +211,7 @@ static int __init armada37xx_cpufreq_dri
+ 		return -EINVAL;
+ 
+ 	armada37xx_cpufreq_dvfs_setup(nb_pm_base, clk, dvfs->divider);
++	clk_put(clk);
+ 
+ 	for (load_lvl = ARMADA_37XX_DVFS_LOAD_0; load_lvl < LOAD_LEVEL_NR;
+ 	     load_lvl++) {

+ 92 - 0
target/linux/mvebu/patches-4.14/510-clk-mvebu-armada-37xx-periph-Fix-switching-CPU-rate-.patch

@@ -0,0 +1,92 @@
+From 61c40f35f5cd6f67ccbd7319a1722eb78c815989 Mon Sep 17 00:00:00 2001
+From: Gregory CLEMENT <gregory.clement@bootlin.com>
+Date: Tue, 19 Jun 2018 14:34:45 +0200
+Subject: [PATCH] clk: mvebu: armada-37xx-periph: Fix switching CPU rate from
+ 300Mhz to 1.2GHz
+
+Switching the CPU from the L2 or L3 frequencies (300 and 200 Mhz
+respectively) to L0 frequency (1.2 Ghz) requires a significant amount
+of time to let VDD stabilize to the appropriate voltage. This amount of
+time is large enough that it cannot be covered by the hardware
+countdown register. Due to this, the CPU might start operating at L0
+before the voltage is stabilized, leading to CPU stalls.
+
+To work around this problem, we prevent switching directly from the
+L2/L3 frequencies to the L0 frequency, and instead switch to the L1
+frequency in-between. The sequence therefore becomes:
+
+1. First switch from L2/L3(200/300MHz) to L1(600MHZ)
+2. Sleep 20ms for stabling VDD voltage
+3. Then switch from L1(600MHZ) to L0(1200Mhz).
+
+It is based on the work done by Ken Ma <make@marvell.com>
+
+Cc: stable@vger.kernel.org
+Fixes: 2089dc33ea0e ("clk: mvebu: armada-37xx-periph: add DVFS support for cpu clocks")
+Signed-off-by: Gregory CLEMENT <gregory.clement@bootlin.com>
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+---
+ drivers/clk/mvebu/armada-37xx-periph.c | 38 ++++++++++++++++++++++++++
+ 1 file changed, 38 insertions(+)
+
+--- a/drivers/clk/mvebu/armada-37xx-periph.c
++++ b/drivers/clk/mvebu/armada-37xx-periph.c
+@@ -35,6 +35,7 @@
+ #define CLK_SEL		0x10
+ #define CLK_DIS		0x14
+ 
++#define  ARMADA_37XX_DVFS_LOAD_1 1
+ #define LOAD_LEVEL_NR	4
+ 
+ #define ARMADA_37XX_NB_L0L1	0x18
+@@ -507,6 +508,40 @@ static long clk_pm_cpu_round_rate(struct
+ 	return -EINVAL;
+ }
+ 
++/*
++ * Switching the CPU from the L2 or L3 frequencies (300 and 200 Mhz
++ * respectively) to L0 frequency (1.2 Ghz) requires a significant
++ * amount of time to let VDD stabilize to the appropriate
++ * voltage. This amount of time is large enough that it cannot be
++ * covered by the hardware countdown register. Due to this, the CPU
++ * might start operating at L0 before the voltage is stabilized,
++ * leading to CPU stalls.
++ *
++ * To work around this problem, we prevent switching directly from the
++ * L2/L3 frequencies to the L0 frequency, and instead switch to the L1
++ * frequency in-between. The sequence therefore becomes:
++ * 1. First switch from L2/L3(200/300MHz) to L1(600MHZ)
++ * 2. Sleep 20ms for stabling VDD voltage
++ * 3. Then switch from L1(600MHZ) to L0(1200Mhz).
++ */
++static void clk_pm_cpu_set_rate_wa(unsigned long rate, struct regmap *base)
++{
++	unsigned int cur_level;
++
++	if (rate != 1200 * 1000 * 1000)
++		return;
++
++	regmap_read(base, ARMADA_37XX_NB_CPU_LOAD, &cur_level);
++	cur_level &= ARMADA_37XX_NB_CPU_LOAD_MASK;
++	if (cur_level <= ARMADA_37XX_DVFS_LOAD_1)
++		return;
++
++	regmap_update_bits(base, ARMADA_37XX_NB_CPU_LOAD,
++			   ARMADA_37XX_NB_CPU_LOAD_MASK,
++			   ARMADA_37XX_DVFS_LOAD_1);
++	msleep(20);
++}
++
+ static int clk_pm_cpu_set_rate(struct clk_hw *hw, unsigned long rate,
+ 			       unsigned long parent_rate)
+ {
+@@ -537,6 +572,9 @@ static int clk_pm_cpu_set_rate(struct cl
+ 			 */
+ 			reg = ARMADA_37XX_NB_CPU_LOAD;
+ 			mask = ARMADA_37XX_NB_CPU_LOAD_MASK;
++
++			clk_pm_cpu_set_rate_wa(rate, base);
++
+ 			regmap_update_bits(base, reg, mask, load_level);
+ 
+ 			return rate;

+ 33 - 0
target/linux/mvebu/patches-4.14/511-clk-mvebu-armada-37xx-periph-Fix-wrong-return-value-.patch

@@ -0,0 +1,33 @@
+From 616bf80d381da13fbb392ebff06f46f946e3ee84 Mon Sep 17 00:00:00 2001
+From: Gregory CLEMENT <gregory.clement@bootlin.com>
+Date: Fri, 13 Jul 2018 12:27:26 +0200
+Subject: [PATCH] clk: mvebu: armada-37xx-periph: Fix wrong return value in
+ get_parent
+
+The return value of the get_parent operation is a u8, whereas a -EINVAL
+was returned. This wrong value was return if the value was bigger that
+the number of parent but this case was already handled by the core.
+
+So we can just remove this chunk of code to fix the issue.
+
+Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
+Fixes: 9818a7a4fd10 ("clk: mvebu: armada-37xx-periph: prepare cpu clk to
+be used with DVFS")
+Signed-off-by: Gregory CLEMENT <gregory.clement@bootlin.com>
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+---
+ drivers/clk/mvebu/armada-37xx-periph.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+--- a/drivers/clk/mvebu/armada-37xx-periph.c
++++ b/drivers/clk/mvebu/armada-37xx-periph.c
+@@ -429,9 +429,6 @@ static u8 clk_pm_cpu_get_parent(struct c
+ 		val &= pm_cpu->mask_mux;
+ 	}
+ 
+-	if (val >= num_parents)
+-		return -EINVAL;
+-
+ 	return val;
+ }
+ 

+ 33 - 0
target/linux/mvebu/patches-4.14/512-clk-mvebu-armada-37xx-periph-Remove-unused-var-num_p.patch

@@ -0,0 +1,33 @@
+From 8927c27b32703e28041ae19bf25ea53461be83a1 Mon Sep 17 00:00:00 2001
+From: Anders Roxell <anders.roxell@linaro.org>
+Date: Fri, 27 Jul 2018 00:27:21 +0200
+Subject: [PATCH] clk: mvebu: armada-37xx-periph: Remove unused var num_parents
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+When building armada-37xx-periph, num_parents isn't used in function
+clk_pm_cpu_get_parent:
+drivers/clk/mvebu/armada-37xx-periph.c: In function ‘clk_pm_cpu_get_parent’:
+drivers/clk/mvebu/armada-37xx-periph.c:419:6: warning: unused variable ‘num_parents’ [-Wunused-variable]
+  int num_parents = clk_hw_get_num_parents(hw);
+      ^~~~~~~~~~~
+Remove the declaration of num_parents to dispose the warning.
+
+Fixes: 616bf80d381d ("clk: mvebu: armada-37xx-periph: Fix wrong return value in get_parent")
+Signed-off-by: Anders Roxell <anders.roxell@linaro.org>
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+---
+ drivers/clk/mvebu/armada-37xx-periph.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/clk/mvebu/armada-37xx-periph.c
++++ b/drivers/clk/mvebu/armada-37xx-periph.c
+@@ -419,7 +419,6 @@ static unsigned int armada_3700_pm_dvfs_
+ static u8 clk_pm_cpu_get_parent(struct clk_hw *hw)
+ {
+ 	struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
+-	int num_parents = clk_hw_get_num_parents(hw);
+ 	u32 val;
+ 
+ 	if (armada_3700_pm_dvfs_is_enabled(pm_cpu->nb_pm_base)) {

+ 40 - 0
target/linux/mvebu/patches-4.14/513-arm64-dts-marvell-armada37xx-Add-emmc-sdio-pinctrl-d.patch

@@ -0,0 +1,40 @@
+From eefe328439642101774f0f5c4ea0dc6ba1cfb687 Mon Sep 17 00:00:00 2001
+From: Ding Tao <miyatsu@qq.com>
+Date: Fri, 26 Oct 2018 11:50:27 +0000
+Subject: [PATCH] arm64: dts: marvell: armada37xx: Add emmc/sdio pinctrl
+ definition
+
+Add emmc/sdio pinctrl definition for marvell armada37xx SoCs.
+
+Signed-off-by: Ding Tao <miyatsu@qq.com>
+Signed-off-by: Gregory CLEMENT <gregory.clement@bootlin.com>
+---
+ arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
++++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
+@@ -218,6 +218,11 @@
+ 					groups = "uart2";
+ 					function = "uart";
+ 				};
++
++				mmc_pins: mmc-pins {
++					groups = "emmc_nb";
++					function = "emmc";
++				};
+ 			};
+ 
+ 			nb_pm: syscon@14000 {
+@@ -247,6 +252,11 @@
+ 					function = "mii";
+ 				};
+ 
++				sdio_pins: sdio-pins {
++					groups = "sdio_sb";
++					function = "sdio";
++				};
++
+ 			};
+ 
+ 			eth0: ethernet@30000 {

+ 49 - 0
target/linux/mvebu/patches-4.14/514-arm64-dts-marvell-armada-37xx-Enable-emmc-on-espress.patch

@@ -0,0 +1,49 @@
+From 43ebc7c1b3ed8198b9acf3019eca16e722f7331c Mon Sep 17 00:00:00 2001
+From: Ding Tao <miyatsu@qq.com>
+Date: Fri, 26 Oct 2018 11:50:28 +0000
+Subject: [PATCH] arm64: dts: marvell: armada-37xx: Enable emmc on espressobin
+
+The ESPRESSObin board has a emmc interface available on U11: declare it
+and let the bootloader enable it if the emmc is present.
+
+[gregory.clement@bootlin.com: disable the emmc by default]
+Signed-off-by: Ding Tao <miyatsu@qq.com>
+Signed-off-by: Gregory CLEMENT <gregory.clement@bootlin.com>
+---
+ .../dts/marvell/armada-3720-espressobin.dts   | 22 +++++++++++++++++++
+ 1 file changed, 22 insertions(+)
+
+--- a/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts
++++ b/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts
+@@ -93,9 +93,31 @@
+ 	cd-gpios = <&gpionb 3 GPIO_ACTIVE_LOW>;
+ 	marvell,pad-type = "sd";
+ 	vqmmc-supply = <&vcc_sd_reg1>;
++
++	pinctrl-names = "default";
++	pinctrl-0 = <&sdio_pins>;
+ 	status = "okay";
+ };
+ 
++/* U11 */
++&sdhci0 {
++	non-removable;
++	bus-width = <8>;
++	mmc-ddr-1_8v;
++	mmc-hs400-1_8v;
++	marvell,xenon-emmc;
++	marvell,xenon-tun-count = <9>;
++	marvell,pad-type = "fixed-1-8v";
++
++	pinctrl-names = "default";
++	pinctrl-0 = <&mmc_pins>;
++/*
++ * This eMMC is not populated on all boards, so disable it by
++ * default and let the bootloader enable it, if it is present
++ */
++	status = "disabled";
++};
++
+ &spi0 {
+ 	status = "okay";
+ 

+ 20 - 0
target/linux/mvebu/patches-4.14/520-arm64-dts-marvell-armada37xx-Add-eth0-alias.patch

@@ -0,0 +1,20 @@
+From be893f672e340b56ca60f2f6c32fdd713a5852f5 Mon Sep 17 00:00:00 2001
+From: Kevin Mihelich <kevin@archlinuxarm.org>
+Date: Tue, 4 Jul 2017 19:25:28 -0600
+Subject: arm64: dts: marvell: armada37xx: Add eth0 alias
+
+Signed-off-by: Kevin Mihelich <kevin@archlinuxarm.org>
+---
+ arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
++++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
+@@ -54,6 +54,7 @@
+ 	#size-cells = <2>;
+ 
+ 	aliases {
++		ethernet0 = &eth0;
+ 		serial0 = &uart0;
+ 	};
+ 

+ 58 - 0
target/linux/mvebu/patches-4.14/521-arm64-dts-armada-3720-espressobin-correct-spi-node.patch

@@ -0,0 +1,58 @@
+From 3217cdfe8a3eae76fafbebbe407be5985a7fd4c2 Mon Sep 17 00:00:00 2001
+From: Tomasz Maciej Nowak <tmn505@gmail.com>
+Date: Mon, 31 Dec 2018 14:18:50 +0100
+Subject: [PATCH] arm64: dts: armada-3720-espressobin: correct spi node
+
+The manufacturer of this board, ships it with various SPI NOR chips and
+increments U-Boot bootloader version along the time. There is no way to
+tell which is placed on the board since no revision bump takes place.
+This creates two issues.
+
+The first, cosmetic. Since the SPI chip may differ, there's message on
+boot stating that kernel expected w25q32dw and found different one. To
+correct this, remove optional device-specific compatible string. Being
+here lets replace bogus "spi-flash" string with proper one.
+
+The second is linked to partitions layout, it changed after commit [1]
+in Marvells downstream U-Boot fork, shifting environment location to the
+end of boot device. Since the new boards can have U-Boot with this
+change it can lead to improper results writing or reading from these
+partitions. We can't tell if users will update bootloader to recent
+version, so let's drop current layout.
+
+1. https://github.com/MarvellEmbeddedProcessors/u-boot-marvell/commit/81e7251252aefe1a6b829ed05f3586320cb45372
+
+Signed-off-by: Tomasz Maciej Nowak <tmn505@gmail.com>
+---
+ .../dts/marvell/armada-3720-espressobin.dts    | 18 +-----------------
+ 1 file changed, 1 insertion(+), 17 deletions(-)
+
+--- a/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts
++++ b/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts
+@@ -123,25 +123,9 @@
+ 
+ 	flash@0 {
+ 		reg = <0>;
+-		compatible = "winbond,w25q32dw", "jedec,spi-flash";
++		compatible = "jedec,spi-nor";
+ 		spi-max-frequency = <104000000>;
+ 		m25p,fast-read;
+-
+-		partitions {
+-			compatible = "fixed-partitions";
+-			#address-cells = <1>;
+-			#size-cells = <1>;
+-
+-			partition@0 {
+-				label = "uboot";
+-				reg = <0 0x180000>;
+-			};
+-
+-			partition@180000 {
+-				label = "ubootenv";
+-				reg = <0x180000 0x10000>;
+-			};
+-		};
+ 	};
+ };
+ 

+ 26 - 0
target/linux/mvebu/patches-4.14/522-arm64-dts-marvell-armada-3720-espressobin-add-ports-.patch

@@ -0,0 +1,26 @@
+From 6ea9a1ee9367fb35acff1c08a0dc4213ff4687a0 Mon Sep 17 00:00:00 2001
+From: Tomasz Maciej Nowak <tmn505@gmail.com>
+Date: Tue, 9 Apr 2019 15:53:42 +0200
+Subject: [PATCH] arm64: dts: marvell: armada-3720-espressobin: add ports
+ phandle
+
+Instead of referencing the whole mdio node, add ports phandle to adjust
+port labels in dts for different hardware iterations of ESPRESSObin
+boards.
+
+Signed-off-by: Tomasz Maciej Nowak <tmn505@gmail.com>
+---
+ arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts
++++ b/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts
+@@ -153,7 +153,7 @@
+ 
+ 		dsa,member = <0 0>;
+ 
+-		ports {
++		ports: ports {
+ 			#address-cells = <1>;
+ 			#size-cells = <0>;
+ 

+ 138 - 0
target/linux/mvebu/patches-4.14/524-PCI-aardvark-set-host-and-device-to-the-same-MAX-payload-size.patch

@@ -0,0 +1,138 @@
+From patchwork Thu Sep 28 12:58:34 2017
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v2,
+ 3/7] PCI: aardvark: set host and device to the same MAX payload size
+X-Patchwork-Submitter: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+X-Patchwork-Id: 819587
+Message-Id: <20170928125838.11887-4-thomas.petazzoni@free-electrons.com>
+To: Bjorn Helgaas <bhelgaas@google.com>, linux-pci@vger.kernel.org
+Cc: Jason Cooper <jason@lakedaemon.net>, Andrew Lunn <andrew@lunn.ch>,
+ Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>, Gregory Clement
+ <gregory.clement@free-electrons.com>, 
+ Nadav Haklai <nadavh@marvell.com>, Hanna Hawa <hannah@marvell.com>,
+ Yehuda Yitschak <yehuday@marvell.com>,
+ linux-arm-kernel@lists.infradead.org, Antoine Tenart
+ <antoine.tenart@free-electrons.com>, =?utf-8?q?Miqu=C3=A8l_Raynal?=
+ <miquel.raynal@free-electrons.com>, Victor Gu <xigu@marvell.com>,
+ Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Thu, 28 Sep 2017 14:58:34 +0200
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+List-Id: <linux-pci.vger.kernel.org>
+
+From: Victor Gu <xigu@marvell.com>
+
+Since the Aardvark does not implement a PCIe root bus, the Linux PCIe
+subsystem will not align the MAX payload size between the host and the
+device. This patch ensures that the host and device have the same MAX
+payload size, fixing a number of problems with various PCIe devices.
+
+This is part of fixing bug
+https://bugzilla.kernel.org/show_bug.cgi?id=196339, this commit was
+reported as the user to be important to get a Intel 7260 mini-PCIe
+WiFi card working.
+
+Fixes: Fixes: 8c39d710363c1 ("PCI: aardvark: Add Aardvark PCI host controller driver")
+Signed-off-by: Victor Gu <xigu@marvell.com>
+Reviewed-by: Evan Wang <xswang@marvell.com>
+Reviewed-by: Nadav Haklai <nadavh@marvell.com>
+[Thomas: tweak commit log.]
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ drivers/pci/host/pci-aardvark.c | 60 ++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 59 insertions(+), 1 deletion(-)
+
+--- a/drivers/pci/host/pci-aardvark.c
++++ b/drivers/pci/host/pci-aardvark.c
+@@ -30,9 +30,11 @@
+ #define PCIE_CORE_DEV_CTRL_STATS_REG				0xc8
+ #define     PCIE_CORE_DEV_CTRL_STATS_RELAX_ORDER_DISABLE	(0 << 4)
+ #define     PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ_SHIFT	5
++#define     PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ		0x2
+ #define     PCIE_CORE_DEV_CTRL_STATS_SNOOP_DISABLE		(0 << 11)
+ #define     PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SIZE_SHIFT	12
+ #define     PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SZ		0x2
++#define     PCIE_CORE_MPS_UNIT_BYTE				128
+ #define PCIE_CORE_LINK_CTRL_STAT_REG				0xd0
+ #define     PCIE_CORE_LINK_L0S_ENTRY				BIT(0)
+ #define     PCIE_CORE_LINK_TRAINING				BIT(5)
+@@ -297,7 +299,8 @@ static void advk_pcie_setup_hw(struct ad
+ 
+ 	/* Set PCIe Device Control and Status 1 PF0 register */
+ 	reg = PCIE_CORE_DEV_CTRL_STATS_RELAX_ORDER_DISABLE |
+-		(7 << PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ_SHIFT) |
++		(PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ <<
++		 PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ_SHIFT) |
+ 		PCIE_CORE_DEV_CTRL_STATS_SNOOP_DISABLE |
+ 		(PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SZ <<
+ 		 PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SIZE_SHIFT);
+@@ -886,6 +889,58 @@ out_release_res:
+ 	return err;
+ }
+ 
++static int advk_pcie_find_smpss(struct pci_dev *dev, void *data)
++{
++	u8 *smpss = data;
++
++	if (!dev)
++		return 0;
++
++	if (!pci_is_pcie(dev))
++		return 0;
++
++	if (*smpss > dev->pcie_mpss)
++		*smpss = dev->pcie_mpss;
++
++	return 0;
++}
++
++static int advk_pcie_bus_configure_mps(struct pci_dev *dev, void *data)
++{
++	int mps;
++
++	if (!dev)
++		return 0;
++
++	if (!pci_is_pcie(dev))
++		return 0;
++
++	mps = PCIE_CORE_MPS_UNIT_BYTE << *(u8 *)data;
++	pcie_set_mps(dev, mps);
++
++	return 0;
++}
++
++static void advk_pcie_configure_mps(struct pci_bus *bus, struct advk_pcie *pcie)
++{
++	u8 smpss = PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ;
++	u32 reg;
++
++	/* Find the minimal supported MAX payload size */
++	advk_pcie_find_smpss(bus->self, &smpss);
++	pci_walk_bus(bus, advk_pcie_find_smpss, &smpss);
++
++	/* Configure RC MAX payload size */
++	reg = advk_readl(pcie, PCIE_CORE_DEV_CTRL_STATS_REG);
++	reg &= ~PCI_EXP_DEVCTL_PAYLOAD;
++	reg |= smpss << PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ_SHIFT;
++	advk_writel(pcie, reg, PCIE_CORE_DEV_CTRL_STATS_REG);
++
++	/* Configure device MAX payload size */
++	advk_pcie_bus_configure_mps(bus->self, &smpss);
++	pci_walk_bus(bus, advk_pcie_bus_configure_mps, &smpss);
++}
++
+ static int advk_pcie_probe(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+@@ -960,6 +1015,9 @@ static int advk_pcie_probe(struct platfo
+ 	list_for_each_entry(child, &bus->children, node)
+ 		pcie_bus_configure_settings(child);
+ 
++	/* Configure the MAX pay load size */
++	advk_pcie_configure_mps(bus, pcie);
++
+ 	pci_bus_add_devices(bus);
+ 	return 0;
+ }

+ 55 - 0
target/linux/mvebu/patches-4.14/526-PCI-aardvark-disable-LOS-state-by-default.patch

@@ -0,0 +1,55 @@
+From patchwork Thu Sep 28 12:58:36 2017
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v2,5/7] PCI: aardvark: disable LOS state by default
+X-Patchwork-Submitter: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+X-Patchwork-Id: 819590
+Message-Id: <20170928125838.11887-6-thomas.petazzoni@free-electrons.com>
+To: Bjorn Helgaas <bhelgaas@google.com>, linux-pci@vger.kernel.org
+Cc: Jason Cooper <jason@lakedaemon.net>, Andrew Lunn <andrew@lunn.ch>,
+ Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>, Gregory Clement
+ <gregory.clement@free-electrons.com>, 
+ Nadav Haklai <nadavh@marvell.com>, Hanna Hawa <hannah@marvell.com>,
+ Yehuda Yitschak <yehuday@marvell.com>,
+ linux-arm-kernel@lists.infradead.org, Antoine Tenart
+ <antoine.tenart@free-electrons.com>, =?utf-8?q?Miqu=C3=A8l_Raynal?=
+ <miquel.raynal@free-electrons.com>, Victor Gu <xigu@marvell.com>,
+ Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Thu, 28 Sep 2017 14:58:36 +0200
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+List-Id: <linux-pci.vger.kernel.org>
+
+From: Victor Gu <xigu@marvell.com>
+
+Some PCIe devices do not support LOS, and will cause timeouts if the
+root complex forces the LOS state. This patch disables the LOS state
+by default.
+
+This is part of fixing bug
+https://bugzilla.kernel.org/show_bug.cgi?id=196339, this commit was
+reported as the user to be important to get a Intel 7260 mini-PCIe
+WiFi card working.
+
+Fixes: 8c39d710363c1 ("PCI: aardvark: Add Aardvark PCI host controller driver")
+Signed-off-by: Victor Gu <xigu@marvell.com>
+Reviewed-by: Evan Wang <xswang@marvell.com>
+Reviewed-by: Nadav Haklai <nadavh@marvell.com>
+[Thomas: tweak commit log.]
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ drivers/pci/host/pci-aardvark.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/pci/host/pci-aardvark.c
++++ b/drivers/pci/host/pci-aardvark.c
+@@ -368,8 +368,7 @@ static void advk_pcie_setup_hw(struct ad
+ 
+ 	advk_pcie_wait_for_link(pcie);
+ 
+-	reg = PCIE_CORE_LINK_L0S_ENTRY |
+-		(1 << PCIE_CORE_LINK_WIDTH_SHIFT);
++	reg = (1 << PCIE_CORE_LINK_WIDTH_SHIFT);
+ 	advk_writel(pcie, reg, PCIE_CORE_LINK_CTRL_STAT_REG);
+ 
+ 	reg = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG);

+ 43 - 0
target/linux/mvebu/patches-4.14/527-PCI-aardvark-allow-to-specify-link-capability.patch

@@ -0,0 +1,43 @@
+From f70b629e488cc3f2a325ac35476f4f7ae502c5d0 Mon Sep 17 00:00:00 2001
+From: Tomasz Maciej Nowak <tmn505@gmail.com>
+Date: Thu, 14 Jun 2018 14:24:40 +0200
+Subject: [PATCH 1/2] PCI: aardvark: allow to specify link capability
+
+Use DT of_pci_get_max_link_speed() facility to allow specifying link
+capability. If none or unspecified value is given it falls back to gen2,
+which is default for Armada 3700 SoC.
+
+Signed-off-by: Tomasz Maciej Nowak <tmn505@gmail.com>
+---
+ drivers/pci/host/pci-aardvark.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+--- a/drivers/pci/host/pci-aardvark.c
++++ b/drivers/pci/host/pci-aardvark.c
+@@ -272,6 +272,8 @@ static void advk_pcie_set_ob_win(struct
+ 
+ static void advk_pcie_setup_hw(struct advk_pcie *pcie)
+ {
++	struct device *dev = &pcie->pdev->dev;
++	struct device_node *node = dev->of_node;
+ 	u32 reg;
+ 	int i;
+ 
+@@ -311,10 +313,15 @@ static void advk_pcie_setup_hw(struct ad
+ 		PCIE_CORE_CTRL2_TD_ENABLE;
+ 	advk_writel(pcie, reg, PCIE_CORE_CTRL2_REG);
+ 
+-	/* Set GEN2 */
++	/* Set GEN */
+ 	reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
+ 	reg &= ~PCIE_GEN_SEL_MSK;
+-	reg |= SPEED_GEN_2;
++	if (of_pci_get_max_link_speed(node) == 1)
++		reg |= SPEED_GEN_1;
++	else if (of_pci_get_max_link_speed(node) == 3)
++		reg |= SPEED_GEN_3;
++	else
++		reg |= SPEED_GEN_2;
+ 	advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
+ 
+ 	/* Set lane X1 */

+ 73 - 0
target/linux/mvebu/patches-4.14/528-arm64-dts-armada-3720-espressobin-set-max-link-to-ge.patch

@@ -0,0 +1,73 @@
+From 33f8fdcedb01680427328d710594facef7a0092c Mon Sep 17 00:00:00 2001
+From: Tomasz Maciej Nowak <tmn505@gmail.com>
+Date: Thu, 14 Jun 2018 14:40:26 +0200
+Subject: [PATCH 2/2] arm64: dts: armada-3720-espressobin: set max link to gen1
+
+Since the beginning there's been an issue with initializing the Atheros
+based MiniPCIe wireless cards. Here's an example of kerenel log:
+
+ OF: PCI: host bridge /soc/pcie@d0070000 ranges:
+ OF: PCI:   MEM 0xe8000000..0xe8ffffff -> 0xe8000000
+ OF: PCI:    IO 0xe9000000..0xe900ffff -> 0xe9000000
+ advk-pcie d0070000.pcie: link up
+ advk-pcie d0070000.pcie: PCI host bridge to bus 0000:00
+ pci_bus 0000:00: root bus resource [bus 00-ff]
+ pci_bus 0000:00: root bus resource [mem0xe8000000-0xe8ffffff]
+ pci_bus 0000:00: root bus resource [io  0x0000-0xffff](bus address [0xe9000000-0xe900ffff])
+ pci 0000:00:00.0: BAR 0: assigned [mem0xe8000000-0xe801ffff 64bit]
+ pci 0000:00:00.0: BAR 6: assigned [mem0xe8020000-0xe802ffff pref]
+ [...]
+ advk-pcie d0070000.pcie: Posted PIO Response Status: CA,0xe00 @ 0x3c
+ advk-pcie d0070000.pcie: Posted PIO Response Status: CA,0xe00 @ 0x44
+ advk-pcie d0070000.pcie: Posted PIO Response Status: CA,0xe00 @ 0x4
+ ath9k 0000:00:00.0: enabling device (0000 -> 0002)
+ advk-pcie d0070000.pcie: Posted PIO Response Status: CA,0xe00 @ 0x3c
+ advk-pcie d0070000.pcie: Posted PIO Response Status: CA,0xe00 @ 0xc
+ advk-pcie d0070000.pcie: Posted PIO Response Status: CA,0xe00 @ 0x4
+ advk-pcie d0070000.pcie: Posted PIO Response Status: CA,0xe00 @ 0x40
+ ath9k 0000:00:00.0: request_irq failed
+ advk-pcie d0070000.pcie: Posted PIO Response Status: CA,0xe00 @ 0x4
+ ath9k: probe of 0000:00:00.0 failed with error -22
+
+The same happens for ath5k cards, while ath10k card didn't appear at
+all (not detected):
+
+ OF: PCI: host bridge /soc/pcie@d0070000 ranges:
+ OF: PCI:   MEM 0xe8000000..0xe8ffffff -> 0xe8000000
+ OF: PCI:    IO 0xe9000000..0xe900ffff -> 0xe9000000
+ advk-pcie d0070000.pcie: link never came up
+ advk-pcie d0070000.pcie: PCI host bridge to bus 0000:00
+ pci_bus 0000:00: root bus resource [bus 00-ff]
+ pci_bus 0000:00: root bus resource [mem0xe8000000-0xe8ffffff]
+ pci_bus 0000:00: root bus resource [io  0x0000-0xffff](bus address [0xe9000000-0xe900ffff])
+ advk-pcie d0070000.pcie: config read/write timed out
+
+Following the issue on esppressobin.net forum [1] the workaround seems
+to be limiting the speed of PCIe bridge to 1st generation. This fixed
+the initialisation of all tested Atheros wireless cards.
+The patch in the forum thread swaped registers which would limit speed
+for all Armada 3700 based boards. The approach in this patch, in
+conjunction with "PCI: aardvark: allow to specify link capability" patch
+is less invasive, it only touches the affected board.
+
+For the record, the iwlwifi and mt76 cards were not affected by this
+issue.
+
+1. http://espressobin.net/forums/topic/which-pcie-wlan-cards-are-supported
+
+Signed-off-by: Tomasz Maciej Nowak <tmn505@gmail.com>
+---
+ arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts
++++ b/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts
+@@ -79,6 +79,8 @@
+ /* J9 */
+ &pcie0 {
+ 	status = "okay";
++
++	max-link-speed = <1>;
+ };
+ 
+ /* J6 */

+ 50 - 0
target/linux/mvebu/patches-4.14/529-armada388-clearfog-enable-spi-flash.patch

@@ -0,0 +1,50 @@
+From bb683d7ad9d53442586cfdd0a79a6d6c1fec344e Mon Sep 17 00:00:00 2001
+From: Baruch Siach <baruch@tkos.co.il>
+Date: Thu, 28 Jun 2018 10:13:35 +0300
+Subject: [PATCH] ARM: dts: armada388-clearfog: enable spi flash
+
+The SolidRun Armada 388 SOM has the SPI flash populated by default
+unless the customer explicitly asks otherwise. Enable support by
+default.
+
+Signed-off-by: Baruch Siach <baruch@tkos.co.il>
+Acked-by: Russell King <rmk+kernel@armlinux.org.uk>
+Signed-off-by: Gregory CLEMENT <gregory.clement@bootlin.com>
+---
+ arch/arm/boot/dts/armada-388-clearfog.dts           | 2 +-
+ arch/arm/boot/dts/armada-388-clearfog.dtsi          | 2 +-
+ arch/arm/boot/dts/armada-38x-solidrun-microsom.dtsi | 1 -
+ 3 files changed, 2 insertions(+), 3 deletions(-)
+
+--- a/arch/arm/boot/dts/armada-388-clearfog.dts
++++ b/arch/arm/boot/dts/armada-388-clearfog.dts
+@@ -284,7 +284,7 @@
+ &spi1 {
+ 	/*
+ 	 * Add SPI CS pins for clearfog:
+-	 * CS0: W25Q32 (not populated on uSOM)
++	 * CS0: W25Q32
+ 	 * CS1:
+ 	 * CS2: mikrobus
+ 	 */
+--- a/arch/arm/boot/dts/armada-388-clearfog.dtsi
++++ b/arch/arm/boot/dts/armada-388-clearfog.dtsi
+@@ -265,7 +265,7 @@
+ &spi1 {
+ 	/*
+ 	 * Add SPI CS pins for clearfog:
+-	 * CS0: W25Q32 (not populated on uSOM)
++	 * CS0: W25Q32
+ 	 * CS1: PIC microcontroller (Pro models)
+ 	 * CS2: mikrobus
+ 	 */
+--- a/arch/arm/boot/dts/armada-38x-solidrun-microsom.dtsi
++++ b/arch/arm/boot/dts/armada-38x-solidrun-microsom.dtsi
+@@ -135,7 +135,6 @@
+ 		compatible = "w25q32", "jedec,spi-nor";
+ 		reg = <0>; /* Chip select 0 */
+ 		spi-max-frequency = <3000000>;
+-		status = "disabled";
+ 	};
+ };
+