From 3771176c9ef9b5d231e9019bc0c872dbe3617209 Mon Sep 17 00:00:00 2001
From: Chuanhong Guo <gch981213@gmail.com>
Date: Thu, 13 Dec 2018 15:14:10 +0800
Subject: [PATCH] ath79: add support for linux 4.19
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The following patches are dropped because they are merged upstream:
-0001-tty-serial-drop-QCA-pecific-SoC-symbols.patch
-0006-usb-drop-deprecated-symbols.patch
-0009-MIPS-ath79-add-lots-of-missing-registers.patch
-0010-MIPS-ath79-add-support-for-QCA953x-QCA956x-TP9343.patch
-0014-MIPS-ath79-finetune-cpu-overrides.patch
-0015-MIPS-ath79-enable-uart-during-early_prink.patch
-0016-MIPS-ath79-get-PCIe-controller-out-of-reset.patch

This patch is dropped due to the introduction of spi-mem framework:
-461-spi-ath79-add-fast-flash-read.patch

Thank to Michael Marley @mamarley for his work on this patch:
-910-unaligned_access_hacks.patch

Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
[synchronized kernel config with make kernel_oldconfig]
Signed-off-by: Petr Å tetiar <ynezz@true.cz>
---
 target/linux/ath79/config-4.19                |  229 ++++
 ...2-watchdog-ath79-fix-maximum-timeout.patch |   32 +
 ...ds-add-reset-controller-based-driver.patch |  186 +++
 .../0004-phy-add-ath79-usb-phys.patch         |  320 +++++
 ...005-usb-add-more-OF-quirk-properties.patch |   24 +
 ...9-intc-add-irq-cascade-driver-for-QC.patch |  168 +++
 ...ip-irq-ath79-cpu-drop-OF-init-helper.patch |   23 +
 ...S-ath79-select-the-PINCTRL-subsystem.patch |   24 +
 ...ngs-PCI-qcom-ar7100-adds-binding-doc.patch |   57 +
 .../0018-MIPS-pci-ar71xx-convert-to-OF.patch  |  202 ++++
 ...ngs-PCI-qcom-ar7240-adds-binding-doc.patch |   61 +
 .../0020-MIPS-pci-ar724x-convert-to-OF.patch  |  205 ++++
 ...elpers-for-setting-clocks-and-expose.patch |  243 ++++
 ...legacy-wdt-and-uart-clock-aliases-ou.patch |  114 ++
 ...ass-PLL-base-to-clock-init-functions.patch |  242 ++++
 ...specifying-the-reference-clock-in-DT.patch |  229 ++++
 ...rt-setting-up-clock-via-DT-on-all-So.patch |   77 ++
 ...9-export-switch-MDIO-reference-clock.patch |   59 +
 ...0027-MIPS-ath79-drop-legacy-IRQ-code.patch |  233 ++++
 .../0028-MIPS-ath79-drop-machfiles.patch      | 1048 +++++++++++++++++
 ...0029-MIPS-ath79-drop-legacy-pci-code.patch |  379 ++++++
 ...op-platform-device-registration-code.patch |  933 +++++++++++++++
 .../0031-MIPS-ath79-drop-OF-clock-code.patch  |   95 ++
 .../0032-MIPS-ath79-sanitize-symbols.patch    |   93 ++
 .../0033-spi-ath79-drop-pdata-support.patch   |   73 ++
 .../0034-MIPS-ath79-ath9k-exports.patch       |   27 +
 .../0036-GPIO-add-named-gpio-exports.patch    |  165 +++
 ...-MIPS-ath79-remove-irq-code-from-pci.patch |  139 +++
 .../patches-4.19/0037-missing-registers.patch |   21 +
 .../004-register_gpio_driver_earlier.patch    |   18 +
 ...mtd_fix_cfi_cmdset_0002_status_check.patch |   64 +
 .../404-mtd-cybertan-trx-parser.patch         |   20 +
 .../405-mtd-tp-link-partition-parser.patch    |   25 +
 .../420-net-ar71xx_mac_driver.patch           |   28 +
 .../430-drivers-link-spi-before-mtd.patch     |   12 +
 ...ath79-swizzle-pci-address-for-ar71xx.patch |   98 ++
 ...490-usb-ehci-add-quirks-for-qca-socs.patch |  103 ++
 .../900-mdio_bitbang_ignore_ta_value.patch    |   32 +
 ...-prevent-rescheduling-during-command.patch |   61 +
 .../910-unaligned_access_hacks.patch          |  891 ++++++++++++++
 40 files changed, 7053 insertions(+)
 create mode 100644 target/linux/ath79/config-4.19
 create mode 100644 target/linux/ath79/patches-4.19/0002-watchdog-ath79-fix-maximum-timeout.patch
 create mode 100644 target/linux/ath79/patches-4.19/0003-leds-add-reset-controller-based-driver.patch
 create mode 100644 target/linux/ath79/patches-4.19/0004-phy-add-ath79-usb-phys.patch
 create mode 100644 target/linux/ath79/patches-4.19/0005-usb-add-more-OF-quirk-properties.patch
 create mode 100644 target/linux/ath79/patches-4.19/0007-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch
 create mode 100644 target/linux/ath79/patches-4.19/0008-irqchip-irq-ath79-cpu-drop-OF-init-helper.patch
 create mode 100644 target/linux/ath79/patches-4.19/0011-MIPS-ath79-select-the-PINCTRL-subsystem.patch
 create mode 100644 target/linux/ath79/patches-4.19/0017-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch
 create mode 100644 target/linux/ath79/patches-4.19/0018-MIPS-pci-ar71xx-convert-to-OF.patch
 create mode 100644 target/linux/ath79/patches-4.19/0019-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch
 create mode 100644 target/linux/ath79/patches-4.19/0020-MIPS-pci-ar724x-convert-to-OF.patch
 create mode 100644 target/linux/ath79/patches-4.19/0021-MIPS-ath79-add-helpers-for-setting-clocks-and-expose.patch
 create mode 100644 target/linux/ath79/patches-4.19/0022-MIPS-ath79-move-legacy-wdt-and-uart-clock-aliases-ou.patch
 create mode 100644 target/linux/ath79/patches-4.19/0023-MIPS-ath79-pass-PLL-base-to-clock-init-functions.patch
 create mode 100644 target/linux/ath79/patches-4.19/0024-MIPS-ath79-make-specifying-the-reference-clock-in-DT.patch
 create mode 100644 target/linux/ath79/patches-4.19/0025-MIPS-ath79-support-setting-up-clock-via-DT-on-all-So.patch
 create mode 100644 target/linux/ath79/patches-4.19/0026-MIPS-ath79-export-switch-MDIO-reference-clock.patch
 create mode 100644 target/linux/ath79/patches-4.19/0027-MIPS-ath79-drop-legacy-IRQ-code.patch
 create mode 100644 target/linux/ath79/patches-4.19/0028-MIPS-ath79-drop-machfiles.patch
 create mode 100644 target/linux/ath79/patches-4.19/0029-MIPS-ath79-drop-legacy-pci-code.patch
 create mode 100644 target/linux/ath79/patches-4.19/0030-MIPS-ath79-drop-platform-device-registration-code.patch
 create mode 100644 target/linux/ath79/patches-4.19/0031-MIPS-ath79-drop-OF-clock-code.patch
 create mode 100644 target/linux/ath79/patches-4.19/0032-MIPS-ath79-sanitize-symbols.patch
 create mode 100644 target/linux/ath79/patches-4.19/0033-spi-ath79-drop-pdata-support.patch
 create mode 100644 target/linux/ath79/patches-4.19/0034-MIPS-ath79-ath9k-exports.patch
 create mode 100644 target/linux/ath79/patches-4.19/0036-GPIO-add-named-gpio-exports.patch
 create mode 100644 target/linux/ath79/patches-4.19/0036-MIPS-ath79-remove-irq-code-from-pci.patch
 create mode 100644 target/linux/ath79/patches-4.19/0037-missing-registers.patch
 create mode 100644 target/linux/ath79/patches-4.19/004-register_gpio_driver_earlier.patch
 create mode 100644 target/linux/ath79/patches-4.19/403-mtd_fix_cfi_cmdset_0002_status_check.patch
 create mode 100644 target/linux/ath79/patches-4.19/404-mtd-cybertan-trx-parser.patch
 create mode 100644 target/linux/ath79/patches-4.19/405-mtd-tp-link-partition-parser.patch
 create mode 100644 target/linux/ath79/patches-4.19/420-net-ar71xx_mac_driver.patch
 create mode 100644 target/linux/ath79/patches-4.19/430-drivers-link-spi-before-mtd.patch
 create mode 100644 target/linux/ath79/patches-4.19/470-MIPS-ath79-swizzle-pci-address-for-ar71xx.patch
 create mode 100644 target/linux/ath79/patches-4.19/490-usb-ehci-add-quirks-for-qca-socs.patch
 create mode 100644 target/linux/ath79/patches-4.19/900-mdio_bitbang_ignore_ta_value.patch
 create mode 100644 target/linux/ath79/patches-4.19/901-phy-mdio-bitbang-prevent-rescheduling-during-command.patch
 create mode 100644 target/linux/ath79/patches-4.19/910-unaligned_access_hacks.patch

diff --git a/target/linux/ath79/config-4.19 b/target/linux/ath79/config-4.19
new file mode 100644
index 00000000000..6cdbb968c3b
--- /dev/null
+++ b/target/linux/ath79/config-4.19
@@ -0,0 +1,229 @@
+CONFIG_AG71XX=y
+# CONFIG_AG71XX_DEBUG is not set
+CONFIG_AG71XX_DEBUG_FS=y
+CONFIG_AR8216_PHY=y
+CONFIG_AR8216_PHY_LEDS=y
+CONFIG_ARCH_BINFMT_ELF_STATE=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_ARCH_DISCARD_MEMBLOCK=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_ARCH_HAS_RESET_CONTROLLER=y
+CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_MMAP_RND_BITS_MAX=15
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_ARCH_USE_QUEUED_RWLOCKS=y
+CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_ATH79=y
+CONFIG_ATH79_WDT=y
+CONFIG_CEVT_R4K=y
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_CMDLINE="rootfstype=squashfs,jffs2"
+CONFIG_CMDLINE_BOOL=y
+# CONFIG_CMDLINE_OVERRIDE is not set
+CONFIG_COMMON_CLK=y
+# CONFIG_COMMON_CLK_BOSTON is not set
+CONFIG_CPU_BIG_ENDIAN=y
+CONFIG_CPU_GENERIC_DUMP_TLB=y
+CONFIG_CPU_HAS_PREFETCH=y
+CONFIG_CPU_HAS_RIXI=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPS32_R2=y
+CONFIG_CPU_MIPSR2=y
+CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y
+CONFIG_CPU_R4K_CACHE_TLB=y
+CONFIG_CPU_R4K_FPU=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_CPU_SUPPORTS_MSA=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_WORKQUEUE=y
+CONFIG_CSRC_R4K=y
+CONFIG_DMA_DIRECT_OPS=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NONCOHERENT_CACHE_SYNC=y
+CONFIG_DMA_NONCOHERENT_MMAP=y
+CONFIG_DMA_NONCOHERENT_OPS=y
+CONFIG_DTC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_ETHERNET_PACKET_MANGLE=y
+CONFIG_FIXED_PHY=y
+CONFIG_GENERIC_ATOMIC64=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_CPU_AUTOPROBE=y
+CONFIG_GENERIC_IRQ_CHIP=y
+CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_LIB_ASHLDI3=y
+CONFIG_GENERIC_LIB_ASHRDI3=y
+CONFIG_GENERIC_LIB_CMPDI2=y
+CONFIG_GENERIC_LIB_LSHRDI3=y
+CONFIG_GENERIC_LIB_UCMPDI2=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_PHY=y
+CONFIG_GENERIC_PINCONF=y
+CONFIG_GENERIC_PINCTRL_GROUPS=y
+CONFIG_GENERIC_PINMUX_FUNCTIONS=y
+CONFIG_GENERIC_SCHED_CLOCK=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIOLIB_IRQCHIP=y
+CONFIG_GPIO_74X164=y
+CONFIG_GPIO_ATH79=y
+CONFIG_GPIO_GENERIC=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_HARDWARE_WATCHPOINTS=y
+CONFIG_HAS_DMA=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAVE_ARCH_COMPILER_H=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_CBPF_JIT=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_COPY_THREAD_TLS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+CONFIG_HAVE_DEBUG_STACKOVERFLOW=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_HAVE_DYNAMIC_FTRACE=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_EXIT_ON_IRQ_STACK=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_KVM=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_HAVE_LD_DEAD_CODE_DATA_ELIMINATION=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_HAVE_NET_DSA=y
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_RSEQ=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HW_HAS_PCI=y
+CONFIG_HZ_PERIODIC=y
+CONFIG_IMAGE_CMDLINE_HACK=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_IRQCHIP=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_IRQ_MIPS_CPU=y
+CONFIG_IRQ_WORK=y
+CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_RESET is not set
+CONFIG_LIBFDT=y
+CONFIG_LOCK_DEBUGGING_SUPPORT=y
+CONFIG_MDIO_BITBANG=y
+CONFIG_MDIO_BUS=y
+CONFIG_MDIO_DEVICE=y
+CONFIG_MDIO_GPIO=y
+CONFIG_MEMFD_CREATE=y
+CONFIG_MFD_SYSCON=y
+CONFIG_MIGRATION=y
+CONFIG_MIPS=y
+CONFIG_MIPS_ASID_BITS=8
+CONFIG_MIPS_ASID_SHIFT=0
+CONFIG_MIPS_CBPF_JIT=y
+CONFIG_MIPS_CLOCK_VSYSCALL=y
+# CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND is not set
+# CONFIG_MIPS_CMDLINE_DTB_EXTEND is not set
+# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set
+CONFIG_MIPS_CMDLINE_FROM_DTB=y
+# CONFIG_MIPS_ELF_APPENDED_DTB is not set
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_MIPS_NO_APPENDED_DTB is not set
+CONFIG_MIPS_RAW_APPENDED_DTB=y
+CONFIG_MIPS_SPRAM=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+# CONFIG_MTD_CFI_I2 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_M25P80=y
+# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
+CONFIG_MTD_PARSER_CYBERTAN=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_SPI_NOR=y
+CONFIG_MTD_SPLIT_LZMA_FW=y
+CONFIG_MTD_SPLIT_TPLINK_FW=y
+CONFIG_MTD_SPLIT_UIMAGE_FW=y
+CONFIG_MTD_TPLINK_PARTS=y
+CONFIG_MTD_VIRT_CONCAT=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_NEED_PER_CPU_KM=y
+CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y
+CONFIG_NVMEM=y
+CONFIG_OF=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_GPIO=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_KOBJ=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_NET=y
+CONFIG_PCI_DRIVERS_LEGACY=y
+CONFIG_PERF_USE_VMALLOC=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_PHYLIB=y
+# CONFIG_PHY_AR7100_USB is not set
+# CONFIG_PHY_AR7200_USB is not set
+# CONFIG_PHY_ATH79_USB is not set
+CONFIG_PINCTRL=y
+CONFIG_RATIONAL=y
+CONFIG_REGMAP=y
+CONFIG_REGMAP_MMIO=y
+CONFIG_RESET_ATH79=y
+CONFIG_RESET_CONTROLLER=y
+CONFIG_SERIAL_8250_NR_UARTS=1
+CONFIG_SERIAL_8250_RUNTIME_UARTS=1
+CONFIG_SERIAL_AR933X=y
+CONFIG_SERIAL_AR933X_CONSOLE=y
+CONFIG_SERIAL_AR933X_NR_UARTS=2
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SPI=y
+CONFIG_SPI_ATH79=y
+CONFIG_SPI_BITBANG=y
+CONFIG_SPI_GPIO=y
+CONFIG_SPI_MASTER=y
+CONFIG_SPI_MEM=y
+# CONFIG_SPI_RB4XX is not set
+CONFIG_SRCU=y
+CONFIG_SWCONFIG=y
+CONFIG_SWCONFIG_LEDS=y
+CONFIG_SWPHY=y
+CONFIG_SYSCTL_EXCEPTION_TRACE=y
+CONFIG_SYS_HAS_CPU_MIPS32_R2=y
+CONFIG_SYS_HAS_EARLY_PRINTK=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_SYS_SUPPORTS_MIPS16=y
+CONFIG_SYS_SUPPORTS_ZBOOT=y
+CONFIG_SYS_SUPPORTS_ZBOOT_UART_PROM=y
+CONFIG_TICK_CPU_ACCOUNTING=y
+CONFIG_TINY_SRCU=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USE_OF=y
diff --git a/target/linux/ath79/patches-4.19/0002-watchdog-ath79-fix-maximum-timeout.patch b/target/linux/ath79/patches-4.19/0002-watchdog-ath79-fix-maximum-timeout.patch
new file mode 100644
index 00000000000..36234d8d83e
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/0002-watchdog-ath79-fix-maximum-timeout.patch
@@ -0,0 +1,32 @@
+From 5f5c9858af167f842ee8df053920b98387a71af1 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Mon, 5 Mar 2018 11:41:25 +0100
+Subject: [PATCH 02/27] watchdog: ath79: fix maximum timeout
+
+If the userland tries to set a timeout higher than the max_timeout,
+then we should fallback to max_timeout.
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/watchdog/ath79_wdt.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/drivers/watchdog/ath79_wdt.c
++++ b/drivers/watchdog/ath79_wdt.c
+@@ -115,10 +115,14 @@ static inline void ath79_wdt_disable(voi
+ 
+ static int ath79_wdt_set_timeout(int val)
+ {
+-	if (val < 1 || val > max_timeout)
++	if (val < 1)
+ 		return -EINVAL;
+ 
+-	timeout = val;
++	if (val > max_timeout)
++		timeout = max_timeout;
++	else
++		timeout = val;
++
+ 	ath79_wdt_keepalive();
+ 
+ 	return 0;
diff --git a/target/linux/ath79/patches-4.19/0003-leds-add-reset-controller-based-driver.patch b/target/linux/ath79/patches-4.19/0003-leds-add-reset-controller-based-driver.patch
new file mode 100644
index 00000000000..b909d57fcef
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/0003-leds-add-reset-controller-based-driver.patch
@@ -0,0 +1,186 @@
+From ecbd9c87f073f097d9fe56390353e64e963e866a Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Tue, 6 Mar 2018 10:03:03 +0100
+Subject: [PATCH 03/27] leds: add reset-controller based driver
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/leds/Kconfig      |  11 ++++
+ drivers/leds/Makefile     |   1 +
+ drivers/leds/leds-reset.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 149 insertions(+)
+ create mode 100644 drivers/leds/leds-reset.c
+
+--- a/drivers/leds/Kconfig
++++ b/drivers/leds/Kconfig
+@@ -756,6 +756,17 @@ config LEDS_NIC78BX
+ 	  To compile this driver as a module, choose M here: the module
+ 	  will be called leds-nic78bx.
+ 
++config LEDS_RESET
++	tristate "LED support for reset-controller API"
++	depends on LEDS_CLASS
++	depends on RESET_CONTROLLER
++	help
++	  This option enables support for LEDs connected to pins driven by reset
++	  controllers. Yes, DNI actual built HW like that.
++
++	  To compile this driver as a module, choose M here: the module
++	  will be called leds-reset.
++
+ comment "LED Triggers"
+ source "drivers/leds/trigger/Kconfig"
+ 
+--- /dev/null
++++ b/drivers/leds/leds-reset.c
+@@ -0,0 +1,140 @@
++/*
++ * Copyright (C) 2018 John Crispin <john@phrozen.org>
++ *
++ * This program 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.
++ *
++ */
++#include <linux/err.h>
++#include <linux/reset.h>
++#include <linux/kernel.h>
++#include <linux/leds.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/platform_device.h>
++#include <linux/reset.h>
++
++struct reset_led_data {
++	struct led_classdev cdev;
++	struct reset_control *rst;
++};
++
++static inline struct reset_led_data *
++			cdev_to_reset_led_data(struct led_classdev *led_cdev)
++{
++	return container_of(led_cdev, struct reset_led_data, cdev);
++}
++
++static void reset_led_set(struct led_classdev *led_cdev,
++	enum led_brightness value)
++{
++	struct reset_led_data *led_dat = cdev_to_reset_led_data(led_cdev);
++
++	if (value == LED_OFF)
++		reset_control_assert(led_dat->rst);
++	else
++		reset_control_deassert(led_dat->rst);
++}
++
++struct reset_leds_priv {
++	int num_leds;
++	struct reset_led_data leds[];
++};
++
++static inline int sizeof_reset_leds_priv(int num_leds)
++{
++	return sizeof(struct reset_leds_priv) +
++		(sizeof(struct reset_led_data) * num_leds);
++}
++
++static struct reset_leds_priv *reset_leds_create(struct platform_device *pdev)
++{
++	struct device *dev = &pdev->dev;
++	struct fwnode_handle *child;
++	struct reset_leds_priv *priv;
++	int count, ret;
++
++	count = device_get_child_node_count(dev);
++	if (!count)
++		return ERR_PTR(-ENODEV);
++
++	priv = devm_kzalloc(dev, sizeof_reset_leds_priv(count), GFP_KERNEL);
++	if (!priv)
++		return ERR_PTR(-ENOMEM);
++
++	device_for_each_child_node(dev, child) {
++		struct reset_led_data *led = &priv->leds[priv->num_leds];
++		struct device_node *np = to_of_node(child);
++
++		ret = fwnode_property_read_string(child, "label", &led->cdev.name);
++		if (!led->cdev.name) {
++			fwnode_handle_put(child);
++			return ERR_PTR(-EINVAL);
++		}
++		led->rst = __of_reset_control_get(np, NULL, 0, 0, 0);
++		if (IS_ERR(led->rst))
++			return ERR_PTR(-EINVAL);
++
++		fwnode_property_read_string(child, "linux,default-trigger",
++						&led->cdev.default_trigger);
++
++		led->cdev.brightness_set = reset_led_set;
++		ret = devm_of_led_classdev_register(&pdev->dev, np, &led->cdev);
++		if (ret < 0)
++			return ERR_PTR(ret);
++		led->cdev.dev->of_node = np;
++		priv->num_leds++;
++	}
++
++	return priv;
++}
++
++static const struct of_device_id of_reset_leds_match[] = {
++	{ .compatible = "reset-leds", },
++	{},
++};
++
++MODULE_DEVICE_TABLE(of, of_reset_leds_match);
++
++static int reset_led_probe(struct platform_device *pdev)
++{
++	struct reset_leds_priv *priv;
++
++	priv = reset_leds_create(pdev);
++	if (IS_ERR(priv))
++		return PTR_ERR(priv);
++
++	platform_set_drvdata(pdev, priv);
++
++	return 0;
++}
++
++static void reset_led_shutdown(struct platform_device *pdev)
++{
++	struct reset_leds_priv *priv = platform_get_drvdata(pdev);
++	int i;
++
++	for (i = 0; i < priv->num_leds; i++) {
++		struct reset_led_data *led = &priv->leds[i];
++
++		if (!(led->cdev.flags & LED_RETAIN_AT_SHUTDOWN))
++			reset_led_set(&led->cdev, LED_OFF);
++	}
++}
++
++static struct platform_driver reset_led_driver = {
++	.probe		= reset_led_probe,
++	.shutdown	= reset_led_shutdown,
++	.driver		= {
++		.name	= "leds-reset",
++		.of_match_table = of_reset_leds_match,
++	},
++};
++
++module_platform_driver(reset_led_driver);
++
++MODULE_AUTHOR("John Crispin <john@phrozen.org>");
++MODULE_DESCRIPTION("reset controller LED driver");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:leds-reset");
+--- a/drivers/leds/Makefile
++++ b/drivers/leds/Makefile
+@@ -78,6 +78,7 @@ obj-$(CONFIG_LEDS_MT6323)		+= leds-mt632
+ obj-$(CONFIG_LEDS_LM3692X)		+= leds-lm3692x.o
+ obj-$(CONFIG_LEDS_SC27XX_BLTC)		+= leds-sc27xx-bltc.o
+ obj-$(CONFIG_LEDS_LM3601X)		+= leds-lm3601x.o
++obj-$(CONFIG_LEDS_RESET)		+= leds-reset.o
+ 
+ # LED SPI Drivers
+ obj-$(CONFIG_LEDS_CR0014114)		+= leds-cr0014114.o
diff --git a/target/linux/ath79/patches-4.19/0004-phy-add-ath79-usb-phys.patch b/target/linux/ath79/patches-4.19/0004-phy-add-ath79-usb-phys.patch
new file mode 100644
index 00000000000..6280baf913f
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/0004-phy-add-ath79-usb-phys.patch
@@ -0,0 +1,320 @@
+From 08c9d6ceef01893678a5d2e8a15517c745417f21 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Tue, 6 Mar 2018 10:04:05 +0100
+Subject: [PATCH 04/27] phy: add ath79 usb phys
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/phy/Kconfig          |  16 ++++++
+ drivers/phy/Makefile         |   2 +
+ drivers/phy/phy-ar7100-usb.c | 124 +++++++++++++++++++++++++++++++++++++++++++
+ drivers/phy/phy-ar7200-usb.c | 108 +++++++++++++++++++++++++++++++++++++
+ 4 files changed, 250 insertions(+)
+ create mode 100644 drivers/phy/phy-ar7100-usb.c
+ create mode 100644 drivers/phy/phy-ar7200-usb.c
+
+--- a/drivers/phy/Kconfig
++++ b/drivers/phy/Kconfig
+@@ -15,6 +15,22 @@ config GENERIC_PHY
+ 	  phy users can obtain reference to the PHY. All the users of this
+ 	  framework should select this config.
+ 
++config PHY_AR7100_USB
++	tristate "Atheros AR7100 USB PHY driver"
++	depends on ATH79 || COMPILE_TEST
++	default y if USB_EHCI_HCD_PLATFORM
++	select PHY_SIMPLE
++	help
++	  Enable this to support the USB PHY on Atheros AR7100 SoCs.
++
++config PHY_AR7200_USB
++	tristate "Atheros AR7200 USB PHY driver"
++	depends on ATH79 || COMPILE_TEST
++	default y if USB_EHCI_HCD_PLATFORM
++	select PHY_SIMPLE
++	help
++	  Enable this to support the USB PHY on Atheros AR7200 SoCs.
++
+ config PHY_LPC18XX_USB_OTG
+ 	tristate "NXP LPC18xx/43xx SoC USB OTG PHY driver"
+ 	depends on OF && (ARCH_LPC18XX || COMPILE_TEST)
+--- a/drivers/phy/Makefile
++++ b/drivers/phy/Makefile
+@@ -4,6 +4,8 @@
+ #
+ 
+ obj-$(CONFIG_GENERIC_PHY)		+= phy-core.o
++obj-$(CONFIG_PHY_AR7100_USB)		+= phy-ar7100-usb.o
++obj-$(CONFIG_PHY_AR7200_USB)		+= phy-ar7200-usb.o
+ obj-$(CONFIG_PHY_LPC18XX_USB_OTG)	+= phy-lpc18xx-usb-otg.o
+ obj-$(CONFIG_PHY_XGENE)			+= phy-xgene.o
+ obj-$(CONFIG_PHY_PISTACHIO_USB)		+= phy-pistachio-usb.o
+--- /dev/null
++++ b/drivers/phy/phy-ar7100-usb.c
+@@ -0,0 +1,140 @@
++/*
++ * Copyright (C) 2018 John Crispin <john@phrozen.org>
++ *
++ * 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.
++ */
++
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/phy/phy.h>
++#include <linux/delay.h>
++#include <linux/reset.h>
++#include <linux/of_gpio.h>
++
++#include <asm/mach-ath79/ath79.h>
++#include <asm/mach-ath79/ar71xx_regs.h>
++
++struct ar7100_usb_phy {
++	struct reset_control	*rst_phy;
++	struct reset_control	*rst_host;
++	struct reset_control	*rst_ohci_dll;
++	void __iomem		*io_base;
++	struct phy		*phy;
++	int			gpio;
++};
++
++static int ar7100_usb_phy_power_off(struct phy *phy)
++{
++	struct ar7100_usb_phy *priv = phy_get_drvdata(phy);
++	int err = 0;
++
++	err |= reset_control_assert(priv->rst_host);
++	err |= reset_control_assert(priv->rst_phy);
++	err |= reset_control_assert(priv->rst_ohci_dll);
++
++	return err;
++}
++
++static int ar7100_usb_phy_power_on(struct phy *phy)
++{
++	struct ar7100_usb_phy *priv = phy_get_drvdata(phy);
++	int err = 0;
++
++	err |= ar7100_usb_phy_power_off(phy);
++	mdelay(100);
++	err |= reset_control_deassert(priv->rst_ohci_dll);
++	err |= reset_control_deassert(priv->rst_phy);
++	err |= reset_control_deassert(priv->rst_host);
++	mdelay(500);
++	iowrite32(0xf0000, priv->io_base + AR71XX_USB_CTRL_REG_CONFIG);
++	iowrite32(0x20c00, priv->io_base + AR71XX_USB_CTRL_REG_FLADJ);
++
++	return err;
++}
++
++static const struct phy_ops ar7100_usb_phy_ops = {
++	.power_on	= ar7100_usb_phy_power_on,
++	.power_off	= ar7100_usb_phy_power_off,
++	.owner		= THIS_MODULE,
++};
++
++static int ar7100_usb_phy_probe(struct platform_device *pdev)
++{
++	struct phy_provider *phy_provider;
++	struct resource *res;
++	struct ar7100_usb_phy *priv;
++
++	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
++	if (!priv)
++		return -ENOMEM;
++
++	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	priv->io_base = devm_ioremap_resource(&pdev->dev, res);
++	if (IS_ERR(priv->io_base))
++		return PTR_ERR(priv->io_base);
++
++	priv->rst_phy = devm_reset_control_get(&pdev->dev, "usb-phy");
++	if (IS_ERR(priv->rst_phy)) {
++		dev_err(&pdev->dev, "phy reset is missing\n");
++		return PTR_ERR(priv->rst_phy);
++	}
++
++	priv->rst_host = devm_reset_control_get(&pdev->dev, "usb-host");
++	if (IS_ERR(priv->rst_host)) {
++		dev_err(&pdev->dev, "host reset is missing\n");
++		return PTR_ERR(priv->rst_host);
++	}
++
++	priv->rst_ohci_dll = devm_reset_control_get(&pdev->dev, "usb-ohci-dll");
++	if (IS_ERR(priv->rst_ohci_dll)) {
++		dev_err(&pdev->dev, "ohci-dll reset is missing\n");
++		return PTR_ERR(priv->rst_host);
++	}
++
++	priv->phy = devm_phy_create(&pdev->dev, NULL, &ar7100_usb_phy_ops);
++	if (IS_ERR(priv->phy)) {
++		dev_err(&pdev->dev, "failed to create PHY\n");
++		return PTR_ERR(priv->phy);
++	}
++
++	priv->gpio = of_get_gpio(pdev->dev.of_node, 0);
++	if (priv->gpio >= 0) {
++		int ret = devm_gpio_request(&pdev->dev, priv->gpio, dev_name(&pdev->dev));
++
++		if (ret) {
++			dev_err(&pdev->dev, "failed to request gpio\n");
++			return ret;
++		}
++		gpio_export_with_name(priv->gpio, 0, dev_name(&pdev->dev));
++		gpio_set_value(priv->gpio, 1);
++	}
++
++	phy_set_drvdata(priv->phy, priv);
++
++	phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
++
++
++	return PTR_ERR_OR_ZERO(phy_provider);
++}
++
++static const struct of_device_id ar7100_usb_phy_of_match[] = {
++	{ .compatible = "qca,ar7100-usb-phy" },
++	{}
++};
++MODULE_DEVICE_TABLE(of, ar7100_usb_phy_of_match);
++
++static struct platform_driver ar7100_usb_phy_driver = {
++	.probe	= ar7100_usb_phy_probe,
++	.driver = {
++		.of_match_table	= ar7100_usb_phy_of_match,
++		.name		= "ar7100-usb-phy",
++	}
++};
++module_platform_driver(ar7100_usb_phy_driver);
++
++MODULE_DESCRIPTION("ATH79 USB PHY driver");
++MODULE_AUTHOR("Alban Bedel <albeu@free.fr>");
++MODULE_LICENSE("GPL");
+--- /dev/null
++++ b/drivers/phy/phy-ar7200-usb.c
+@@ -0,0 +1,123 @@
++/*
++ * Copyright (C) 2015 Alban Bedel <albeu@free.fr>
++ *
++ * 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.
++ */
++
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/phy/phy.h>
++#include <linux/reset.h>
++#include <linux/of_gpio.h>
++
++struct ar7200_usb_phy {
++	struct reset_control	*rst_phy;
++	struct reset_control	*suspend_override;
++	struct phy		*phy;
++	int			gpio;
++};
++
++static int ar7200_usb_phy_power_on(struct phy *phy)
++{
++	struct ar7200_usb_phy *priv = phy_get_drvdata(phy);
++	int err = 0;
++
++	if (priv->rst_phy)
++		err = reset_control_deassert(priv->rst_phy);
++	if (!err && priv->suspend_override)
++		err = reset_control_assert(priv->suspend_override);
++	if (err && priv->rst_phy)
++		err = reset_control_assert(priv->rst_phy);
++
++	return err;
++}
++
++static int ar7200_usb_phy_power_off(struct phy *phy)
++{
++	struct ar7200_usb_phy *priv = phy_get_drvdata(phy);
++	int err = 0;
++
++	if (priv->suspend_override)
++		err = reset_control_deassert(priv->suspend_override);
++	if (priv->rst_phy)
++		err |= reset_control_assert(priv->rst_phy);
++
++	return err;
++}
++
++static const struct phy_ops ar7200_usb_phy_ops = {
++	.power_on	= ar7200_usb_phy_power_on,
++	.power_off	= ar7200_usb_phy_power_off,
++	.owner		= THIS_MODULE,
++};
++
++static int ar7200_usb_phy_probe(struct platform_device *pdev)
++{
++	struct phy_provider *phy_provider;
++	struct ar7200_usb_phy *priv;
++
++	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
++	if (!priv)
++		return -ENOMEM;
++
++	priv->rst_phy = devm_reset_control_get(&pdev->dev, "usb-phy");
++	if (IS_ERR(priv->rst_phy)) {
++		dev_err(&pdev->dev, "phy reset is missing\n");
++		return PTR_ERR(priv->rst_phy);
++	}
++
++	priv->suspend_override = devm_reset_control_get_optional(
++		&pdev->dev, "usb-suspend-override");
++	if (IS_ERR(priv->suspend_override)) {
++		if (PTR_ERR(priv->suspend_override) == -ENOENT)
++			priv->suspend_override = NULL;
++		else
++			return PTR_ERR(priv->suspend_override);
++	}
++
++	priv->phy = devm_phy_create(&pdev->dev, NULL, &ar7200_usb_phy_ops);
++	if (IS_ERR(priv->phy)) {
++		dev_err(&pdev->dev, "failed to create PHY\n");
++		return PTR_ERR(priv->phy);
++	}
++
++	priv->gpio = of_get_gpio(pdev->dev.of_node, 0);
++	if (priv->gpio >= 0) {
++		int ret = devm_gpio_request(&pdev->dev, priv->gpio, dev_name(&pdev->dev));
++
++		if (ret) {
++			dev_err(&pdev->dev, "failed to request gpio\n");
++			return ret;
++		}
++		gpio_export_with_name(priv->gpio, 0, dev_name(&pdev->dev));
++		gpio_set_value(priv->gpio, 1);
++	}
++
++	phy_set_drvdata(priv->phy, priv);
++
++	phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
++
++	return PTR_ERR_OR_ZERO(phy_provider);
++}
++
++static const struct of_device_id ar7200_usb_phy_of_match[] = {
++	{ .compatible = "qca,ar7200-usb-phy" },
++	{}
++};
++MODULE_DEVICE_TABLE(of, ar7200_usb_phy_of_match);
++
++static struct platform_driver ar7200_usb_phy_driver = {
++	.probe	= ar7200_usb_phy_probe,
++	.driver = {
++		.of_match_table	= ar7200_usb_phy_of_match,
++		.name		= "ar7200-usb-phy",
++	}
++};
++module_platform_driver(ar7200_usb_phy_driver);
++
++MODULE_DESCRIPTION("ATH79 USB PHY driver");
++MODULE_AUTHOR("Alban Bedel <albeu@free.fr>");
++MODULE_LICENSE("GPL");
diff --git a/target/linux/ath79/patches-4.19/0005-usb-add-more-OF-quirk-properties.patch b/target/linux/ath79/patches-4.19/0005-usb-add-more-OF-quirk-properties.patch
new file mode 100644
index 00000000000..52d77c805cf
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/0005-usb-add-more-OF-quirk-properties.patch
@@ -0,0 +1,24 @@
+From 2201818e5bd33f389beceb3943fdfcf5a698fc5b Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Tue, 6 Mar 2018 10:01:43 +0100
+Subject: [PATCH 05/27] usb: add more OF/quirk properties
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/usb/host/ehci-platform.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/usb/host/ehci-platform.c
++++ b/drivers/usb/host/ehci-platform.c
+@@ -161,6 +161,11 @@ static int ehci_platform_probe(struct pl
+ 	ehci = hcd_to_ehci(hcd);
+ 
+ 	if (pdata == &ehci_platform_defaults && dev->dev.of_node) {
++		of_property_read_u32(dev->dev.of_node, "caps-offset", &pdata->caps_offset);
++
++		if (of_property_read_bool(dev->dev.of_node, "has-synopsys-hc-bug"))
++			pdata->has_synopsys_hc_bug = 1;
++
+ 		if (of_property_read_bool(dev->dev.of_node, "big-endian-regs"))
+ 			ehci->big_endian_mmio = 1;
+ 
diff --git a/target/linux/ath79/patches-4.19/0007-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch b/target/linux/ath79/patches-4.19/0007-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch
new file mode 100644
index 00000000000..bd26107af52
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/0007-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch
@@ -0,0 +1,168 @@
+From f3eacff2310a60348a755c50a8da6fc251fc8587 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Tue, 6 Mar 2018 09:55:13 +0100
+Subject: [PATCH 07/33] irqchip/irq-ath79-intc: add irq cascade driver for
+ QCA9556 SoCs
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/irqchip/Makefile         |   1 +
+ drivers/irqchip/irq-ath79-intc.c | 142 +++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 143 insertions(+)
+ create mode 100644 drivers/irqchip/irq-ath79-intc.c
+
+--- a/drivers/irqchip/Makefile
++++ b/drivers/irqchip/Makefile
+@@ -3,6 +3,7 @@ obj-$(CONFIG_IRQCHIP)			+= irqchip.o
+ 
+ obj-$(CONFIG_ALPINE_MSI)		+= irq-alpine-msi.o
+ obj-$(CONFIG_ATH79)			+= irq-ath79-cpu.o
++obj-$(CONFIG_ATH79)			+= irq-ath79-intc.o
+ obj-$(CONFIG_ATH79)			+= irq-ath79-misc.o
+ obj-$(CONFIG_ARCH_BCM2835)		+= irq-bcm2835.o
+ obj-$(CONFIG_ARCH_BCM2835)		+= irq-bcm2836.o
+--- /dev/null
++++ b/drivers/irqchip/irq-ath79-intc.c
+@@ -0,0 +1,142 @@
++/*
++ *  Atheros AR71xx/AR724x/AR913x specific interrupt handling
++ *
++ *  Copyright (C) 2018 John Crispin <john@phrozen.org>
++ *
++ *  This program 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.
++ */
++
++#include <linux/interrupt.h>
++#include <linux/irqchip.h>
++#include <linux/of.h>
++#include <linux/of_irq.h>
++#include <linux/irqdomain.h>
++
++#include <asm/irq_cpu.h>
++#include <asm/mach-ath79/ath79.h>
++#include <asm/mach-ath79/ar71xx_regs.h>
++
++#define ATH79_MAX_INTC_CASCADE	3
++
++struct ath79_intc {
++	struct irq_chip chip;
++	u32 irq;
++	u32 pending_mask;
++	u32 int_status;
++	u32 irq_mask[ATH79_MAX_INTC_CASCADE];
++	u32 irq_wb_chan[ATH79_MAX_INTC_CASCADE];
++};
++
++static void ath79_intc_irq_handler(struct irq_desc *desc)
++{
++	struct irq_domain *domain = irq_desc_get_handler_data(desc);
++	struct ath79_intc *intc = domain->host_data;
++	u32 pending;
++
++	pending = ath79_reset_rr(intc->int_status);
++	pending &= intc->pending_mask;
++
++	if (pending) {
++		int i;
++
++		for (i = 0; i < domain->hwirq_max; i++)
++			if (pending & intc->irq_mask[i]) {
++				if (intc->irq_wb_chan[i] != 0xffffffff)
++					ath79_ddr_wb_flush(intc->irq_wb_chan[i]);
++				generic_handle_irq(irq_find_mapping(domain, i));
++			}
++	} else {
++		spurious_interrupt();
++	}
++}
++
++static void ath79_intc_irq_enable(struct irq_data *d)
++{
++	struct ath79_intc *intc = d->domain->host_data;
++	enable_irq(intc->irq);
++}
++
++static void ath79_intc_irq_disable(struct irq_data *d)
++{
++	struct ath79_intc *intc = d->domain->host_data;
++	disable_irq(intc->irq);
++}
++
++static int ath79_intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
++{
++	struct ath79_intc *intc = d->host_data;
++
++	irq_set_chip_and_handler(irq, &intc->chip, handle_level_irq);
++
++	return 0;
++}
++
++static const struct irq_domain_ops ath79_irq_domain_ops = {
++	.xlate = irq_domain_xlate_onecell,
++	.map = ath79_intc_map,
++};
++
++static int __init ath79_intc_of_init(
++	struct device_node *node, struct device_node *parent)
++{
++	struct irq_domain *domain;
++	struct ath79_intc *intc;
++	int cnt, cntwb, i, err;
++
++	cnt = of_property_count_u32_elems(node, "qca,pending-bits");
++	if (cnt > ATH79_MAX_INTC_CASCADE)
++		panic("Too many INTC pending bits\n");
++
++	intc = kzalloc(sizeof(*intc), GFP_KERNEL);
++	if (!intc)
++		panic("Failed to allocate INTC memory\n");
++	intc->chip = dummy_irq_chip;
++	intc->chip.name = "INTC";
++	intc->chip.irq_disable = ath79_intc_irq_disable;
++	intc->chip.irq_enable = ath79_intc_irq_enable;
++
++	if (of_property_read_u32(node, "qca,int-status-addr", &intc->int_status) < 0) {
++		panic("Missing address of interrupt status register\n");
++	}
++
++	of_property_read_u32_array(node, "qca,pending-bits", intc->irq_mask, cnt);
++	for (i = 0; i < cnt; i++) {
++		intc->pending_mask |= intc->irq_mask[i];
++		intc->irq_wb_chan[i] = 0xffffffff;
++	}
++
++	cntwb = of_count_phandle_with_args(
++		node, "qca,ddr-wb-channels", "#qca,ddr-wb-channel-cells");
++
++	for (i = 0; i < cntwb; i++) {
++		struct of_phandle_args args;
++		u32 irq = i;
++
++		of_property_read_u32_index(
++			node, "qca,ddr-wb-channel-interrupts", i, &irq);
++		if (irq >= ATH79_MAX_INTC_CASCADE)
++			continue;
++
++		err = of_parse_phandle_with_args(
++			node, "qca,ddr-wb-channels",
++			"#qca,ddr-wb-channel-cells",
++			i, &args);
++		if (err)
++			return err;
++
++		intc->irq_wb_chan[irq] = args.args[0];
++	}
++
++	intc->irq = irq_of_parse_and_map(node, 0);
++	if (!intc->irq)
++		panic("Failed to get INTC IRQ");
++
++	domain = irq_domain_add_linear(node, cnt, &ath79_irq_domain_ops, intc);
++	irq_set_chained_handler_and_data(intc->irq, ath79_intc_irq_handler, domain);
++
++	return 0;
++}
++IRQCHIP_DECLARE(ath79_intc, "qca,ar9340-intc",
++		ath79_intc_of_init);
diff --git a/target/linux/ath79/patches-4.19/0008-irqchip-irq-ath79-cpu-drop-OF-init-helper.patch b/target/linux/ath79/patches-4.19/0008-irqchip-irq-ath79-cpu-drop-OF-init-helper.patch
new file mode 100644
index 00000000000..b5ad731d06d
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/0008-irqchip-irq-ath79-cpu-drop-OF-init-helper.patch
@@ -0,0 +1,23 @@
+From e029f998594f151008ecbfa024e2957edd2a5189 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Tue, 6 Mar 2018 09:58:19 +0100
+Subject: [PATCH 08/33] irqchip/irq-ath79-cpu: drop !OF init helper
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/irqchip/irq-ath79-cpu.c | 7 -------
+ 1 file changed, 7 deletions(-)
+
+--- a/drivers/irqchip/irq-ath79-cpu.c
++++ b/drivers/irqchip/irq-ath79-cpu.c
+@@ -88,10 +88,3 @@ static int __init ar79_cpu_intc_of_init(
+ }
+ IRQCHIP_DECLARE(ar79_cpu_intc, "qca,ar7100-cpu-intc",
+ 		ar79_cpu_intc_of_init);
+-
+-void __init ath79_cpu_irq_init(unsigned irq_wb_chan2, unsigned irq_wb_chan3)
+-{
+-	irq_wb_chan[2] = irq_wb_chan2;
+-	irq_wb_chan[3] = irq_wb_chan3;
+-	mips_cpu_irq_init();
+-}
diff --git a/target/linux/ath79/patches-4.19/0011-MIPS-ath79-select-the-PINCTRL-subsystem.patch b/target/linux/ath79/patches-4.19/0011-MIPS-ath79-select-the-PINCTRL-subsystem.patch
new file mode 100644
index 00000000000..05db5060b13
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/0011-MIPS-ath79-select-the-PINCTRL-subsystem.patch
@@ -0,0 +1,24 @@
+From 0c8856211d26f84277f7fcb0b9595e5c646bc464 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Tue, 6 Mar 2018 10:00:55 +0100
+Subject: [PATCH 11/33] MIPS: ath79: select the PINCTRL subsystem
+
+The pinmux on QCA SoCs is controlled by a single register. The
+"pinctrl-single" driver can be used but requires the target
+to select PINCTRL.
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ arch/mips/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -288,6 +288,7 @@ config BCM63XX
+ 	select SYS_HAS_EARLY_PRINTK
+ 	select SWAP_IO_SPACE
+ 	select GPIOLIB
++	select PINCTRL
+ 	select HAVE_CLK
+ 	select MIPS_L1_CACHE_SHIFT_4
+ 	select CLKDEV_LOOKUP
diff --git a/target/linux/ath79/patches-4.19/0017-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch b/target/linux/ath79/patches-4.19/0017-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch
new file mode 100644
index 00000000000..bf7eb691a5d
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/0017-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch
@@ -0,0 +1,57 @@
+From 4a4f869ec58ed8910b9b2e68d0eee50957e9bb20 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Mon, 25 Jun 2018 15:52:10 +0200
+Subject: [PATCH 17/33] dt-bindings: PCI: qcom,ar7100: adds binding doc
+
+With the driver being converted from platform_data to pure OF, we need to
+also add some docs.
+
+Cc: Rob Herring <robh+dt@kernel.org>
+Cc: devicetree@vger.kernel.org
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ .../devicetree/bindings/pci/qcom,ar7100-pci.txt    | 38 ++++++++++++++++++++++
+ 1 file changed, 38 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/pci/qcom,ar7100-pci.txt
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/pci/qcom,ar7100-pci.txt
+@@ -0,0 +1,38 @@
++* Qualcomm Atheros AR7100 PCI express root complex
++
++Required properties:
++- compatible: should contain "qcom,ar7100-pci" to identify the core.
++- reg: Should contain the register ranges as listed in the reg-names property.
++- reg-names: Definition: Must include the following entries
++	- "cfg_base"	IO Memory
++- #address-cells: set to <3>
++- #size-cells: set to <2>
++- ranges: ranges for the PCI memory and I/O regions
++- interrupt-map-mask and interrupt-map: standard PCI
++	properties to define the mapping of the PCIe interface to interrupt
++	numbers.
++- #interrupt-cells: set to <1>
++- interrupt-controller: define to enable the builtin IRQ cascade.
++
++Optional properties:
++- interrupt-parent: phandle to the MIPS IRQ controller
++
++* Example for ar7100
++	pcie-controller@180c0000 {
++		compatible = "qca,ar7100-pci";
++		#address-cells = <3>;
++		#size-cells = <2>;
++		bus-range = <0x0 0x0>;
++		reg = <0x17010000 0x100>;
++		reg-names = "cfg_base";
++		ranges = <0x2000000 0 0x10000000 0x10000000 0 0x07000000
++			  0x1000000 0 0x00000000 0x00000000 0 0x00000001>;
++		interrupt-parent = <&cpuintc>;
++		interrupts = <2>;
++
++		interrupt-controller;
++		#interrupt-cells = <1>;
++
++		interrupt-map-mask = <0 0 0 1>;
++		interrupt-map = <0 0 0 0 &pcie0 0>;
++	};
diff --git a/target/linux/ath79/patches-4.19/0018-MIPS-pci-ar71xx-convert-to-OF.patch b/target/linux/ath79/patches-4.19/0018-MIPS-pci-ar71xx-convert-to-OF.patch
new file mode 100644
index 00000000000..91796a12f04
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/0018-MIPS-pci-ar71xx-convert-to-OF.patch
@@ -0,0 +1,202 @@
+From 1855ab6b1d27f5b38a648baf57ff6a534afec26d Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Sat, 23 Jun 2018 15:07:23 +0200
+Subject: [PATCH 18/33] MIPS: pci-ar71xx: convert to OF
+
+With the ath79 target getting converted to pure OF, we can drop all the
+platform data code and add the missing OF bits to the driver. We also add
+a irq domain for the PCI/e controllers cascade, thus making it usable from
+dts files.
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ arch/mips/pci/pci-ar71xx.c | 82 +++++++++++++++++++++++-----------------------
+ 1 file changed, 41 insertions(+), 41 deletions(-)
+
+--- a/arch/mips/pci/pci-ar71xx.c
++++ b/arch/mips/pci/pci-ar71xx.c
+@@ -18,8 +18,11 @@
+ #include <linux/pci.h>
+ #include <linux/pci_regs.h>
+ #include <linux/interrupt.h>
++#include <linux/irqchip/chained_irq.h>
+ #include <linux/init.h>
+ #include <linux/platform_device.h>
++#include <linux/of_irq.h>
++#include <linux/of_pci.h>
+ 
+ #include <asm/mach-ath79/ar71xx_regs.h>
+ #include <asm/mach-ath79/ath79.h>
+@@ -49,12 +52,13 @@
+ #define AR71XX_PCI_IRQ_COUNT		5
+ 
+ struct ar71xx_pci_controller {
++	struct device_node *np;
+ 	void __iomem *cfg_base;
+ 	int irq;
+-	int irq_base;
+ 	struct pci_controller pci_ctrl;
+ 	struct resource io_res;
+ 	struct resource mem_res;
++	struct irq_domain *domain;
+ };
+ 
+ /* Byte lane enable bits */
+@@ -228,29 +232,30 @@ static struct pci_ops ar71xx_pci_ops = {
+ 
+ static void ar71xx_pci_irq_handler(struct irq_desc *desc)
+ {
+-	struct ar71xx_pci_controller *apc;
+ 	void __iomem *base = ath79_reset_base;
++	struct irq_chip *chip = irq_desc_get_chip(desc);
++	struct ar71xx_pci_controller *apc = irq_desc_get_handler_data(desc);
+ 	u32 pending;
+ 
+-	apc = irq_desc_get_handler_data(desc);
+-
++	chained_irq_enter(chip, desc);
+ 	pending = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_STATUS) &
+ 		  __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+ 
+ 	if (pending & AR71XX_PCI_INT_DEV0)
+-		generic_handle_irq(apc->irq_base + 0);
++		generic_handle_irq(irq_linear_revmap(apc->domain, 1));
+ 
+ 	else if (pending & AR71XX_PCI_INT_DEV1)
+-		generic_handle_irq(apc->irq_base + 1);
++		generic_handle_irq(irq_linear_revmap(apc->domain, 2));
+ 
+ 	else if (pending & AR71XX_PCI_INT_DEV2)
+-		generic_handle_irq(apc->irq_base + 2);
++		generic_handle_irq(irq_linear_revmap(apc->domain, 3));
+ 
+ 	else if (pending & AR71XX_PCI_INT_CORE)
+-		generic_handle_irq(apc->irq_base + 4);
++		generic_handle_irq(irq_linear_revmap(apc->domain, 4));
+ 
+ 	else
+ 		spurious_interrupt();
++	chained_irq_exit(chip, desc);
+ }
+ 
+ static void ar71xx_pci_irq_unmask(struct irq_data *d)
+@@ -261,7 +266,7 @@ static void ar71xx_pci_irq_unmask(struct
+ 	u32 t;
+ 
+ 	apc = irq_data_get_irq_chip_data(d);
+-	irq = d->irq - apc->irq_base;
++	irq = irq_linear_revmap(apc->domain, d->irq);
+ 
+ 	t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+ 	__raw_writel(t | (1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+@@ -278,7 +283,7 @@ static void ar71xx_pci_irq_mask(struct i
+ 	u32 t;
+ 
+ 	apc = irq_data_get_irq_chip_data(d);
+-	irq = d->irq - apc->irq_base;
++	irq = irq_linear_revmap(apc->domain, d->irq);
+ 
+ 	t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+ 	__raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+@@ -294,24 +299,31 @@ static struct irq_chip ar71xx_pci_irq_ch
+ 	.irq_mask_ack	= ar71xx_pci_irq_mask,
+ };
+ 
++static int ar71xx_pci_irq_map(struct irq_domain *d,
++			      unsigned int irq, irq_hw_number_t hw)
++{
++	struct ar71xx_pci_controller *apc = d->host_data;
++
++	irq_set_chip_and_handler(irq, &ar71xx_pci_irq_chip, handle_level_irq);
++	irq_set_chip_data(irq, apc);
++
++	return 0;
++}
++
++static const struct irq_domain_ops ar71xx_pci_domain_ops = {
++	.xlate = irq_domain_xlate_onecell,
++	.map = ar71xx_pci_irq_map,
++};
++
+ static void ar71xx_pci_irq_init(struct ar71xx_pci_controller *apc)
+ {
+ 	void __iomem *base = ath79_reset_base;
+-	int i;
+ 
+ 	__raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+ 	__raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_STATUS);
+ 
+-	BUILD_BUG_ON(ATH79_PCI_IRQ_COUNT < AR71XX_PCI_IRQ_COUNT);
+-
+-	apc->irq_base = ATH79_PCI_IRQ_BASE;
+-	for (i = apc->irq_base;
+-	     i < apc->irq_base + AR71XX_PCI_IRQ_COUNT; i++) {
+-		irq_set_chip_and_handler(i, &ar71xx_pci_irq_chip,
+-					 handle_level_irq);
+-		irq_set_chip_data(i, apc);
+-	}
+-
++	apc->domain = irq_domain_add_linear(apc->np, AR71XX_PCI_IRQ_COUNT,
++					    &ar71xx_pci_domain_ops, apc);
+ 	irq_set_chained_handler_and_data(apc->irq, ar71xx_pci_irq_handler,
+ 					 apc);
+ }
+@@ -328,6 +340,11 @@ static void ar71xx_pci_reset(void)
+ 	mdelay(100);
+ }
+ 
++static const struct of_device_id ar71xx_pci_ids[] = {
++	{ .compatible = "qca,ar7100-pci" },
++	{},
++};
++
+ static int ar71xx_pci_probe(struct platform_device *pdev)
+ {
+ 	struct ar71xx_pci_controller *apc;
+@@ -348,26 +365,6 @@ static int ar71xx_pci_probe(struct platf
+ 	if (apc->irq < 0)
+ 		return -EINVAL;
+ 
+-	res = platform_get_resource_byname(pdev, IORESOURCE_IO, "io_base");
+-	if (!res)
+-		return -EINVAL;
+-
+-	apc->io_res.parent = res;
+-	apc->io_res.name = "PCI IO space";
+-	apc->io_res.start = res->start;
+-	apc->io_res.end = res->end;
+-	apc->io_res.flags = IORESOURCE_IO;
+-
+-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem_base");
+-	if (!res)
+-		return -EINVAL;
+-
+-	apc->mem_res.parent = res;
+-	apc->mem_res.name = "PCI memory space";
+-	apc->mem_res.start = res->start;
+-	apc->mem_res.end = res->end;
+-	apc->mem_res.flags = IORESOURCE_MEM;
+-
+ 	ar71xx_pci_reset();
+ 
+ 	/* setup COMMAND register */
+@@ -380,9 +377,11 @@ static int ar71xx_pci_probe(struct platf
+ 
+ 	ar71xx_pci_irq_init(apc);
+ 
++	apc->np = pdev->dev.of_node;
+ 	apc->pci_ctrl.pci_ops = &ar71xx_pci_ops;
+ 	apc->pci_ctrl.mem_resource = &apc->mem_res;
+ 	apc->pci_ctrl.io_resource = &apc->io_res;
++	pci_load_of_ranges(&apc->pci_ctrl, pdev->dev.of_node);
+ 
+ 	register_pci_controller(&apc->pci_ctrl);
+ 
+@@ -393,6 +392,7 @@ static struct platform_driver ar71xx_pci
+ 	.probe = ar71xx_pci_probe,
+ 	.driver = {
+ 		.name = "ar71xx-pci",
++		.of_match_table = of_match_ptr(ar71xx_pci_ids),
+ 	},
+ };
+ 
diff --git a/target/linux/ath79/patches-4.19/0019-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch b/target/linux/ath79/patches-4.19/0019-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch
new file mode 100644
index 00000000000..a0af79cb4da
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/0019-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch
@@ -0,0 +1,61 @@
+From ea27764bc3ef2a05decf3ae05edffc289cd0d93c Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Mon, 25 Jun 2018 15:52:02 +0200
+Subject: [PATCH 19/33] dt-bindings: PCI: qcom,ar7240: adds binding doc
+
+With the driver being converted from platform_data to pure OF, we need to
+also add some docs.
+
+Cc: Rob Herring <robh+dt@kernel.org>
+Cc: devicetree@vger.kernel.org
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ .../devicetree/bindings/pci/qcom,ar7240-pci.txt    | 42 ++++++++++++++++++++++
+ 1 file changed, 42 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/pci/qcom,ar7240-pci.txt
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/pci/qcom,ar7240-pci.txt
+@@ -0,0 +1,42 @@
++* Qualcomm Atheros AR724X PCI express root complex
++
++Required properties:
++- compatible: should contain "qcom,ar7240-pci" to identify the core.
++- reg: Should contain the register ranges as listed in the reg-names property.
++- reg-names: Definition: Must include the following entries
++	- "crp_base"	Configuration registers
++	- "ctrl_base"	Control registers
++	- "cfg_base"	IO Memory
++- #address-cells: set to <3>
++- #size-cells: set to <2>
++- ranges: ranges for the PCI memory and I/O regions
++- interrupt-map-mask and interrupt-map: standard PCI
++	properties to define the mapping of the PCIe interface to interrupt
++	numbers.
++- #interrupt-cells: set to <1>
++- interrupt-parent: phandle to the MIPS IRQ controller
++
++Optional properties:
++- interrupt-controller: define to enable the builtin IRQ cascade.
++
++* Example for qca9557
++	pcie-controller@180c0000 {
++		compatible = "qcom,ar7240-pci";
++		#address-cells = <3>;
++		#size-cells = <2>;
++		bus-range = <0x0 0x0>;
++		reg = <0x180c0000 0x1000>,
++		      <0x180f0000 0x100>,
++		      <0x14000000 0x1000>;
++		reg-names = "crp_base", "ctrl_base", "cfg_base";
++		ranges = <0x2000000 0 0x10000000 0x10000000 0 0x04000000
++			  0x1000000 0 0x00000000 0x00000000 0 0x00000001>;
++		interrupt-parent = <&intc2>;
++		interrupts = <1>;
++
++		interrupt-controller;
++		#interrupt-cells = <1>;
++
++		interrupt-map-mask = <0 0 0 1>;
++		interrupt-map = <0 0 0 0 &pcie0 0>;
++	};
diff --git a/target/linux/ath79/patches-4.19/0020-MIPS-pci-ar724x-convert-to-OF.patch b/target/linux/ath79/patches-4.19/0020-MIPS-pci-ar724x-convert-to-OF.patch
new file mode 100644
index 00000000000..936bfd48164
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/0020-MIPS-pci-ar724x-convert-to-OF.patch
@@ -0,0 +1,205 @@
+From a522ee0199d5d3ea114ca2e211f6ac398d3e8e0b Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Sat, 23 Jun 2018 15:07:37 +0200
+Subject: [PATCH 20/33] MIPS: pci-ar724x: convert to OF
+
+With the ath79 target getting converted to pure OF, we can drop all the
+platform data code and add the missing OF bits to the driver. We also add
+a irq domain for the PCI/e controllers cascade, thus making it usable from
+dts files.
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ arch/mips/pci/pci-ar724x.c | 88 ++++++++++++++++++++++------------------------
+ 1 file changed, 42 insertions(+), 46 deletions(-)
+
+--- a/arch/mips/pci/pci-ar724x.c
++++ b/arch/mips/pci/pci-ar724x.c
+@@ -14,8 +14,11 @@
+ #include <linux/init.h>
+ #include <linux/delay.h>
+ #include <linux/platform_device.h>
++#include <linux/irqchip/chained_irq.h>
+ #include <asm/mach-ath79/ath79.h>
+ #include <asm/mach-ath79/ar71xx_regs.h>
++#include <linux/of_irq.h>
++#include <linux/of_pci.h>
+ 
+ #define AR724X_PCI_REG_APP		0x00
+ #define AR724X_PCI_REG_RESET		0x18
+@@ -45,17 +48,20 @@ struct ar724x_pci_controller {
+ 	void __iomem *crp_base;
+ 
+ 	int irq;
+-	int irq_base;
+ 
+ 	bool link_up;
+ 	bool bar0_is_cached;
+ 	u32  bar0_value;
+ 
++	struct device_node *np;
+ 	struct pci_controller pci_controller;
++	struct irq_domain *domain;
+ 	struct resource io_res;
+ 	struct resource mem_res;
+ };
+ 
++static struct irq_chip ar724x_pci_irq_chip;
++
+ static inline bool ar724x_pci_check_link(struct ar724x_pci_controller *apc)
+ {
+ 	u32 reset;
+@@ -231,35 +237,31 @@ static struct pci_ops ar724x_pci_ops = {
+ 
+ static void ar724x_pci_irq_handler(struct irq_desc *desc)
+ {
+-	struct ar724x_pci_controller *apc;
+-	void __iomem *base;
++	struct irq_chip *chip = irq_desc_get_chip(desc);
++	struct ar724x_pci_controller *apc = irq_desc_get_handler_data(desc);
+ 	u32 pending;
+ 
+-	apc = irq_desc_get_handler_data(desc);
+-	base = apc->ctrl_base;
+-
+-	pending = __raw_readl(base + AR724X_PCI_REG_INT_STATUS) &
+-		  __raw_readl(base + AR724X_PCI_REG_INT_MASK);
++	chained_irq_enter(chip, desc);
++	pending = __raw_readl(apc->ctrl_base + AR724X_PCI_REG_INT_STATUS) &
++		  __raw_readl(apc->ctrl_base + AR724X_PCI_REG_INT_MASK);
+ 
+ 	if (pending & AR724X_PCI_INT_DEV0)
+-		generic_handle_irq(apc->irq_base + 0);
+-
++		generic_handle_irq(irq_linear_revmap(apc->domain, 1));
+ 	else
+ 		spurious_interrupt();
++	chained_irq_exit(chip, desc);
+ }
+ 
+ static void ar724x_pci_irq_unmask(struct irq_data *d)
+ {
+ 	struct ar724x_pci_controller *apc;
+ 	void __iomem *base;
+-	int offset;
+ 	u32 t;
+ 
+ 	apc = irq_data_get_irq_chip_data(d);
+ 	base = apc->ctrl_base;
+-	offset = apc->irq_base - d->irq;
+ 
+-	switch (offset) {
++	switch (irq_linear_revmap(apc->domain, d->irq)) {
+ 	case 0:
+ 		t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);
+ 		__raw_writel(t | AR724X_PCI_INT_DEV0,
+@@ -273,14 +275,12 @@ static void ar724x_pci_irq_mask(struct i
+ {
+ 	struct ar724x_pci_controller *apc;
+ 	void __iomem *base;
+-	int offset;
+ 	u32 t;
+ 
+ 	apc = irq_data_get_irq_chip_data(d);
+ 	base = apc->ctrl_base;
+-	offset = apc->irq_base - d->irq;
+ 
+-	switch (offset) {
++	switch (irq_linear_revmap(apc->domain, d->irq)) {
+ 	case 0:
+ 		t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);
+ 		__raw_writel(t & ~AR724X_PCI_INT_DEV0,
+@@ -305,26 +305,34 @@ static struct irq_chip ar724x_pci_irq_ch
+ 	.irq_mask_ack	= ar724x_pci_irq_mask,
+ };
+ 
++static int ar724x_pci_irq_map(struct irq_domain *d,
++			      unsigned int irq, irq_hw_number_t hw)
++{
++	struct ar724x_pci_controller *apc = d->host_data;
++
++	irq_set_chip_and_handler(irq, &ar724x_pci_irq_chip, handle_level_irq);
++	irq_set_chip_data(irq, apc);
++
++	return 0;
++}
++
++static const struct irq_domain_ops ar724x_pci_domain_ops = {
++	.xlate = irq_domain_xlate_onecell,
++	.map = ar724x_pci_irq_map,
++};
++
+ static void ar724x_pci_irq_init(struct ar724x_pci_controller *apc,
+ 				int id)
+ {
+ 	void __iomem *base;
+-	int i;
+ 
+ 	base = apc->ctrl_base;
+ 
+ 	__raw_writel(0, base + AR724X_PCI_REG_INT_MASK);
+ 	__raw_writel(0, base + AR724X_PCI_REG_INT_STATUS);
+ 
+-	apc->irq_base = ATH79_PCI_IRQ_BASE + (id * AR724X_PCI_IRQ_COUNT);
+-
+-	for (i = apc->irq_base;
+-	     i < apc->irq_base + AR724X_PCI_IRQ_COUNT; i++) {
+-		irq_set_chip_and_handler(i, &ar724x_pci_irq_chip,
+-					 handle_level_irq);
+-		irq_set_chip_data(i, apc);
+-	}
+-
++	apc->domain = irq_domain_add_linear(apc->np, 2,
++					    &ar724x_pci_domain_ops, apc);
+ 	irq_set_chained_handler_and_data(apc->irq, ar724x_pci_irq_handler,
+ 					 apc);
+ }
+@@ -394,29 +402,11 @@ static int ar724x_pci_probe(struct platf
+ 	if (apc->irq < 0)
+ 		return -EINVAL;
+ 
+-	res = platform_get_resource_byname(pdev, IORESOURCE_IO, "io_base");
+-	if (!res)
+-		return -EINVAL;
+-
+-	apc->io_res.parent = res;
+-	apc->io_res.name = "PCI IO space";
+-	apc->io_res.start = res->start;
+-	apc->io_res.end = res->end;
+-	apc->io_res.flags = IORESOURCE_IO;
+-
+-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem_base");
+-	if (!res)
+-		return -EINVAL;
+-
+-	apc->mem_res.parent = res;
+-	apc->mem_res.name = "PCI memory space";
+-	apc->mem_res.start = res->start;
+-	apc->mem_res.end = res->end;
+-	apc->mem_res.flags = IORESOURCE_MEM;
+-
++	apc->np = pdev->dev.of_node;
+ 	apc->pci_controller.pci_ops = &ar724x_pci_ops;
+ 	apc->pci_controller.io_resource = &apc->io_res;
+ 	apc->pci_controller.mem_resource = &apc->mem_res;
++	pci_load_of_ranges(&apc->pci_controller, pdev->dev.of_node);
+ 
+ 	/*
+ 	 * Do the full PCIE Root Complex Initialization Sequence if the PCIe
+@@ -438,10 +428,16 @@ static int ar724x_pci_probe(struct platf
+ 	return 0;
+ }
+ 
++static const struct of_device_id ar724x_pci_ids[] = {
++	{ .compatible = "qcom,ar7240-pci" },
++	{},
++};
++
+ static struct platform_driver ar724x_pci_driver = {
+ 	.probe = ar724x_pci_probe,
+ 	.driver = {
+ 		.name = "ar724x-pci",
++		.of_match_table = of_match_ptr(ar724x_pci_ids),
+ 	},
+ };
+ 
diff --git a/target/linux/ath79/patches-4.19/0021-MIPS-ath79-add-helpers-for-setting-clocks-and-expose.patch b/target/linux/ath79/patches-4.19/0021-MIPS-ath79-add-helpers-for-setting-clocks-and-expose.patch
new file mode 100644
index 00000000000..c273140dfc4
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/0021-MIPS-ath79-add-helpers-for-setting-clocks-and-expose.patch
@@ -0,0 +1,243 @@
+From 288a8eb0d41f09fda242e05f8a7bd1f5b3489477 Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@nbd.name>
+Date: Tue, 6 Mar 2018 13:19:26 +0100
+Subject: [PATCH 21/33] MIPS: ath79: add helpers for setting clocks and expose
+ the ref clock
+
+Preparation for transitioning the legacy clock setup code over
+to OF.
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ arch/mips/ath79/clock.c               | 128 ++++++++++++++++++----------------
+ include/dt-bindings/clock/ath79-clk.h |   3 +-
+ 2 files changed, 68 insertions(+), 63 deletions(-)
+
+--- a/arch/mips/ath79/clock.c
++++ b/arch/mips/ath79/clock.c
+@@ -37,20 +37,46 @@ static struct clk_onecell_data clk_data
+ 	.clk_num = ARRAY_SIZE(clks),
+ };
+ 
+-static struct clk *__init ath79_add_sys_clkdev(
+-	const char *id, unsigned long rate)
++static const char * const clk_names[ATH79_CLK_END] = {
++	[ATH79_CLK_CPU] = "cpu",
++	[ATH79_CLK_DDR] = "ddr",
++	[ATH79_CLK_AHB] = "ahb",
++	[ATH79_CLK_REF] = "ref",
++};
++
++static const char * __init ath79_clk_name(int type)
+ {
+-	struct clk *clk;
+-	int err;
++	BUG_ON(type >= ARRAY_SIZE(clk_names) || !clk_names[type]);
++	return clk_names[type];
++}
+ 
+-	clk = clk_register_fixed_rate(NULL, id, NULL, 0, rate);
++static void __init __ath79_set_clk(int type, const char *name, struct clk *clk)
++{
+ 	if (IS_ERR(clk))
+-		panic("failed to allocate %s clock structure", id);
++		panic("failed to allocate %s clock structure", clk_names[type]);
+ 
+-	err = clk_register_clkdev(clk, id, NULL);
+-	if (err)
+-		panic("unable to register %s clock device", id);
++	clks[type] = clk;
++	clk_register_clkdev(clk, name, NULL);
++}
+ 
++static struct clk * __init ath79_set_clk(int type, unsigned long rate)
++{
++	const char *name = ath79_clk_name(type);
++	struct clk *clk;
++
++	clk = clk_register_fixed_rate(NULL, name, NULL, 0, rate);
++	__ath79_set_clk(type, name, clk);
++	return clk;
++}
++
++static struct clk * __init ath79_set_ff_clk(int type, const char *parent,
++					    unsigned int mult, unsigned int div)
++{
++	const char *name = ath79_clk_name(type);
++	struct clk *clk;
++
++	clk = clk_register_fixed_factor(NULL, name, parent, 0, mult, div);
++	__ath79_set_clk(type, name, clk);
+ 	return clk;
+ }
+ 
+@@ -80,27 +106,15 @@ static void __init ar71xx_clocks_init(vo
+ 	div = (((pll >> AR71XX_AHB_DIV_SHIFT) & AR71XX_AHB_DIV_MASK) + 1) * 2;
+ 	ahb_rate = cpu_rate / div;
+ 
+-	ath79_add_sys_clkdev("ref", ref_rate);
+-	clks[ATH79_CLK_CPU] = ath79_add_sys_clkdev("cpu", cpu_rate);
+-	clks[ATH79_CLK_DDR] = ath79_add_sys_clkdev("ddr", ddr_rate);
+-	clks[ATH79_CLK_AHB] = ath79_add_sys_clkdev("ahb", ahb_rate);
++	ath79_set_clk(ATH79_CLK_REF, ref_rate);
++	ath79_set_clk(ATH79_CLK_CPU, cpu_rate);
++	ath79_set_clk(ATH79_CLK_DDR, ddr_rate);
++	ath79_set_clk(ATH79_CLK_AHB, ahb_rate);
+ 
+ 	clk_add_alias("wdt", NULL, "ahb", NULL);
+ 	clk_add_alias("uart", NULL, "ahb", NULL);
+ }
+ 
+-static struct clk * __init ath79_reg_ffclk(const char *name,
+-		const char *parent_name, unsigned int mult, unsigned int div)
+-{
+-	struct clk *clk;
+-
+-	clk = clk_register_fixed_factor(NULL, name, parent_name, 0, mult, div);
+-	if (IS_ERR(clk))
+-		panic("failed to allocate %s clock structure", name);
+-
+-	return clk;
+-}
+-
+ static void __init ar724x_clk_init(struct clk *ref_clk, void __iomem *pll_base)
+ {
+ 	u32 pll;
+@@ -114,24 +128,19 @@ static void __init ar724x_clk_init(struc
+ 	ddr_div = ((pll >> AR724X_DDR_DIV_SHIFT) & AR724X_DDR_DIV_MASK) + 1;
+ 	ahb_div = (((pll >> AR724X_AHB_DIV_SHIFT) & AR724X_AHB_DIV_MASK) + 1) * 2;
+ 
+-	clks[ATH79_CLK_CPU] = ath79_reg_ffclk("cpu", "ref", mult, div);
+-	clks[ATH79_CLK_DDR] = ath79_reg_ffclk("ddr", "ref", mult, div * ddr_div);
+-	clks[ATH79_CLK_AHB] = ath79_reg_ffclk("ahb", "ref", mult, div * ahb_div);
++	ath79_set_ff_clk(ATH79_CLK_CPU, "ref", mult, div);
++	ath79_set_ff_clk(ATH79_CLK_DDR, "ref", mult, div * ddr_div);
++	ath79_set_ff_clk(ATH79_CLK_AHB, "ref", mult, div * ahb_div);
+ }
+ 
+ static void __init ar724x_clocks_init(void)
+ {
+ 	struct clk *ref_clk;
+ 
+-	ref_clk = ath79_add_sys_clkdev("ref", AR724X_BASE_FREQ);
++	ref_clk = ath79_set_clk(ATH79_CLK_REF, AR724X_BASE_FREQ);
+ 
+ 	ar724x_clk_init(ref_clk, ath79_pll_base);
+ 
+-	/* just make happy plat_time_init() from arch/mips/ath79/setup.c */
+-	clk_register_clkdev(clks[ATH79_CLK_CPU], "cpu", NULL);
+-	clk_register_clkdev(clks[ATH79_CLK_DDR], "ddr", NULL);
+-	clk_register_clkdev(clks[ATH79_CLK_AHB], "ahb", NULL);
+-
+ 	clk_add_alias("wdt", NULL, "ahb", NULL);
+ 	clk_add_alias("uart", NULL, "ahb", NULL);
+ }
+@@ -186,12 +195,12 @@ static void __init ar9330_clk_init(struc
+ 		     AR933X_PLL_CLOCK_CTRL_AHB_DIV_MASK) + 1;
+ 	}
+ 
+-	clks[ATH79_CLK_CPU] = ath79_reg_ffclk("cpu", "ref",
+-					ninit_mul, ref_div * out_div * cpu_div);
+-	clks[ATH79_CLK_DDR] = ath79_reg_ffclk("ddr", "ref",
+-					ninit_mul, ref_div * out_div * ddr_div);
+-	clks[ATH79_CLK_AHB] = ath79_reg_ffclk("ahb", "ref",
+-					ninit_mul, ref_div * out_div * ahb_div);
++	ath79_set_ff_clk(ATH79_CLK_CPU, "ref", ninit_mul,
++			 ref_div * out_div * cpu_div);
++	ath79_set_ff_clk(ATH79_CLK_DDR, "ref", ninit_mul,
++			 ref_div * out_div * ddr_div);
++	ath79_set_ff_clk(ATH79_CLK_AHB, "ref", ninit_mul,
++			 ref_div * out_div * ahb_div);
+ }
+ 
+ static void __init ar933x_clocks_init(void)
+@@ -206,15 +215,10 @@ static void __init ar933x_clocks_init(vo
+ 	else
+ 		ref_rate = (25 * 1000 * 1000);
+ 
+-	ref_clk = ath79_add_sys_clkdev("ref", ref_rate);
++	ref_clk = ath79_set_clk(ATH79_CLK_REF, ref_rate);
+ 
+ 	ar9330_clk_init(ref_clk, ath79_pll_base);
+ 
+-	/* just make happy plat_time_init() from arch/mips/ath79/setup.c */
+-	clk_register_clkdev(clks[ATH79_CLK_CPU], "cpu", NULL);
+-	clk_register_clkdev(clks[ATH79_CLK_DDR], "ddr", NULL);
+-	clk_register_clkdev(clks[ATH79_CLK_AHB], "ahb", NULL);
+-
+ 	clk_add_alias("wdt", NULL, "ahb", NULL);
+ 	clk_add_alias("uart", NULL, "ref", NULL);
+ }
+@@ -344,10 +348,10 @@ static void __init ar934x_clocks_init(vo
+ 	else
+ 		ahb_rate = cpu_pll / (postdiv + 1);
+ 
+-	ath79_add_sys_clkdev("ref", ref_rate);
+-	clks[ATH79_CLK_CPU] = ath79_add_sys_clkdev("cpu", cpu_rate);
+-	clks[ATH79_CLK_DDR] = ath79_add_sys_clkdev("ddr", ddr_rate);
+-	clks[ATH79_CLK_AHB] = ath79_add_sys_clkdev("ahb", ahb_rate);
++	ath79_set_clk(ATH79_CLK_REF, ref_rate);
++	ath79_set_clk(ATH79_CLK_CPU, cpu_rate);
++	ath79_set_clk(ATH79_CLK_DDR, ddr_rate);
++	ath79_set_clk(ATH79_CLK_AHB, ahb_rate);
+ 
+ 	clk_add_alias("wdt", NULL, "ref", NULL);
+ 	clk_add_alias("uart", NULL, "ref", NULL);
+@@ -431,10 +435,10 @@ static void __init qca953x_clocks_init(v
+ 	else
+ 		ahb_rate = cpu_pll / (postdiv + 1);
+ 
+-	ath79_add_sys_clkdev("ref", ref_rate);
+-	ath79_add_sys_clkdev("cpu", cpu_rate);
+-	ath79_add_sys_clkdev("ddr", ddr_rate);
+-	ath79_add_sys_clkdev("ahb", ahb_rate);
++	ath79_set_clk(ATH79_CLK_REF, ref_rate);
++	ath79_set_clk(ATH79_CLK_CPU, cpu_rate);
++	ath79_set_clk(ATH79_CLK_DDR, ddr_rate);
++	ath79_set_clk(ATH79_CLK_AHB, ahb_rate);
+ 
+ 	clk_add_alias("wdt", NULL, "ref", NULL);
+ 	clk_add_alias("uart", NULL, "ref", NULL);
+@@ -516,10 +520,10 @@ static void __init qca955x_clocks_init(v
+ 	else
+ 		ahb_rate = cpu_pll / (postdiv + 1);
+ 
+-	ath79_add_sys_clkdev("ref", ref_rate);
+-	clks[ATH79_CLK_CPU] = ath79_add_sys_clkdev("cpu", cpu_rate);
+-	clks[ATH79_CLK_DDR] = ath79_add_sys_clkdev("ddr", ddr_rate);
+-	clks[ATH79_CLK_AHB] = ath79_add_sys_clkdev("ahb", ahb_rate);
++	ath79_set_clk(ATH79_CLK_REF, ref_rate);
++	ath79_set_clk(ATH79_CLK_CPU, cpu_rate);
++	ath79_set_clk(ATH79_CLK_DDR, ddr_rate);
++	ath79_set_clk(ATH79_CLK_AHB, ahb_rate);
+ 
+ 	clk_add_alias("wdt", NULL, "ref", NULL);
+ 	clk_add_alias("uart", NULL, "ref", NULL);
+@@ -620,10 +624,10 @@ static void __init qca956x_clocks_init(v
+ 	else
+ 		ahb_rate = cpu_pll / (postdiv + 1);
+ 
+-	ath79_add_sys_clkdev("ref", ref_rate);
+-	ath79_add_sys_clkdev("cpu", cpu_rate);
+-	ath79_add_sys_clkdev("ddr", ddr_rate);
+-	ath79_add_sys_clkdev("ahb", ahb_rate);
++	ath79_set_clk(ATH79_CLK_REF, ref_rate);
++	ath79_set_clk(ATH79_CLK_CPU, cpu_rate);
++	ath79_set_clk(ATH79_CLK_DDR, ddr_rate);
++	ath79_set_clk(ATH79_CLK_AHB, ahb_rate);
+ 
+ 	clk_add_alias("wdt", NULL, "ref", NULL);
+ 	clk_add_alias("uart", NULL, "ref", NULL);
+--- a/include/dt-bindings/clock/ath79-clk.h
++++ b/include/dt-bindings/clock/ath79-clk.h
+@@ -13,7 +13,8 @@
+ #define ATH79_CLK_CPU		0
+ #define ATH79_CLK_DDR		1
+ #define ATH79_CLK_AHB		2
++#define ATH79_CLK_REF		3
+ 
+-#define ATH79_CLK_END		3
++#define ATH79_CLK_END		4
+ 
+ #endif /* __DT_BINDINGS_ATH79_CLK_H */
diff --git a/target/linux/ath79/patches-4.19/0022-MIPS-ath79-move-legacy-wdt-and-uart-clock-aliases-ou.patch b/target/linux/ath79/patches-4.19/0022-MIPS-ath79-move-legacy-wdt-and-uart-clock-aliases-ou.patch
new file mode 100644
index 00000000000..389edc45a84
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/0022-MIPS-ath79-move-legacy-wdt-and-uart-clock-aliases-ou.patch
@@ -0,0 +1,114 @@
+From 339c191a95e978353c9ba3aafab0261e14de109b Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@nbd.name>
+Date: Tue, 6 Mar 2018 13:22:43 +0100
+Subject: [PATCH 22/33] MIPS: ath79: move legacy "wdt" and "uart" clock aliases
+ out of soc init
+
+Preparation for reusing functions for DT
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ arch/mips/ath79/clock.c | 38 +++++++++++++++++---------------------
+ 1 file changed, 17 insertions(+), 21 deletions(-)
+
+--- a/arch/mips/ath79/clock.c
++++ b/arch/mips/ath79/clock.c
+@@ -110,9 +110,6 @@ static void __init ar71xx_clocks_init(vo
+ 	ath79_set_clk(ATH79_CLK_CPU, cpu_rate);
+ 	ath79_set_clk(ATH79_CLK_DDR, ddr_rate);
+ 	ath79_set_clk(ATH79_CLK_AHB, ahb_rate);
+-
+-	clk_add_alias("wdt", NULL, "ahb", NULL);
+-	clk_add_alias("uart", NULL, "ahb", NULL);
+ }
+ 
+ static void __init ar724x_clk_init(struct clk *ref_clk, void __iomem *pll_base)
+@@ -140,9 +137,6 @@ static void __init ar724x_clocks_init(vo
+ 	ref_clk = ath79_set_clk(ATH79_CLK_REF, AR724X_BASE_FREQ);
+ 
+ 	ar724x_clk_init(ref_clk, ath79_pll_base);
+-
+-	clk_add_alias("wdt", NULL, "ahb", NULL);
+-	clk_add_alias("uart", NULL, "ahb", NULL);
+ }
+ 
+ static void __init ar9330_clk_init(struct clk *ref_clk, void __iomem *pll_base)
+@@ -218,9 +212,6 @@ static void __init ar933x_clocks_init(vo
+ 	ref_clk = ath79_set_clk(ATH79_CLK_REF, ref_rate);
+ 
+ 	ar9330_clk_init(ref_clk, ath79_pll_base);
+-
+-	clk_add_alias("wdt", NULL, "ahb", NULL);
+-	clk_add_alias("uart", NULL, "ref", NULL);
+ }
+ 
+ static u32 __init ar934x_get_pll_freq(u32 ref, u32 ref_div, u32 nint, u32 nfrac,
+@@ -353,9 +344,6 @@ static void __init ar934x_clocks_init(vo
+ 	ath79_set_clk(ATH79_CLK_DDR, ddr_rate);
+ 	ath79_set_clk(ATH79_CLK_AHB, ahb_rate);
+ 
+-	clk_add_alias("wdt", NULL, "ref", NULL);
+-	clk_add_alias("uart", NULL, "ref", NULL);
+-
+ 	iounmap(dpll_base);
+ }
+ 
+@@ -439,9 +427,6 @@ static void __init qca953x_clocks_init(v
+ 	ath79_set_clk(ATH79_CLK_CPU, cpu_rate);
+ 	ath79_set_clk(ATH79_CLK_DDR, ddr_rate);
+ 	ath79_set_clk(ATH79_CLK_AHB, ahb_rate);
+-
+-	clk_add_alias("wdt", NULL, "ref", NULL);
+-	clk_add_alias("uart", NULL, "ref", NULL);
+ }
+ 
+ static void __init qca955x_clocks_init(void)
+@@ -524,9 +509,6 @@ static void __init qca955x_clocks_init(v
+ 	ath79_set_clk(ATH79_CLK_CPU, cpu_rate);
+ 	ath79_set_clk(ATH79_CLK_DDR, ddr_rate);
+ 	ath79_set_clk(ATH79_CLK_AHB, ahb_rate);
+-
+-	clk_add_alias("wdt", NULL, "ref", NULL);
+-	clk_add_alias("uart", NULL, "ref", NULL);
+ }
+ 
+ static void __init qca956x_clocks_init(void)
+@@ -628,13 +610,13 @@ static void __init qca956x_clocks_init(v
+ 	ath79_set_clk(ATH79_CLK_CPU, cpu_rate);
+ 	ath79_set_clk(ATH79_CLK_DDR, ddr_rate);
+ 	ath79_set_clk(ATH79_CLK_AHB, ahb_rate);
+-
+-	clk_add_alias("wdt", NULL, "ref", NULL);
+-	clk_add_alias("uart", NULL, "ref", NULL);
+ }
+ 
+ void __init ath79_clocks_init(void)
+ {
++	const char *wdt;
++	const char *uart;
++
+ 	if (soc_is_ar71xx())
+ 		ar71xx_clocks_init();
+ 	else if (soc_is_ar724x() || soc_is_ar913x())
+@@ -651,6 +633,20 @@ void __init ath79_clocks_init(void)
+ 		qca956x_clocks_init();
+ 	else
+ 		BUG();
++
++	if (soc_is_ar71xx() || soc_is_ar724x() || soc_is_ar913x()) {
++		wdt = "ahb";
++		uart = "ahb";
++	} else if (soc_is_ar933x()) {
++		wdt = "ahb";
++		uart = "ref";
++	} else {
++		wdt = "ref";
++		uart = "ref";
++	}
++
++	clk_add_alias("wdt", NULL, wdt, NULL);
++	clk_add_alias("uart", NULL, uart, NULL);
+ }
+ 
+ unsigned long __init
diff --git a/target/linux/ath79/patches-4.19/0023-MIPS-ath79-pass-PLL-base-to-clock-init-functions.patch b/target/linux/ath79/patches-4.19/0023-MIPS-ath79-pass-PLL-base-to-clock-init-functions.patch
new file mode 100644
index 00000000000..6c0f2ad54c5
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/0023-MIPS-ath79-pass-PLL-base-to-clock-init-functions.patch
@@ -0,0 +1,242 @@
+From 6350b2c36c522fecbc91a80b63f49319dafd2a72 Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@nbd.name>
+Date: Tue, 6 Mar 2018 13:23:20 +0100
+Subject: [PATCH 23/33] MIPS: ath79: pass PLL base to clock init functions
+
+Preparation for passing the mapped base via DT
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ arch/mips/ath79/clock.c | 60 ++++++++++++++++++++++++-------------------------
+ 1 file changed, 30 insertions(+), 30 deletions(-)
+
+--- a/arch/mips/ath79/clock.c
++++ b/arch/mips/ath79/clock.c
+@@ -80,7 +80,7 @@ static struct clk * __init ath79_set_ff_
+ 	return clk;
+ }
+ 
+-static void __init ar71xx_clocks_init(void)
++static void __init ar71xx_clocks_init(void __iomem *pll_base)
+ {
+ 	unsigned long ref_rate;
+ 	unsigned long cpu_rate;
+@@ -92,7 +92,7 @@ static void __init ar71xx_clocks_init(vo
+ 
+ 	ref_rate = AR71XX_BASE_FREQ;
+ 
+-	pll = ath79_pll_rr(AR71XX_PLL_REG_CPU_CONFIG);
++	pll = __raw_readl(pll_base + AR71XX_PLL_REG_CPU_CONFIG);
+ 
+ 	div = ((pll >> AR71XX_PLL_FB_SHIFT) & AR71XX_PLL_FB_MASK) + 1;
+ 	freq = div * ref_rate;
+@@ -130,13 +130,13 @@ static void __init ar724x_clk_init(struc
+ 	ath79_set_ff_clk(ATH79_CLK_AHB, "ref", mult, div * ahb_div);
+ }
+ 
+-static void __init ar724x_clocks_init(void)
++static void __init ar724x_clocks_init(void __iomem *pll_base)
+ {
+ 	struct clk *ref_clk;
+ 
+ 	ref_clk = ath79_set_clk(ATH79_CLK_REF, AR724X_BASE_FREQ);
+ 
+-	ar724x_clk_init(ref_clk, ath79_pll_base);
++	ar724x_clk_init(ref_clk, pll_base);
+ }
+ 
+ static void __init ar9330_clk_init(struct clk *ref_clk, void __iomem *pll_base)
+@@ -197,7 +197,7 @@ static void __init ar9330_clk_init(struc
+ 			 ref_div * out_div * ahb_div);
+ }
+ 
+-static void __init ar933x_clocks_init(void)
++static void __init ar933x_clocks_init(void __iomem *pll_base)
+ {
+ 	struct clk *ref_clk;
+ 	unsigned long ref_rate;
+@@ -234,7 +234,7 @@ static u32 __init ar934x_get_pll_freq(u3
+ 	return ret;
+ }
+ 
+-static void __init ar934x_clocks_init(void)
++static void __init ar934x_clocks_init(void __iomem *pll_base)
+ {
+ 	unsigned long ref_rate;
+ 	unsigned long cpu_rate;
+@@ -265,7 +265,7 @@ static void __init ar934x_clocks_init(vo
+ 			  AR934X_SRIF_DPLL1_REFDIV_MASK;
+ 		frac = 1 << 18;
+ 	} else {
+-		pll = ath79_pll_rr(AR934X_PLL_CPU_CONFIG_REG);
++		pll = __raw_readl(pll_base + AR934X_PLL_CPU_CONFIG_REG);
+ 		out_div = (pll >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
+ 			AR934X_PLL_CPU_CONFIG_OUTDIV_MASK;
+ 		ref_div = (pll >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
+@@ -292,7 +292,7 @@ static void __init ar934x_clocks_init(vo
+ 			  AR934X_SRIF_DPLL1_REFDIV_MASK;
+ 		frac = 1 << 18;
+ 	} else {
+-		pll = ath79_pll_rr(AR934X_PLL_DDR_CONFIG_REG);
++		pll = __raw_readl(pll_base + AR934X_PLL_DDR_CONFIG_REG);
+ 		out_div = (pll >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) &
+ 			  AR934X_PLL_DDR_CONFIG_OUTDIV_MASK;
+ 		ref_div = (pll >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) &
+@@ -307,7 +307,7 @@ static void __init ar934x_clocks_init(vo
+ 	ddr_pll = ar934x_get_pll_freq(ref_rate, ref_div, nint,
+ 				      nfrac, frac, out_div);
+ 
+-	clk_ctrl = ath79_pll_rr(AR934X_PLL_CPU_DDR_CLK_CTRL_REG);
++	clk_ctrl = __raw_readl(pll_base + AR934X_PLL_CPU_DDR_CLK_CTRL_REG);
+ 
+ 	postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_SHIFT) &
+ 		  AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_MASK;
+@@ -347,7 +347,7 @@ static void __init ar934x_clocks_init(vo
+ 	iounmap(dpll_base);
+ }
+ 
+-static void __init qca953x_clocks_init(void)
++static void __init qca953x_clocks_init(void __iomem *pll_base)
+ {
+ 	unsigned long ref_rate;
+ 	unsigned long cpu_rate;
+@@ -363,7 +363,7 @@ static void __init qca953x_clocks_init(v
+ 	else
+ 		ref_rate = 25 * 1000 * 1000;
+ 
+-	pll = ath79_pll_rr(QCA953X_PLL_CPU_CONFIG_REG);
++	pll = __raw_readl(pll_base + QCA953X_PLL_CPU_CONFIG_REG);
+ 	out_div = (pll >> QCA953X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
+ 		  QCA953X_PLL_CPU_CONFIG_OUTDIV_MASK;
+ 	ref_div = (pll >> QCA953X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
+@@ -377,7 +377,7 @@ static void __init qca953x_clocks_init(v
+ 	cpu_pll += frac * (ref_rate >> 6) / ref_div;
+ 	cpu_pll /= (1 << out_div);
+ 
+-	pll = ath79_pll_rr(QCA953X_PLL_DDR_CONFIG_REG);
++	pll = __raw_readl(pll_base + QCA953X_PLL_DDR_CONFIG_REG);
+ 	out_div = (pll >> QCA953X_PLL_DDR_CONFIG_OUTDIV_SHIFT) &
+ 		  QCA953X_PLL_DDR_CONFIG_OUTDIV_MASK;
+ 	ref_div = (pll >> QCA953X_PLL_DDR_CONFIG_REFDIV_SHIFT) &
+@@ -391,7 +391,7 @@ static void __init qca953x_clocks_init(v
+ 	ddr_pll += frac * (ref_rate >> 6) / (ref_div << 4);
+ 	ddr_pll /= (1 << out_div);
+ 
+-	clk_ctrl = ath79_pll_rr(QCA953X_PLL_CLK_CTRL_REG);
++	clk_ctrl = __raw_readl(pll_base + QCA953X_PLL_CLK_CTRL_REG);
+ 
+ 	postdiv = (clk_ctrl >> QCA953X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) &
+ 		  QCA953X_PLL_CLK_CTRL_CPU_POST_DIV_MASK;
+@@ -429,7 +429,7 @@ static void __init qca953x_clocks_init(v
+ 	ath79_set_clk(ATH79_CLK_AHB, ahb_rate);
+ }
+ 
+-static void __init qca955x_clocks_init(void)
++static void __init qca955x_clocks_init(void __iomem *pll_base)
+ {
+ 	unsigned long ref_rate;
+ 	unsigned long cpu_rate;
+@@ -445,7 +445,7 @@ static void __init qca955x_clocks_init(v
+ 	else
+ 		ref_rate = 25 * 1000 * 1000;
+ 
+-	pll = ath79_pll_rr(QCA955X_PLL_CPU_CONFIG_REG);
++	pll = __raw_readl(pll_base + QCA955X_PLL_CPU_CONFIG_REG);
+ 	out_div = (pll >> QCA955X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
+ 		  QCA955X_PLL_CPU_CONFIG_OUTDIV_MASK;
+ 	ref_div = (pll >> QCA955X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
+@@ -459,7 +459,7 @@ static void __init qca955x_clocks_init(v
+ 	cpu_pll += frac * ref_rate / (ref_div * (1 << 6));
+ 	cpu_pll /= (1 << out_div);
+ 
+-	pll = ath79_pll_rr(QCA955X_PLL_DDR_CONFIG_REG);
++	pll = __raw_readl(pll_base + QCA955X_PLL_DDR_CONFIG_REG);
+ 	out_div = (pll >> QCA955X_PLL_DDR_CONFIG_OUTDIV_SHIFT) &
+ 		  QCA955X_PLL_DDR_CONFIG_OUTDIV_MASK;
+ 	ref_div = (pll >> QCA955X_PLL_DDR_CONFIG_REFDIV_SHIFT) &
+@@ -473,7 +473,7 @@ static void __init qca955x_clocks_init(v
+ 	ddr_pll += frac * ref_rate / (ref_div * (1 << 10));
+ 	ddr_pll /= (1 << out_div);
+ 
+-	clk_ctrl = ath79_pll_rr(QCA955X_PLL_CLK_CTRL_REG);
++	clk_ctrl = __raw_readl(pll_base + QCA955X_PLL_CLK_CTRL_REG);
+ 
+ 	postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) &
+ 		  QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_MASK;
+@@ -511,7 +511,7 @@ static void __init qca955x_clocks_init(v
+ 	ath79_set_clk(ATH79_CLK_AHB, ahb_rate);
+ }
+ 
+-static void __init qca956x_clocks_init(void)
++static void __init qca956x_clocks_init(void __iomem *pll_base)
+ {
+ 	unsigned long ref_rate;
+ 	unsigned long cpu_rate;
+@@ -537,13 +537,13 @@ static void __init qca956x_clocks_init(v
+ 	else
+ 		ref_rate = 25 * 1000 * 1000;
+ 
+-	pll = ath79_pll_rr(QCA956X_PLL_CPU_CONFIG_REG);
++	pll = __raw_readl(pll_base + QCA956X_PLL_CPU_CONFIG_REG);
+ 	out_div = (pll >> QCA956X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
+ 		  QCA956X_PLL_CPU_CONFIG_OUTDIV_MASK;
+ 	ref_div = (pll >> QCA956X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
+ 		  QCA956X_PLL_CPU_CONFIG_REFDIV_MASK;
+ 
+-	pll = ath79_pll_rr(QCA956X_PLL_CPU_CONFIG1_REG);
++	pll = __raw_readl(pll_base + QCA956X_PLL_CPU_CONFIG1_REG);
+ 	nint = (pll >> QCA956X_PLL_CPU_CONFIG1_NINT_SHIFT) &
+ 	       QCA956X_PLL_CPU_CONFIG1_NINT_MASK;
+ 	hfrac = (pll >> QCA956X_PLL_CPU_CONFIG1_NFRAC_H_SHIFT) &
+@@ -556,12 +556,12 @@ static void __init qca956x_clocks_init(v
+ 	cpu_pll += (hfrac >> 13) * ref_rate / ref_div;
+ 	cpu_pll /= (1 << out_div);
+ 
+-	pll = ath79_pll_rr(QCA956X_PLL_DDR_CONFIG_REG);
++	pll = __raw_readl(pll_base + QCA956X_PLL_DDR_CONFIG_REG);
+ 	out_div = (pll >> QCA956X_PLL_DDR_CONFIG_OUTDIV_SHIFT) &
+ 		  QCA956X_PLL_DDR_CONFIG_OUTDIV_MASK;
+ 	ref_div = (pll >> QCA956X_PLL_DDR_CONFIG_REFDIV_SHIFT) &
+ 		  QCA956X_PLL_DDR_CONFIG_REFDIV_MASK;
+-	pll = ath79_pll_rr(QCA956X_PLL_DDR_CONFIG1_REG);
++	pll = __raw_readl(pll_base + QCA956X_PLL_DDR_CONFIG1_REG);
+ 	nint = (pll >> QCA956X_PLL_DDR_CONFIG1_NINT_SHIFT) &
+ 	       QCA956X_PLL_DDR_CONFIG1_NINT_MASK;
+ 	hfrac = (pll >> QCA956X_PLL_DDR_CONFIG1_NFRAC_H_SHIFT) &
+@@ -574,7 +574,7 @@ static void __init qca956x_clocks_init(v
+ 	ddr_pll += (hfrac >> 13) * ref_rate / ref_div;
+ 	ddr_pll /= (1 << out_div);
+ 
+-	clk_ctrl = ath79_pll_rr(QCA956X_PLL_CLK_CTRL_REG);
++	clk_ctrl = __raw_readl(pll_base + QCA956X_PLL_CLK_CTRL_REG);
+ 
+ 	postdiv = (clk_ctrl >> QCA956X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) &
+ 		  QCA956X_PLL_CLK_CTRL_CPU_POST_DIV_MASK;
+@@ -618,19 +618,19 @@ void __init ath79_clocks_init(void)
+ 	const char *uart;
+ 
+ 	if (soc_is_ar71xx())
+-		ar71xx_clocks_init();
++		ar71xx_clocks_init(ath79_pll_base);
+ 	else if (soc_is_ar724x() || soc_is_ar913x())
+-		ar724x_clocks_init();
++		ar724x_clocks_init(ath79_pll_base);
+ 	else if (soc_is_ar933x())
+-		ar933x_clocks_init();
++		ar933x_clocks_init(ath79_pll_base);
+ 	else if (soc_is_ar934x())
+-		ar934x_clocks_init();
++		ar934x_clocks_init(ath79_pll_base);
+ 	else if (soc_is_qca953x())
+-		qca953x_clocks_init();
++		qca953x_clocks_init(ath79_pll_base);
+ 	else if (soc_is_qca955x())
+-		qca955x_clocks_init();
++		qca955x_clocks_init(ath79_pll_base);
+ 	else if (soc_is_qca956x() || soc_is_tp9343())
+-		qca956x_clocks_init();
++		qca956x_clocks_init(ath79_pll_base);
+ 	else
+ 		BUG();
+ 
diff --git a/target/linux/ath79/patches-4.19/0024-MIPS-ath79-make-specifying-the-reference-clock-in-DT.patch b/target/linux/ath79/patches-4.19/0024-MIPS-ath79-make-specifying-the-reference-clock-in-DT.patch
new file mode 100644
index 00000000000..9ceb6438039
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/0024-MIPS-ath79-make-specifying-the-reference-clock-in-DT.patch
@@ -0,0 +1,229 @@
+From 5fadb2544ed0bb72ddddd846aa303bb9ed2d211c Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@nbd.name>
+Date: Tue, 6 Mar 2018 13:24:07 +0100
+Subject: [PATCH 24/33] MIPS: ath79: make specifying the reference clock in DT
+ optional
+
+It can be autodetected for many SoCs using the strapping options.
+If the clock is specified in DT, the autodetected value is ignored
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ arch/mips/ath79/clock.c | 84 +++++++++++++++++++++++--------------------------
+ 1 file changed, 40 insertions(+), 44 deletions(-)
+
+--- a/arch/mips/ath79/clock.c
++++ b/arch/mips/ath79/clock.c
+@@ -80,6 +80,18 @@ static struct clk * __init ath79_set_ff_
+ 	return clk;
+ }
+ 
++static unsigned long __init ath79_setup_ref_clk(unsigned long rate)
++{
++	struct clk *clk = clks[ATH79_CLK_REF];
++
++	if (clk)
++		rate = clk_get_rate(clk);
++	else
++		clk = ath79_set_clk(ATH79_CLK_REF, rate);
++
++	return rate;
++}
++
+ static void __init ar71xx_clocks_init(void __iomem *pll_base)
+ {
+ 	unsigned long ref_rate;
+@@ -90,7 +102,7 @@ static void __init ar71xx_clocks_init(vo
+ 	u32 freq;
+ 	u32 div;
+ 
+-	ref_rate = AR71XX_BASE_FREQ;
++	ref_rate = ath79_setup_ref_clk(AR71XX_BASE_FREQ);
+ 
+ 	pll = __raw_readl(pll_base + AR71XX_PLL_REG_CPU_CONFIG);
+ 
+@@ -106,16 +118,17 @@ static void __init ar71xx_clocks_init(vo
+ 	div = (((pll >> AR71XX_AHB_DIV_SHIFT) & AR71XX_AHB_DIV_MASK) + 1) * 2;
+ 	ahb_rate = cpu_rate / div;
+ 
+-	ath79_set_clk(ATH79_CLK_REF, ref_rate);
+ 	ath79_set_clk(ATH79_CLK_CPU, cpu_rate);
+ 	ath79_set_clk(ATH79_CLK_DDR, ddr_rate);
+ 	ath79_set_clk(ATH79_CLK_AHB, ahb_rate);
+ }
+ 
+-static void __init ar724x_clk_init(struct clk *ref_clk, void __iomem *pll_base)
++static void __init ar724x_clocks_init(void __iomem *pll_base)
+ {
+-	u32 pll;
+ 	u32 mult, div, ddr_div, ahb_div;
++	u32 pll;
++
++	ath79_setup_ref_clk(AR71XX_BASE_FREQ);
+ 
+ 	pll = __raw_readl(pll_base + AR724X_PLL_REG_CPU_CONFIG);
+ 
+@@ -130,17 +143,9 @@ static void __init ar724x_clk_init(struc
+ 	ath79_set_ff_clk(ATH79_CLK_AHB, "ref", mult, div * ahb_div);
+ }
+ 
+-static void __init ar724x_clocks_init(void __iomem *pll_base)
+-{
+-	struct clk *ref_clk;
+-
+-	ref_clk = ath79_set_clk(ATH79_CLK_REF, AR724X_BASE_FREQ);
+-
+-	ar724x_clk_init(ref_clk, pll_base);
+-}
+-
+-static void __init ar9330_clk_init(struct clk *ref_clk, void __iomem *pll_base)
++static void __init ar933x_clocks_init(void __iomem *pll_base)
+ {
++	unsigned long ref_rate;
+ 	u32 clock_ctrl;
+ 	u32 ref_div;
+ 	u32 ninit_mul;
+@@ -149,6 +154,15 @@ static void __init ar9330_clk_init(struc
+ 	u32 cpu_div;
+ 	u32 ddr_div;
+ 	u32 ahb_div;
++	u32 t;
++
++	t = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP);
++	if (t & AR933X_BOOTSTRAP_REF_CLK_40)
++		ref_rate = (40 * 1000 * 1000);
++	else
++		ref_rate = (25 * 1000 * 1000);
++
++	ath79_setup_ref_clk(ref_rate);
+ 
+ 	clock_ctrl = __raw_readl(pll_base + AR933X_PLL_CLOCK_CTRL_REG);
+ 	if (clock_ctrl & AR933X_PLL_CLOCK_CTRL_BYPASS) {
+@@ -197,23 +211,6 @@ static void __init ar9330_clk_init(struc
+ 			 ref_div * out_div * ahb_div);
+ }
+ 
+-static void __init ar933x_clocks_init(void __iomem *pll_base)
+-{
+-	struct clk *ref_clk;
+-	unsigned long ref_rate;
+-	u32 t;
+-
+-	t = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP);
+-	if (t & AR933X_BOOTSTRAP_REF_CLK_40)
+-		ref_rate = (40 * 1000 * 1000);
+-	else
+-		ref_rate = (25 * 1000 * 1000);
+-
+-	ref_clk = ath79_set_clk(ATH79_CLK_REF, ref_rate);
+-
+-	ar9330_clk_init(ref_clk, ath79_pll_base);
+-}
+-
+ static u32 __init ar934x_get_pll_freq(u32 ref, u32 ref_div, u32 nint, u32 nfrac,
+ 				      u32 frac, u32 out_div)
+ {
+@@ -253,6 +250,8 @@ static void __init ar934x_clocks_init(vo
+ 	else
+ 		ref_rate = 25 * 1000 * 1000;
+ 
++	ref_rate = ath79_setup_ref_clk(ref_rate);
++
+ 	pll = __raw_readl(dpll_base + AR934X_SRIF_CPU_DPLL2_REG);
+ 	if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) {
+ 		out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) &
+@@ -339,7 +338,6 @@ static void __init ar934x_clocks_init(vo
+ 	else
+ 		ahb_rate = cpu_pll / (postdiv + 1);
+ 
+-	ath79_set_clk(ATH79_CLK_REF, ref_rate);
+ 	ath79_set_clk(ATH79_CLK_CPU, cpu_rate);
+ 	ath79_set_clk(ATH79_CLK_DDR, ddr_rate);
+ 	ath79_set_clk(ATH79_CLK_AHB, ahb_rate);
+@@ -363,6 +361,8 @@ static void __init qca953x_clocks_init(v
+ 	else
+ 		ref_rate = 25 * 1000 * 1000;
+ 
++	ref_rate = ath79_setup_ref_clk(ref_rate);
++
+ 	pll = __raw_readl(pll_base + QCA953X_PLL_CPU_CONFIG_REG);
+ 	out_div = (pll >> QCA953X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
+ 		  QCA953X_PLL_CPU_CONFIG_OUTDIV_MASK;
+@@ -423,7 +423,6 @@ static void __init qca953x_clocks_init(v
+ 	else
+ 		ahb_rate = cpu_pll / (postdiv + 1);
+ 
+-	ath79_set_clk(ATH79_CLK_REF, ref_rate);
+ 	ath79_set_clk(ATH79_CLK_CPU, cpu_rate);
+ 	ath79_set_clk(ATH79_CLK_DDR, ddr_rate);
+ 	ath79_set_clk(ATH79_CLK_AHB, ahb_rate);
+@@ -445,6 +444,8 @@ static void __init qca955x_clocks_init(v
+ 	else
+ 		ref_rate = 25 * 1000 * 1000;
+ 
++	ref_rate = ath79_setup_ref_clk(ref_rate);
++
+ 	pll = __raw_readl(pll_base + QCA955X_PLL_CPU_CONFIG_REG);
+ 	out_div = (pll >> QCA955X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
+ 		  QCA955X_PLL_CPU_CONFIG_OUTDIV_MASK;
+@@ -505,7 +506,6 @@ static void __init qca955x_clocks_init(v
+ 	else
+ 		ahb_rate = cpu_pll / (postdiv + 1);
+ 
+-	ath79_set_clk(ATH79_CLK_REF, ref_rate);
+ 	ath79_set_clk(ATH79_CLK_CPU, cpu_rate);
+ 	ath79_set_clk(ATH79_CLK_DDR, ddr_rate);
+ 	ath79_set_clk(ATH79_CLK_AHB, ahb_rate);
+@@ -537,6 +537,8 @@ static void __init qca956x_clocks_init(v
+ 	else
+ 		ref_rate = 25 * 1000 * 1000;
+ 
++	ref_rate = ath79_setup_ref_clk(ref_rate);
++
+ 	pll = __raw_readl(pll_base + QCA956X_PLL_CPU_CONFIG_REG);
+ 	out_div = (pll >> QCA956X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
+ 		  QCA956X_PLL_CPU_CONFIG_OUTDIV_MASK;
+@@ -606,7 +608,6 @@ static void __init qca956x_clocks_init(v
+ 	else
+ 		ahb_rate = cpu_pll / (postdiv + 1);
+ 
+-	ath79_set_clk(ATH79_CLK_REF, ref_rate);
+ 	ath79_set_clk(ATH79_CLK_CPU, cpu_rate);
+ 	ath79_set_clk(ATH79_CLK_DDR, ddr_rate);
+ 	ath79_set_clk(ATH79_CLK_AHB, ahb_rate);
+@@ -682,10 +683,8 @@ static void __init ath79_clocks_init_dt_
+ 	void __iomem *pll_base;
+ 
+ 	ref_clk = of_clk_get(np, 0);
+-	if (IS_ERR(ref_clk)) {
+-		pr_err("%pOF: of_clk_get failed\n", np);
+-		goto err;
+-	}
++	if (!IS_ERR(ref_clk))
++		clks[ATH79_CLK_REF] = ref_clk;
+ 
+ 	pll_base = of_iomap(np, 0);
+ 	if (!pll_base) {
+@@ -694,9 +693,9 @@ static void __init ath79_clocks_init_dt_
+ 	}
+ 
+ 	if (of_device_is_compatible(np, "qca,ar9130-pll"))
+-		ar724x_clk_init(ref_clk, pll_base);
++		ar724x_clocks_init(pll_base);
+ 	else if (of_device_is_compatible(np, "qca,ar9330-pll"))
+-		ar9330_clk_init(ref_clk, pll_base);
++		ar933x_clocks_init(pll_base);
+ 	else {
+ 		pr_err("%pOF: could not find any appropriate clk_init()\n", np);
+ 		goto err_iounmap;
+@@ -714,9 +713,6 @@ err_iounmap:
+ 
+ err_clk:
+ 	clk_put(ref_clk);
+-
+-err:
+-	return;
+ }
+ CLK_OF_DECLARE(ar9130_clk, "qca,ar9130-pll", ath79_clocks_init_dt_ng);
+ CLK_OF_DECLARE(ar9330_clk, "qca,ar9330-pll", ath79_clocks_init_dt_ng);
diff --git a/target/linux/ath79/patches-4.19/0025-MIPS-ath79-support-setting-up-clock-via-DT-on-all-So.patch b/target/linux/ath79/patches-4.19/0025-MIPS-ath79-support-setting-up-clock-via-DT-on-all-So.patch
new file mode 100644
index 00000000000..13f46a91464
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/0025-MIPS-ath79-support-setting-up-clock-via-DT-on-all-So.patch
@@ -0,0 +1,77 @@
+From 6325626de001df98aebe51f3008b1aca05798d19 Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@nbd.name>
+Date: Tue, 6 Mar 2018 13:26:27 +0100
+Subject: [PATCH 25/33] MIPS: ath79: support setting up clock via DT on all SoC
+ types
+
+Use the same functions as the legacy code
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ arch/mips/ath79/clock.c | 39 ++++++++++++++++++++++-----------------
+ 1 file changed, 22 insertions(+), 17 deletions(-)
+
+--- a/arch/mips/ath79/clock.c
++++ b/arch/mips/ath79/clock.c
+@@ -669,16 +669,6 @@ ath79_get_sys_clk_rate(const char *id)
+ #ifdef CONFIG_OF
+ static void __init ath79_clocks_init_dt(struct device_node *np)
+ {
+-	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+-}
+-
+-CLK_OF_DECLARE(ar7100, "qca,ar7100-pll", ath79_clocks_init_dt);
+-CLK_OF_DECLARE(ar7240, "qca,ar7240-pll", ath79_clocks_init_dt);
+-CLK_OF_DECLARE(ar9340, "qca,ar9340-pll", ath79_clocks_init_dt);
+-CLK_OF_DECLARE(ar9550, "qca,qca9550-pll", ath79_clocks_init_dt);
+-
+-static void __init ath79_clocks_init_dt_ng(struct device_node *np)
+-{
+ 	struct clk *ref_clk;
+ 	void __iomem *pll_base;
+ 
+@@ -692,14 +682,21 @@ static void __init ath79_clocks_init_dt_
+ 		goto err_clk;
+ 	}
+ 
+-	if (of_device_is_compatible(np, "qca,ar9130-pll"))
++	if (of_device_is_compatible(np, "qca,ar7100-pll"))
++		ar71xx_clocks_init(pll_base);
++	else if (of_device_is_compatible(np, "qca,ar7240-pll") ||
++		 of_device_is_compatible(np, "qca,ar9130-pll"))
+ 		ar724x_clocks_init(pll_base);
+ 	else if (of_device_is_compatible(np, "qca,ar9330-pll"))
+ 		ar933x_clocks_init(pll_base);
+-	else {
+-		pr_err("%pOF: could not find any appropriate clk_init()\n", np);
+-		goto err_iounmap;
+-	}
++	else if (of_device_is_compatible(np, "qca,ar9340-pll"))
++		ar934x_clocks_init(pll_base);
++	else if (of_device_is_compatible(np, "qca,qca9530-pll"))
++		qca953x_clocks_init(pll_base);
++	else if (of_device_is_compatible(np, "qca,qca9550-pll"))
++		qca955x_clocks_init(pll_base);
++	else if (of_device_is_compatible(np, "qca,qca9560-pll"))
++		qca956x_clocks_init(pll_base);
+ 
+ 	if (of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data)) {
+ 		pr_err("%pOF: could not register clk provider\n", np);
+@@ -714,6 +711,14 @@ err_iounmap:
+ err_clk:
+ 	clk_put(ref_clk);
+ }
+-CLK_OF_DECLARE(ar9130_clk, "qca,ar9130-pll", ath79_clocks_init_dt_ng);
+-CLK_OF_DECLARE(ar9330_clk, "qca,ar9330-pll", ath79_clocks_init_dt_ng);
++
++CLK_OF_DECLARE(ar7100_clk, "qca,ar7100-pll", ath79_clocks_init_dt);
++CLK_OF_DECLARE(ar7240_clk, "qca,ar7240-pll", ath79_clocks_init_dt);
++CLK_OF_DECLARE(ar9130_clk, "qca,ar9130-pll", ath79_clocks_init_dt);
++CLK_OF_DECLARE(ar9330_clk, "qca,ar9330-pll", ath79_clocks_init_dt);
++CLK_OF_DECLARE(ar9340_clk, "qca,ar9340-pll", ath79_clocks_init_dt);
++CLK_OF_DECLARE(ar9530_clk, "qca,qca9530-pll", ath79_clocks_init_dt);
++CLK_OF_DECLARE(ar9550_clk, "qca,qca9550-pll", ath79_clocks_init_dt);
++CLK_OF_DECLARE(ar9560_clk, "qca,qca9560-pll", ath79_clocks_init_dt);
++
+ #endif
diff --git a/target/linux/ath79/patches-4.19/0026-MIPS-ath79-export-switch-MDIO-reference-clock.patch b/target/linux/ath79/patches-4.19/0026-MIPS-ath79-export-switch-MDIO-reference-clock.patch
new file mode 100644
index 00000000000..27adb56f560
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/0026-MIPS-ath79-export-switch-MDIO-reference-clock.patch
@@ -0,0 +1,59 @@
+From 78538d673801902108797f2c813e70cfbce280c9 Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@nbd.name>
+Date: Tue, 6 Mar 2018 13:27:28 +0100
+Subject: [PATCH 26/33] MIPS: ath79: export switch MDIO reference clock
+
+On AR934x, the MDIO reference clock can be configured to a fixed 100 MHz
+clock. If that feature is not used, it defaults to the main reference
+clock, like on all other SoC.
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ arch/mips/ath79/clock.c               | 8 ++++++++
+ include/dt-bindings/clock/ath79-clk.h | 3 ++-
+ 2 files changed, 10 insertions(+), 1 deletion(-)
+
+--- a/arch/mips/ath79/clock.c
++++ b/arch/mips/ath79/clock.c
+@@ -42,6 +42,7 @@ static const char * const clk_names[ATH7
+ 	[ATH79_CLK_DDR] = "ddr",
+ 	[ATH79_CLK_AHB] = "ahb",
+ 	[ATH79_CLK_REF] = "ref",
++	[ATH79_CLK_MDIO] = "mdio",
+ };
+ 
+ static const char * __init ath79_clk_name(int type)
+@@ -342,6 +343,10 @@ static void __init ar934x_clocks_init(vo
+ 	ath79_set_clk(ATH79_CLK_DDR, ddr_rate);
+ 	ath79_set_clk(ATH79_CLK_AHB, ahb_rate);
+ 
++	clk_ctrl = __raw_readl(pll_base + AR934X_PLL_SWITCH_CLOCK_CONTROL_REG);
++	if (clk_ctrl & AR934X_PLL_SWITCH_CLOCK_CONTROL_MDIO_CLK_SEL)
++		ath79_set_clk(ATH79_CLK_MDIO, 100 * 1000 * 1000);
++
+ 	iounmap(dpll_base);
+ }
+ 
+@@ -698,6 +703,9 @@ static void __init ath79_clocks_init_dt(
+ 	else if (of_device_is_compatible(np, "qca,qca9560-pll"))
+ 		qca956x_clocks_init(pll_base);
+ 
++	if (!clks[ATH79_CLK_MDIO])
++		clks[ATH79_CLK_MDIO] = clks[ATH79_CLK_REF];
++
+ 	if (of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data)) {
+ 		pr_err("%pOF: could not register clk provider\n", np);
+ 		goto err_iounmap;
+--- a/include/dt-bindings/clock/ath79-clk.h
++++ b/include/dt-bindings/clock/ath79-clk.h
+@@ -14,7 +14,8 @@
+ #define ATH79_CLK_DDR		1
+ #define ATH79_CLK_AHB		2
+ #define ATH79_CLK_REF		3
++#define ATH79_CLK_MDIO		4
+ 
+-#define ATH79_CLK_END		4
++#define ATH79_CLK_END		5
+ 
+ #endif /* __DT_BINDINGS_ATH79_CLK_H */
diff --git a/target/linux/ath79/patches-4.19/0027-MIPS-ath79-drop-legacy-IRQ-code.patch b/target/linux/ath79/patches-4.19/0027-MIPS-ath79-drop-legacy-IRQ-code.patch
new file mode 100644
index 00000000000..79f003d2ea3
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/0027-MIPS-ath79-drop-legacy-IRQ-code.patch
@@ -0,0 +1,233 @@
+From 3765b1f79593a0a9098ed15e48074c95403a53ee Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Sat, 23 Jun 2018 15:05:08 +0200
+Subject: [PATCH 27/33] MIPS: ath79: drop legacy IRQ code
+
+With the target now being fully OF based, we can drop the legacy IRQ code.
+All IRQs are now handled via the new irqchip drivers.
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ arch/mips/ath79/Makefile                 |   2 +-
+ arch/mips/ath79/irq.c                    | 169 -------------------------------
+ arch/mips/ath79/setup.c                  |   6 ++
+ arch/mips/include/asm/mach-ath79/ath79.h |   4 -
+ 4 files changed, 7 insertions(+), 174 deletions(-)
+ delete mode 100644 arch/mips/ath79/irq.c
+
+--- a/arch/mips/ath79/Makefile
++++ b/arch/mips/ath79/Makefile
+@@ -8,7 +8,7 @@
+ # under the terms of the GNU General Public License version 2 as published
+ # by the Free Software Foundation.
+ 
+-obj-y	:= prom.o setup.o irq.o common.o clock.o
++obj-y	:= prom.o setup.o common.o clock.o
+ 
+ obj-$(CONFIG_EARLY_PRINTK)		+= early_printk.o
+ obj-$(CONFIG_PCI)			+= pci.o
+--- a/arch/mips/ath79/irq.c
++++ /dev/null
+@@ -1,169 +0,0 @@
+-/*
+- *  Atheros AR71xx/AR724x/AR913x specific interrupt handling
+- *
+- *  Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com>
+- *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
+- *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+- *
+- *  Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP
+- *
+- *  This program 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.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/interrupt.h>
+-#include <linux/irqchip.h>
+-#include <linux/of_irq.h>
+-
+-#include <asm/irq_cpu.h>
+-#include <asm/mipsregs.h>
+-
+-#include <asm/mach-ath79/ath79.h>
+-#include <asm/mach-ath79/ar71xx_regs.h>
+-#include "common.h"
+-#include "machtypes.h"
+-
+-
+-static void ar934x_ip2_irq_dispatch(struct irq_desc *desc)
+-{
+-	u32 status;
+-
+-	status = ath79_reset_rr(AR934X_RESET_REG_PCIE_WMAC_INT_STATUS);
+-
+-	if (status & AR934X_PCIE_WMAC_INT_PCIE_ALL) {
+-		ath79_ddr_wb_flush(3);
+-		generic_handle_irq(ATH79_IP2_IRQ(0));
+-	} else if (status & AR934X_PCIE_WMAC_INT_WMAC_ALL) {
+-		ath79_ddr_wb_flush(4);
+-		generic_handle_irq(ATH79_IP2_IRQ(1));
+-	} else {
+-		spurious_interrupt();
+-	}
+-}
+-
+-static void ar934x_ip2_irq_init(void)
+-{
+-	int i;
+-
+-	for (i = ATH79_IP2_IRQ_BASE;
+-	     i < ATH79_IP2_IRQ_BASE + ATH79_IP2_IRQ_COUNT; i++)
+-		irq_set_chip_and_handler(i, &dummy_irq_chip,
+-					 handle_level_irq);
+-
+-	irq_set_chained_handler(ATH79_CPU_IRQ(2), ar934x_ip2_irq_dispatch);
+-}
+-
+-static void qca955x_ip2_irq_dispatch(struct irq_desc *desc)
+-{
+-	u32 status;
+-
+-	status = ath79_reset_rr(QCA955X_RESET_REG_EXT_INT_STATUS);
+-	status &= QCA955X_EXT_INT_PCIE_RC1_ALL | QCA955X_EXT_INT_WMAC_ALL;
+-
+-	if (status == 0) {
+-		spurious_interrupt();
+-		return;
+-	}
+-
+-	if (status & QCA955X_EXT_INT_PCIE_RC1_ALL) {
+-		/* TODO: flush DDR? */
+-		generic_handle_irq(ATH79_IP2_IRQ(0));
+-	}
+-
+-	if (status & QCA955X_EXT_INT_WMAC_ALL) {
+-		/* TODO: flush DDR? */
+-		generic_handle_irq(ATH79_IP2_IRQ(1));
+-	}
+-}
+-
+-static void qca955x_ip3_irq_dispatch(struct irq_desc *desc)
+-{
+-	u32 status;
+-
+-	status = ath79_reset_rr(QCA955X_RESET_REG_EXT_INT_STATUS);
+-	status &= QCA955X_EXT_INT_PCIE_RC2_ALL |
+-		  QCA955X_EXT_INT_USB1 |
+-		  QCA955X_EXT_INT_USB2;
+-
+-	if (status == 0) {
+-		spurious_interrupt();
+-		return;
+-	}
+-
+-	if (status & QCA955X_EXT_INT_USB1) {
+-		/* TODO: flush DDR? */
+-		generic_handle_irq(ATH79_IP3_IRQ(0));
+-	}
+-
+-	if (status & QCA955X_EXT_INT_USB2) {
+-		/* TODO: flush DDR? */
+-		generic_handle_irq(ATH79_IP3_IRQ(1));
+-	}
+-
+-	if (status & QCA955X_EXT_INT_PCIE_RC2_ALL) {
+-		/* TODO: flush DDR? */
+-		generic_handle_irq(ATH79_IP3_IRQ(2));
+-	}
+-}
+-
+-static void qca955x_irq_init(void)
+-{
+-	int i;
+-
+-	for (i = ATH79_IP2_IRQ_BASE;
+-	     i < ATH79_IP2_IRQ_BASE + ATH79_IP2_IRQ_COUNT; i++)
+-		irq_set_chip_and_handler(i, &dummy_irq_chip,
+-					 handle_level_irq);
+-
+-	irq_set_chained_handler(ATH79_CPU_IRQ(2), qca955x_ip2_irq_dispatch);
+-
+-	for (i = ATH79_IP3_IRQ_BASE;
+-	     i < ATH79_IP3_IRQ_BASE + ATH79_IP3_IRQ_COUNT; i++)
+-		irq_set_chip_and_handler(i, &dummy_irq_chip,
+-					 handle_level_irq);
+-
+-	irq_set_chained_handler(ATH79_CPU_IRQ(3), qca955x_ip3_irq_dispatch);
+-}
+-
+-void __init arch_init_irq(void)
+-{
+-	unsigned irq_wb_chan2 = -1;
+-	unsigned irq_wb_chan3 = -1;
+-	bool misc_is_ar71xx;
+-
+-	if (mips_machtype == ATH79_MACH_GENERIC_OF) {
+-		irqchip_init();
+-		return;
+-	}
+-
+-	if (soc_is_ar71xx() || soc_is_ar724x() ||
+-	    soc_is_ar913x() || soc_is_ar933x()) {
+-		irq_wb_chan2 = 3;
+-		irq_wb_chan3 = 2;
+-	} else if (soc_is_ar934x()) {
+-		irq_wb_chan3 = 2;
+-	}
+-
+-	ath79_cpu_irq_init(irq_wb_chan2, irq_wb_chan3);
+-
+-	if (soc_is_ar71xx() || soc_is_ar913x())
+-		misc_is_ar71xx = true;
+-	else if (soc_is_ar724x() ||
+-		 soc_is_ar933x() ||
+-		 soc_is_ar934x() ||
+-		 soc_is_qca955x())
+-		misc_is_ar71xx = false;
+-	else
+-		BUG();
+-	ath79_misc_irq_init(
+-		ath79_reset_base + AR71XX_RESET_REG_MISC_INT_STATUS,
+-		ATH79_CPU_IRQ(6), ATH79_MISC_IRQ_BASE, misc_is_ar71xx);
+-
+-	if (soc_is_ar934x())
+-		ar934x_ip2_irq_init();
+-	else if (soc_is_qca955x())
+-		qca955x_irq_init();
+-}
+--- a/arch/mips/ath79/setup.c
++++ b/arch/mips/ath79/setup.c
+@@ -19,6 +19,7 @@
+ #include <linux/clk.h>
+ #include <linux/clk-provider.h>
+ #include <linux/of_fdt.h>
++#include <linux/irqchip.h>
+ 
+ #include <asm/bootinfo.h>
+ #include <asm/idle.h>
+@@ -311,6 +312,11 @@ void __init plat_time_init(void)
+ 	mips_hpt_frequency = cpu_clk_rate / 2;
+ }
+ 
++void __init arch_init_irq(void)
++{
++	irqchip_init();
++}
++
+ static int __init ath79_setup(void)
+ {
+ 	if  (mips_machtype == ATH79_MACH_GENERIC_OF)
+--- a/arch/mips/include/asm/mach-ath79/ath79.h
++++ b/arch/mips/include/asm/mach-ath79/ath79.h
+@@ -178,8 +178,4 @@ static inline u32 ath79_reset_rr(unsigne
+ void ath79_device_reset_set(u32 mask);
+ void ath79_device_reset_clear(u32 mask);
+ 
+-void ath79_cpu_irq_init(unsigned irq_wb_chan2, unsigned irq_wb_chan3);
+-void ath79_misc_irq_init(void __iomem *regs, int irq,
+-			int irq_base, bool is_ar71xx);
+-
+ #endif /* __ASM_MACH_ATH79_H */
diff --git a/target/linux/ath79/patches-4.19/0028-MIPS-ath79-drop-machfiles.patch b/target/linux/ath79/patches-4.19/0028-MIPS-ath79-drop-machfiles.patch
new file mode 100644
index 00000000000..0515b206b04
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/0028-MIPS-ath79-drop-machfiles.patch
@@ -0,0 +1,1048 @@
+From badf28957b6dc400dff27bd23ba2ae75d9514be5 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Sat, 23 Jun 2018 15:04:09 +0200
+Subject: [PATCH 28/33] MIPS: ath79: drop machfiles
+
+With the target now being fully OF based, we can drop the legacy mach
+files. Boards can now boot fully of devicetree files.
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ arch/mips/Kconfig              |   1 -
+ arch/mips/ath79/Kconfig        |  73 -------------------
+ arch/mips/ath79/Makefile       |  10 ---
+ arch/mips/ath79/clock.c        |   1 -
+ arch/mips/ath79/mach-ap121.c   |  92 ------------------------
+ arch/mips/ath79/mach-ap136.c   | 156 -----------------------------------------
+ arch/mips/ath79/mach-ap81.c    | 100 --------------------------
+ arch/mips/ath79/mach-db120.c   | 136 -----------------------------------
+ arch/mips/ath79/mach-pb44.c    | 128 ---------------------------------
+ arch/mips/ath79/mach-ubnt-xm.c | 126 ---------------------------------
+ arch/mips/ath79/machtypes.h    |  28 --------
+ arch/mips/ath79/setup.c        |  77 +++-----------------
+ 12 files changed, 9 insertions(+), 919 deletions(-)
+ delete mode 100644 arch/mips/ath79/mach-ap121.c
+ delete mode 100644 arch/mips/ath79/mach-ap136.c
+ delete mode 100644 arch/mips/ath79/mach-ap81.c
+ delete mode 100644 arch/mips/ath79/mach-db120.c
+ delete mode 100644 arch/mips/ath79/mach-pb44.c
+ delete mode 100644 arch/mips/ath79/mach-ubnt-xm.c
+ delete mode 100644 arch/mips/ath79/machtypes.h
+
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -202,7 +202,6 @@ config ATH79
+ 	select COMMON_CLK
+ 	select CLKDEV_LOOKUP
+ 	select IRQ_MIPS_CPU
+-	select MIPS_MACHINE
+ 	select SYS_HAS_CPU_MIPS32_R2
+ 	select SYS_HAS_EARLY_PRINTK
+ 	select SYS_SUPPORTS_32BIT_KERNEL
+--- a/arch/mips/ath79/Kconfig
++++ b/arch/mips/ath79/Kconfig
+@@ -1,79 +1,6 @@
+ # SPDX-License-Identifier: GPL-2.0
+ if ATH79
+ 
+-menu "Atheros AR71XX/AR724X/AR913X machine selection"
+-
+-config ATH79_MACH_AP121
+-	bool "Atheros AP121 reference board"
+-	select SOC_AR933X
+-	select ATH79_DEV_GPIO_BUTTONS
+-	select ATH79_DEV_LEDS_GPIO
+-	select ATH79_DEV_SPI
+-	select ATH79_DEV_USB
+-	select ATH79_DEV_WMAC
+-	help
+-	  Say 'Y' here if you want your kernel to support the
+-	  Atheros AP121 reference board.
+-
+-config ATH79_MACH_AP136
+-	bool "Atheros AP136 reference board"
+-	select SOC_QCA955X
+-	select ATH79_DEV_GPIO_BUTTONS
+-	select ATH79_DEV_LEDS_GPIO
+-	select ATH79_DEV_SPI
+-	select ATH79_DEV_USB
+-	select ATH79_DEV_WMAC
+-	help
+-	  Say 'Y' here if you want your kernel to support the
+-	  Atheros AP136 reference board.
+-
+-config ATH79_MACH_AP81
+-	bool "Atheros AP81 reference board"
+-	select SOC_AR913X
+-	select ATH79_DEV_GPIO_BUTTONS
+-	select ATH79_DEV_LEDS_GPIO
+-	select ATH79_DEV_SPI
+-	select ATH79_DEV_USB
+-	select ATH79_DEV_WMAC
+-	help
+-	  Say 'Y' here if you want your kernel to support the
+-	  Atheros AP81 reference board.
+-
+-config ATH79_MACH_DB120
+-	bool "Atheros DB120 reference board"
+-	select SOC_AR934X
+-	select ATH79_DEV_GPIO_BUTTONS
+-	select ATH79_DEV_LEDS_GPIO
+-	select ATH79_DEV_SPI
+-	select ATH79_DEV_USB
+-	select ATH79_DEV_WMAC
+-	help
+-	  Say 'Y' here if you want your kernel to support the
+-	  Atheros DB120 reference board.
+-
+-config ATH79_MACH_PB44
+-	bool "Atheros PB44 reference board"
+-	select SOC_AR71XX
+-	select ATH79_DEV_GPIO_BUTTONS
+-	select ATH79_DEV_LEDS_GPIO
+-	select ATH79_DEV_SPI
+-	select ATH79_DEV_USB
+-	help
+-	  Say 'Y' here if you want your kernel to support the
+-	  Atheros PB44 reference board.
+-
+-config ATH79_MACH_UBNT_XM
+-	bool "Ubiquiti Networks XM (rev 1.0) board"
+-	select SOC_AR724X
+-	select ATH79_DEV_GPIO_BUTTONS
+-	select ATH79_DEV_LEDS_GPIO
+-	select ATH79_DEV_SPI
+-	help
+-	  Say 'Y' here if you want your kernel to support the
+-	  Ubiquiti Networks XM (rev 1.0) board.
+-
+-endmenu
+-
+ config SOC_AR71XX
+ 	select HW_HAS_PCI
+ 	def_bool n
+--- a/arch/mips/ath79/Makefile
++++ b/arch/mips/ath79/Makefile
+@@ -22,13 +22,3 @@ obj-$(CONFIG_ATH79_DEV_LEDS_GPIO)	+= dev
+ obj-$(CONFIG_ATH79_DEV_SPI)		+= dev-spi.o
+ obj-$(CONFIG_ATH79_DEV_USB)		+= dev-usb.o
+ obj-$(CONFIG_ATH79_DEV_WMAC)		+= dev-wmac.o
+-
+-#
+-# Machines
+-#
+-obj-$(CONFIG_ATH79_MACH_AP121)		+= mach-ap121.o
+-obj-$(CONFIG_ATH79_MACH_AP136)		+= mach-ap136.o
+-obj-$(CONFIG_ATH79_MACH_AP81)		+= mach-ap81.o
+-obj-$(CONFIG_ATH79_MACH_DB120)		+= mach-db120.o
+-obj-$(CONFIG_ATH79_MACH_PB44)		+= mach-pb44.o
+-obj-$(CONFIG_ATH79_MACH_UBNT_XM)	+= mach-ubnt-xm.o
+--- a/arch/mips/ath79/clock.c
++++ b/arch/mips/ath79/clock.c
+@@ -26,7 +26,6 @@
+ #include <asm/mach-ath79/ath79.h>
+ #include <asm/mach-ath79/ar71xx_regs.h>
+ #include "common.h"
+-#include "machtypes.h"
+ 
+ #define AR71XX_BASE_FREQ	40000000
+ #define AR724X_BASE_FREQ	40000000
+--- a/arch/mips/ath79/mach-ap121.c
++++ /dev/null
+@@ -1,92 +0,0 @@
+-/*
+- *  Atheros AP121 board support
+- *
+- *  Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
+- *
+- *  This program 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.
+- */
+-
+-#include "machtypes.h"
+-#include "dev-gpio-buttons.h"
+-#include "dev-leds-gpio.h"
+-#include "dev-spi.h"
+-#include "dev-usb.h"
+-#include "dev-wmac.h"
+-
+-#define AP121_GPIO_LED_WLAN		0
+-#define AP121_GPIO_LED_USB		1
+-
+-#define AP121_GPIO_BTN_JUMPSTART	11
+-#define AP121_GPIO_BTN_RESET		12
+-
+-#define AP121_KEYS_POLL_INTERVAL	20	/* msecs */
+-#define AP121_KEYS_DEBOUNCE_INTERVAL	(3 * AP121_KEYS_POLL_INTERVAL)
+-
+-#define AP121_CAL_DATA_ADDR	0x1fff1000
+-
+-static struct gpio_led ap121_leds_gpio[] __initdata = {
+-	{
+-		.name		= "ap121:green:usb",
+-		.gpio		= AP121_GPIO_LED_USB,
+-		.active_low	= 0,
+-	},
+-	{
+-		.name		= "ap121:green:wlan",
+-		.gpio		= AP121_GPIO_LED_WLAN,
+-		.active_low	= 0,
+-	},
+-};
+-
+-static struct gpio_keys_button ap121_gpio_keys[] __initdata = {
+-	{
+-		.desc		= "jumpstart button",
+-		.type		= EV_KEY,
+-		.code		= KEY_WPS_BUTTON,
+-		.debounce_interval = AP121_KEYS_DEBOUNCE_INTERVAL,
+-		.gpio		= AP121_GPIO_BTN_JUMPSTART,
+-		.active_low	= 1,
+-	},
+-	{
+-		.desc		= "reset button",
+-		.type		= EV_KEY,
+-		.code		= KEY_RESTART,
+-		.debounce_interval = AP121_KEYS_DEBOUNCE_INTERVAL,
+-		.gpio		= AP121_GPIO_BTN_RESET,
+-		.active_low	= 1,
+-	}
+-};
+-
+-static struct spi_board_info ap121_spi_info[] = {
+-	{
+-		.bus_num	= 0,
+-		.chip_select	= 0,
+-		.max_speed_hz	= 25000000,
+-		.modalias	= "mx25l1606e",
+-	}
+-};
+-
+-static struct ath79_spi_platform_data ap121_spi_data = {
+-	.bus_num	= 0,
+-	.num_chipselect = 1,
+-};
+-
+-static void __init ap121_setup(void)
+-{
+-	u8 *cal_data = (u8 *) KSEG1ADDR(AP121_CAL_DATA_ADDR);
+-
+-	ath79_register_leds_gpio(-1, ARRAY_SIZE(ap121_leds_gpio),
+-				 ap121_leds_gpio);
+-	ath79_register_gpio_keys_polled(-1, AP121_KEYS_POLL_INTERVAL,
+-					ARRAY_SIZE(ap121_gpio_keys),
+-					ap121_gpio_keys);
+-
+-	ath79_register_spi(&ap121_spi_data, ap121_spi_info,
+-			   ARRAY_SIZE(ap121_spi_info));
+-	ath79_register_usb();
+-	ath79_register_wmac(cal_data);
+-}
+-
+-MIPS_MACHINE(ATH79_MACH_AP121, "AP121", "Atheros AP121 reference board",
+-	     ap121_setup);
+--- a/arch/mips/ath79/mach-ap136.c
++++ /dev/null
+@@ -1,156 +0,0 @@
+-/*
+- * Qualcomm Atheros AP136 reference board support
+- *
+- * Copyright (c) 2012 Qualcomm Atheros
+- * Copyright (c) 2012-2013 Gabor Juhos <juhosg@openwrt.org>
+- *
+- * Permission to use, copy, modify, and/or distribute this software for any
+- * purpose with or without fee is hereby granted, provided that the above
+- * copyright notice and this permission notice appear in all copies.
+- *
+- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+- *
+- */
+-
+-#include <linux/pci.h>
+-#include <linux/ath9k_platform.h>
+-
+-#include "machtypes.h"
+-#include "dev-gpio-buttons.h"
+-#include "dev-leds-gpio.h"
+-#include "dev-spi.h"
+-#include "dev-usb.h"
+-#include "dev-wmac.h"
+-#include "pci.h"
+-
+-#define AP136_GPIO_LED_STATUS_RED	14
+-#define AP136_GPIO_LED_STATUS_GREEN	19
+-#define AP136_GPIO_LED_USB		4
+-#define AP136_GPIO_LED_WLAN_2G		13
+-#define AP136_GPIO_LED_WLAN_5G		12
+-#define AP136_GPIO_LED_WPS_RED		15
+-#define AP136_GPIO_LED_WPS_GREEN	20
+-
+-#define AP136_GPIO_BTN_WPS		16
+-#define AP136_GPIO_BTN_RFKILL		21
+-
+-#define AP136_KEYS_POLL_INTERVAL	20	/* msecs */
+-#define AP136_KEYS_DEBOUNCE_INTERVAL	(3 * AP136_KEYS_POLL_INTERVAL)
+-
+-#define AP136_WMAC_CALDATA_OFFSET 0x1000
+-#define AP136_PCIE_CALDATA_OFFSET 0x5000
+-
+-static struct gpio_led ap136_leds_gpio[] __initdata = {
+-	{
+-		.name		= "qca:green:status",
+-		.gpio		= AP136_GPIO_LED_STATUS_GREEN,
+-		.active_low	= 1,
+-	},
+-	{
+-		.name		= "qca:red:status",
+-		.gpio		= AP136_GPIO_LED_STATUS_RED,
+-		.active_low	= 1,
+-	},
+-	{
+-		.name		= "qca:green:wps",
+-		.gpio		= AP136_GPIO_LED_WPS_GREEN,
+-		.active_low	= 1,
+-	},
+-	{
+-		.name		= "qca:red:wps",
+-		.gpio		= AP136_GPIO_LED_WPS_RED,
+-		.active_low	= 1,
+-	},
+-	{
+-		.name		= "qca:red:wlan-2g",
+-		.gpio		= AP136_GPIO_LED_WLAN_2G,
+-		.active_low	= 1,
+-	},
+-	{
+-		.name		= "qca:red:usb",
+-		.gpio		= AP136_GPIO_LED_USB,
+-		.active_low	= 1,
+-	}
+-};
+-
+-static struct gpio_keys_button ap136_gpio_keys[] __initdata = {
+-	{
+-		.desc		= "WPS button",
+-		.type		= EV_KEY,
+-		.code		= KEY_WPS_BUTTON,
+-		.debounce_interval = AP136_KEYS_DEBOUNCE_INTERVAL,
+-		.gpio		= AP136_GPIO_BTN_WPS,
+-		.active_low	= 1,
+-	},
+-	{
+-		.desc		= "RFKILL button",
+-		.type		= EV_KEY,
+-		.code		= KEY_RFKILL,
+-		.debounce_interval = AP136_KEYS_DEBOUNCE_INTERVAL,
+-		.gpio		= AP136_GPIO_BTN_RFKILL,
+-		.active_low	= 1,
+-	},
+-};
+-
+-static struct spi_board_info ap136_spi_info[] = {
+-	{
+-		.bus_num	= 0,
+-		.chip_select	= 0,
+-		.max_speed_hz	= 25000000,
+-		.modalias	= "mx25l6405d",
+-	}
+-};
+-
+-static struct ath79_spi_platform_data ap136_spi_data = {
+-	.bus_num	= 0,
+-	.num_chipselect	= 1,
+-};
+-
+-#ifdef CONFIG_PCI
+-static struct ath9k_platform_data ap136_ath9k_data;
+-
+-static int ap136_pci_plat_dev_init(struct pci_dev *dev)
+-{
+-	if (dev->bus->number == 1 && (PCI_SLOT(dev->devfn)) == 0)
+-		dev->dev.platform_data = &ap136_ath9k_data;
+-
+-	return 0;
+-}
+-
+-static void __init ap136_pci_init(u8 *eeprom)
+-{
+-	memcpy(ap136_ath9k_data.eeprom_data, eeprom,
+-	       sizeof(ap136_ath9k_data.eeprom_data));
+-
+-	ath79_pci_set_plat_dev_init(ap136_pci_plat_dev_init);
+-	ath79_register_pci();
+-}
+-#else
+-static inline void ap136_pci_init(u8 *eeprom) {}
+-#endif /* CONFIG_PCI */
+-
+-static void __init ap136_setup(void)
+-{
+-	u8 *art = (u8 *) KSEG1ADDR(0x1fff0000);
+-
+-	ath79_register_leds_gpio(-1, ARRAY_SIZE(ap136_leds_gpio),
+-				 ap136_leds_gpio);
+-	ath79_register_gpio_keys_polled(-1, AP136_KEYS_POLL_INTERVAL,
+-					ARRAY_SIZE(ap136_gpio_keys),
+-					ap136_gpio_keys);
+-	ath79_register_spi(&ap136_spi_data, ap136_spi_info,
+-			   ARRAY_SIZE(ap136_spi_info));
+-	ath79_register_usb();
+-	ath79_register_wmac(art + AP136_WMAC_CALDATA_OFFSET);
+-	ap136_pci_init(art + AP136_PCIE_CALDATA_OFFSET);
+-}
+-
+-MIPS_MACHINE(ATH79_MACH_AP136_010, "AP136-010",
+-	     "Atheros AP136-010 reference board",
+-	     ap136_setup);
+--- a/arch/mips/ath79/mach-ap81.c
++++ /dev/null
+@@ -1,100 +0,0 @@
+-/*
+- *  Atheros AP81 board support
+- *
+- *  Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org>
+- *  Copyright (C) 2009 Imre Kaloz <kaloz@openwrt.org>
+- *
+- *  This program 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.
+- */
+-
+-#include "machtypes.h"
+-#include "dev-wmac.h"
+-#include "dev-gpio-buttons.h"
+-#include "dev-leds-gpio.h"
+-#include "dev-spi.h"
+-#include "dev-usb.h"
+-
+-#define AP81_GPIO_LED_STATUS	1
+-#define AP81_GPIO_LED_AOSS	3
+-#define AP81_GPIO_LED_WLAN	6
+-#define AP81_GPIO_LED_POWER	14
+-
+-#define AP81_GPIO_BTN_SW4	12
+-#define AP81_GPIO_BTN_SW1	21
+-
+-#define AP81_KEYS_POLL_INTERVAL		20	/* msecs */
+-#define AP81_KEYS_DEBOUNCE_INTERVAL	(3 * AP81_KEYS_POLL_INTERVAL)
+-
+-#define AP81_CAL_DATA_ADDR	0x1fff1000
+-
+-static struct gpio_led ap81_leds_gpio[] __initdata = {
+-	{
+-		.name		= "ap81:green:status",
+-		.gpio		= AP81_GPIO_LED_STATUS,
+-		.active_low	= 1,
+-	}, {
+-		.name		= "ap81:amber:aoss",
+-		.gpio		= AP81_GPIO_LED_AOSS,
+-		.active_low	= 1,
+-	}, {
+-		.name		= "ap81:green:wlan",
+-		.gpio		= AP81_GPIO_LED_WLAN,
+-		.active_low	= 1,
+-	}, {
+-		.name		= "ap81:green:power",
+-		.gpio		= AP81_GPIO_LED_POWER,
+-		.active_low	= 1,
+-	}
+-};
+-
+-static struct gpio_keys_button ap81_gpio_keys[] __initdata = {
+-	{
+-		.desc		= "sw1",
+-		.type		= EV_KEY,
+-		.code		= BTN_0,
+-		.debounce_interval = AP81_KEYS_DEBOUNCE_INTERVAL,
+-		.gpio		= AP81_GPIO_BTN_SW1,
+-		.active_low	= 1,
+-	} , {
+-		.desc		= "sw4",
+-		.type		= EV_KEY,
+-		.code		= BTN_1,
+-		.debounce_interval = AP81_KEYS_DEBOUNCE_INTERVAL,
+-		.gpio		= AP81_GPIO_BTN_SW4,
+-		.active_low	= 1,
+-	}
+-};
+-
+-static struct spi_board_info ap81_spi_info[] = {
+-	{
+-		.bus_num	= 0,
+-		.chip_select	= 0,
+-		.max_speed_hz	= 25000000,
+-		.modalias	= "m25p64",
+-	}
+-};
+-
+-static struct ath79_spi_platform_data ap81_spi_data = {
+-	.bus_num	= 0,
+-	.num_chipselect = 1,
+-};
+-
+-static void __init ap81_setup(void)
+-{
+-	u8 *cal_data = (u8 *) KSEG1ADDR(AP81_CAL_DATA_ADDR);
+-
+-	ath79_register_leds_gpio(-1, ARRAY_SIZE(ap81_leds_gpio),
+-				 ap81_leds_gpio);
+-	ath79_register_gpio_keys_polled(-1, AP81_KEYS_POLL_INTERVAL,
+-					ARRAY_SIZE(ap81_gpio_keys),
+-					ap81_gpio_keys);
+-	ath79_register_spi(&ap81_spi_data, ap81_spi_info,
+-			   ARRAY_SIZE(ap81_spi_info));
+-	ath79_register_wmac(cal_data);
+-	ath79_register_usb();
+-}
+-
+-MIPS_MACHINE(ATH79_MACH_AP81, "AP81", "Atheros AP81 reference board",
+-	     ap81_setup);
+--- a/arch/mips/ath79/mach-db120.c
++++ /dev/null
+@@ -1,136 +0,0 @@
+-/*
+- * Atheros DB120 reference board support
+- *
+- * Copyright (c) 2011 Qualcomm Atheros
+- * Copyright (c) 2011 Gabor Juhos <juhosg@openwrt.org>
+- *
+- * Permission to use, copy, modify, and/or distribute this software for any
+- * purpose with or without fee is hereby granted, provided that the above
+- * copyright notice and this permission notice appear in all copies.
+- *
+- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+- *
+- */
+-
+-#include <linux/pci.h>
+-#include <linux/ath9k_platform.h>
+-
+-#include "machtypes.h"
+-#include "dev-gpio-buttons.h"
+-#include "dev-leds-gpio.h"
+-#include "dev-spi.h"
+-#include "dev-usb.h"
+-#include "dev-wmac.h"
+-#include "pci.h"
+-
+-#define DB120_GPIO_LED_WLAN_5G		12
+-#define DB120_GPIO_LED_WLAN_2G		13
+-#define DB120_GPIO_LED_STATUS		14
+-#define DB120_GPIO_LED_WPS		15
+-
+-#define DB120_GPIO_BTN_WPS		16
+-
+-#define DB120_KEYS_POLL_INTERVAL	20	/* msecs */
+-#define DB120_KEYS_DEBOUNCE_INTERVAL	(3 * DB120_KEYS_POLL_INTERVAL)
+-
+-#define DB120_WMAC_CALDATA_OFFSET 0x1000
+-#define DB120_PCIE_CALDATA_OFFSET 0x5000
+-
+-static struct gpio_led db120_leds_gpio[] __initdata = {
+-	{
+-		.name		= "db120:green:status",
+-		.gpio		= DB120_GPIO_LED_STATUS,
+-		.active_low	= 1,
+-	},
+-	{
+-		.name		= "db120:green:wps",
+-		.gpio		= DB120_GPIO_LED_WPS,
+-		.active_low	= 1,
+-	},
+-	{
+-		.name		= "db120:green:wlan-5g",
+-		.gpio		= DB120_GPIO_LED_WLAN_5G,
+-		.active_low	= 1,
+-	},
+-	{
+-		.name		= "db120:green:wlan-2g",
+-		.gpio		= DB120_GPIO_LED_WLAN_2G,
+-		.active_low	= 1,
+-	},
+-};
+-
+-static struct gpio_keys_button db120_gpio_keys[] __initdata = {
+-	{
+-		.desc		= "WPS button",
+-		.type		= EV_KEY,
+-		.code		= KEY_WPS_BUTTON,
+-		.debounce_interval = DB120_KEYS_DEBOUNCE_INTERVAL,
+-		.gpio		= DB120_GPIO_BTN_WPS,
+-		.active_low	= 1,
+-	},
+-};
+-
+-static struct spi_board_info db120_spi_info[] = {
+-	{
+-		.bus_num	= 0,
+-		.chip_select	= 0,
+-		.max_speed_hz	= 25000000,
+-		.modalias	= "s25sl064a",
+-	}
+-};
+-
+-static struct ath79_spi_platform_data db120_spi_data = {
+-	.bus_num	= 0,
+-	.num_chipselect = 1,
+-};
+-
+-#ifdef CONFIG_PCI
+-static struct ath9k_platform_data db120_ath9k_data;
+-
+-static int db120_pci_plat_dev_init(struct pci_dev *dev)
+-{
+-	switch (PCI_SLOT(dev->devfn)) {
+-	case 0:
+-		dev->dev.platform_data = &db120_ath9k_data;
+-		break;
+-	}
+-
+-	return 0;
+-}
+-
+-static void __init db120_pci_init(u8 *eeprom)
+-{
+-	memcpy(db120_ath9k_data.eeprom_data, eeprom,
+-	       sizeof(db120_ath9k_data.eeprom_data));
+-
+-	ath79_pci_set_plat_dev_init(db120_pci_plat_dev_init);
+-	ath79_register_pci();
+-}
+-#else
+-static inline void db120_pci_init(u8 *eeprom) {}
+-#endif /* CONFIG_PCI */
+-
+-static void __init db120_setup(void)
+-{
+-	u8 *art = (u8 *) KSEG1ADDR(0x1fff0000);
+-
+-	ath79_register_leds_gpio(-1, ARRAY_SIZE(db120_leds_gpio),
+-				 db120_leds_gpio);
+-	ath79_register_gpio_keys_polled(-1, DB120_KEYS_POLL_INTERVAL,
+-					ARRAY_SIZE(db120_gpio_keys),
+-					db120_gpio_keys);
+-	ath79_register_spi(&db120_spi_data, db120_spi_info,
+-			   ARRAY_SIZE(db120_spi_info));
+-	ath79_register_usb();
+-	ath79_register_wmac(art + DB120_WMAC_CALDATA_OFFSET);
+-	db120_pci_init(art + DB120_PCIE_CALDATA_OFFSET);
+-}
+-
+-MIPS_MACHINE(ATH79_MACH_DB120, "DB120", "Atheros DB120 reference board",
+-	     db120_setup);
+--- a/arch/mips/ath79/mach-pb44.c
++++ /dev/null
+@@ -1,128 +0,0 @@
+-/*
+- *  Atheros PB44 reference board support
+- *
+- *  Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org>
+- *
+- *  This program 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.
+- */
+-
+-#include <linux/init.h>
+-#include <linux/platform_device.h>
+-#include <linux/i2c.h>
+-#include <linux/gpio/machine.h>
+-#include <linux/platform_data/pcf857x.h>
+-
+-#include "machtypes.h"
+-#include "dev-gpio-buttons.h"
+-#include "dev-leds-gpio.h"
+-#include "dev-spi.h"
+-#include "dev-usb.h"
+-#include "pci.h"
+-
+-#define PB44_GPIO_I2C_SCL	0
+-#define PB44_GPIO_I2C_SDA	1
+-
+-#define PB44_GPIO_EXP_BASE	16
+-#define PB44_GPIO_SW_RESET	(PB44_GPIO_EXP_BASE + 6)
+-#define PB44_GPIO_SW_JUMP	(PB44_GPIO_EXP_BASE + 8)
+-#define PB44_GPIO_LED_JUMP1	(PB44_GPIO_EXP_BASE + 9)
+-#define PB44_GPIO_LED_JUMP2	(PB44_GPIO_EXP_BASE + 10)
+-
+-#define PB44_KEYS_POLL_INTERVAL		20	/* msecs */
+-#define PB44_KEYS_DEBOUNCE_INTERVAL	(3 * PB44_KEYS_POLL_INTERVAL)
+-
+-static struct gpiod_lookup_table pb44_i2c_gpiod_table = {
+-	.dev_id = "i2c-gpio.0",
+-	.table = {
+-		GPIO_LOOKUP_IDX("ath79-gpio", PB44_GPIO_I2C_SDA,
+-				NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+-		GPIO_LOOKUP_IDX("ath79-gpio", PB44_GPIO_I2C_SCL,
+-				NULL, 1, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+-	},
+-};
+-
+-static struct platform_device pb44_i2c_gpio_device = {
+-	.name		= "i2c-gpio",
+-	.id		= 0,
+-	.dev = {
+-		.platform_data	= NULL,
+-	}
+-};
+-
+-static struct pcf857x_platform_data pb44_pcf857x_data = {
+-	.gpio_base	= PB44_GPIO_EXP_BASE,
+-};
+-
+-static struct i2c_board_info pb44_i2c_board_info[] __initdata = {
+-	{
+-		I2C_BOARD_INFO("pcf8575", 0x20),
+-		.platform_data	= &pb44_pcf857x_data,
+-	},
+-};
+-
+-static struct gpio_led pb44_leds_gpio[] __initdata = {
+-	{
+-		.name		= "pb44:amber:jump1",
+-		.gpio		= PB44_GPIO_LED_JUMP1,
+-		.active_low	= 1,
+-	}, {
+-		.name		= "pb44:green:jump2",
+-		.gpio		= PB44_GPIO_LED_JUMP2,
+-		.active_low	= 1,
+-	},
+-};
+-
+-static struct gpio_keys_button pb44_gpio_keys[] __initdata = {
+-	{
+-		.desc		= "soft_reset",
+-		.type		= EV_KEY,
+-		.code		= KEY_RESTART,
+-		.debounce_interval = PB44_KEYS_DEBOUNCE_INTERVAL,
+-		.gpio		= PB44_GPIO_SW_RESET,
+-		.active_low	= 1,
+-	} , {
+-		.desc		= "jumpstart",
+-		.type		= EV_KEY,
+-		.code		= KEY_WPS_BUTTON,
+-		.debounce_interval = PB44_KEYS_DEBOUNCE_INTERVAL,
+-		.gpio		= PB44_GPIO_SW_JUMP,
+-		.active_low	= 1,
+-	}
+-};
+-
+-static struct spi_board_info pb44_spi_info[] = {
+-	{
+-		.bus_num	= 0,
+-		.chip_select	= 0,
+-		.max_speed_hz	= 25000000,
+-		.modalias	= "m25p64",
+-	},
+-};
+-
+-static struct ath79_spi_platform_data pb44_spi_data = {
+-	.bus_num		= 0,
+-	.num_chipselect		= 1,
+-};
+-
+-static void __init pb44_init(void)
+-{
+-	gpiod_add_lookup_table(&pb44_i2c_gpiod_table);
+-	i2c_register_board_info(0, pb44_i2c_board_info,
+-				ARRAY_SIZE(pb44_i2c_board_info));
+-	platform_device_register(&pb44_i2c_gpio_device);
+-
+-	ath79_register_leds_gpio(-1, ARRAY_SIZE(pb44_leds_gpio),
+-				 pb44_leds_gpio);
+-	ath79_register_gpio_keys_polled(-1, PB44_KEYS_POLL_INTERVAL,
+-					ARRAY_SIZE(pb44_gpio_keys),
+-					pb44_gpio_keys);
+-	ath79_register_spi(&pb44_spi_data, pb44_spi_info,
+-			   ARRAY_SIZE(pb44_spi_info));
+-	ath79_register_usb();
+-	ath79_register_pci();
+-}
+-
+-MIPS_MACHINE(ATH79_MACH_PB44, "PB44", "Atheros PB44 reference board",
+-	     pb44_init);
+--- a/arch/mips/ath79/mach-ubnt-xm.c
++++ /dev/null
+@@ -1,126 +0,0 @@
+-/*
+- *  Ubiquiti Networks XM (rev 1.0) board support
+- *
+- *  Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com>
+- *
+- *  Derived from: mach-pb44.c
+- *
+- *  This program 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.
+- */
+-
+-#include <linux/init.h>
+-#include <linux/pci.h>
+-#include <linux/ath9k_platform.h>
+-
+-#include <asm/mach-ath79/irq.h>
+-
+-#include "machtypes.h"
+-#include "dev-gpio-buttons.h"
+-#include "dev-leds-gpio.h"
+-#include "dev-spi.h"
+-#include "pci.h"
+-
+-#define UBNT_XM_GPIO_LED_L1		0
+-#define UBNT_XM_GPIO_LED_L2		1
+-#define UBNT_XM_GPIO_LED_L3		11
+-#define UBNT_XM_GPIO_LED_L4		7
+-
+-#define UBNT_XM_GPIO_BTN_RESET		12
+-
+-#define UBNT_XM_KEYS_POLL_INTERVAL	20
+-#define UBNT_XM_KEYS_DEBOUNCE_INTERVAL	(3 * UBNT_XM_KEYS_POLL_INTERVAL)
+-
+-#define UBNT_XM_EEPROM_ADDR		(u8 *) KSEG1ADDR(0x1fff1000)
+-
+-static struct gpio_led ubnt_xm_leds_gpio[] __initdata = {
+-	{
+-		.name		= "ubnt-xm:red:link1",
+-		.gpio		= UBNT_XM_GPIO_LED_L1,
+-		.active_low	= 0,
+-	}, {
+-		.name		= "ubnt-xm:orange:link2",
+-		.gpio		= UBNT_XM_GPIO_LED_L2,
+-		.active_low	= 0,
+-	}, {
+-		.name		= "ubnt-xm:green:link3",
+-		.gpio		= UBNT_XM_GPIO_LED_L3,
+-		.active_low	= 0,
+-	}, {
+-		.name		= "ubnt-xm:green:link4",
+-		.gpio		= UBNT_XM_GPIO_LED_L4,
+-		.active_low	= 0,
+-	},
+-};
+-
+-static struct gpio_keys_button ubnt_xm_gpio_keys[] __initdata = {
+-	{
+-		.desc			= "reset",
+-		.type			= EV_KEY,
+-		.code			= KEY_RESTART,
+-		.debounce_interval	= UBNT_XM_KEYS_DEBOUNCE_INTERVAL,
+-		.gpio			= UBNT_XM_GPIO_BTN_RESET,
+-		.active_low		= 1,
+-	}
+-};
+-
+-static struct spi_board_info ubnt_xm_spi_info[] = {
+-	{
+-		.bus_num	= 0,
+-		.chip_select	= 0,
+-		.max_speed_hz	= 25000000,
+-		.modalias	= "mx25l6405d",
+-	}
+-};
+-
+-static struct ath79_spi_platform_data ubnt_xm_spi_data = {
+-	.bus_num		= 0,
+-	.num_chipselect		= 1,
+-};
+-
+-#ifdef CONFIG_PCI
+-static struct ath9k_platform_data ubnt_xm_eeprom_data;
+-
+-static int ubnt_xm_pci_plat_dev_init(struct pci_dev *dev)
+-{
+-	switch (PCI_SLOT(dev->devfn)) {
+-	case 0:
+-		dev->dev.platform_data = &ubnt_xm_eeprom_data;
+-		break;
+-	}
+-
+-	return 0;
+-}
+-
+-static void __init ubnt_xm_pci_init(void)
+-{
+-	memcpy(ubnt_xm_eeprom_data.eeprom_data, UBNT_XM_EEPROM_ADDR,
+-	       sizeof(ubnt_xm_eeprom_data.eeprom_data));
+-
+-	ath79_pci_set_plat_dev_init(ubnt_xm_pci_plat_dev_init);
+-	ath79_register_pci();
+-}
+-#else
+-static inline void ubnt_xm_pci_init(void) {}
+-#endif /* CONFIG_PCI */
+-
+-static void __init ubnt_xm_init(void)
+-{
+-	ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_xm_leds_gpio),
+-				 ubnt_xm_leds_gpio);
+-
+-	ath79_register_gpio_keys_polled(-1, UBNT_XM_KEYS_POLL_INTERVAL,
+-					ARRAY_SIZE(ubnt_xm_gpio_keys),
+-					ubnt_xm_gpio_keys);
+-
+-	ath79_register_spi(&ubnt_xm_spi_data, ubnt_xm_spi_info,
+-			   ARRAY_SIZE(ubnt_xm_spi_info));
+-
+-	ubnt_xm_pci_init();
+-}
+-
+-MIPS_MACHINE(ATH79_MACH_UBNT_XM,
+-	     "UBNT-XM",
+-	     "Ubiquiti Networks XM (rev 1.0) board",
+-	     ubnt_xm_init);
+--- a/arch/mips/ath79/machtypes.h
++++ /dev/null
+@@ -1,28 +0,0 @@
+-/*
+- *  Atheros AR71XX/AR724X/AR913X machine type definitions
+- *
+- *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+- *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+- *
+- *  This program 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.
+- */
+-
+-#ifndef _ATH79_MACHTYPE_H
+-#define _ATH79_MACHTYPE_H
+-
+-#include <asm/mips_machine.h>
+-
+-enum ath79_mach_type {
+-	ATH79_MACH_GENERIC_OF = -1,	/* Device tree board */
+-	ATH79_MACH_GENERIC = 0,
+-	ATH79_MACH_AP121,		/* Atheros AP121 reference board */
+-	ATH79_MACH_AP136_010,		/* Atheros AP136-010 reference board */
+-	ATH79_MACH_AP81,		/* Atheros AP81 reference board */
+-	ATH79_MACH_DB120,		/* Atheros DB120 reference board */
+-	ATH79_MACH_PB44,		/* Atheros PB44 reference board */
+-	ATH79_MACH_UBNT_XM,		/* Ubiquiti Networks XM board rev 1.0 */
+-};
+-
+-#endif /* _ATH79_MACHTYPE_H */
+--- a/arch/mips/ath79/setup.c
++++ b/arch/mips/ath79/setup.c
+@@ -33,7 +33,6 @@
+ #include <asm/mach-ath79/ar71xx_regs.h>
+ #include "common.h"
+ #include "dev-common.h"
+-#include "machtypes.h"
+ 
+ #define ATH79_SYS_TYPE_LEN	64
+ 
+@@ -236,25 +235,21 @@ void __init plat_mem_setup(void)
+ 	else if (fw_passed_dtb)
+ 		__dt_setup_arch((void *)KSEG0ADDR(fw_passed_dtb));
+ 
+-	if (mips_machtype != ATH79_MACH_GENERIC_OF) {
+-		ath79_reset_base = ioremap_nocache(AR71XX_RESET_BASE,
+-						   AR71XX_RESET_SIZE);
+-		ath79_pll_base = ioremap_nocache(AR71XX_PLL_BASE,
+-						 AR71XX_PLL_SIZE);
+-		ath79_detect_sys_type();
+-		ath79_ddr_ctrl_init();
++	ath79_reset_base = ioremap_nocache(AR71XX_RESET_BASE,
++					   AR71XX_RESET_SIZE);
++	ath79_pll_base = ioremap_nocache(AR71XX_PLL_BASE,
++					 AR71XX_PLL_SIZE);
++	ath79_detect_sys_type();
++	ath79_ddr_ctrl_init();
+ 
+-		detect_memory_region(0, ATH79_MEM_SIZE_MIN, ATH79_MEM_SIZE_MAX);
+-
+-		/* OF machines should use the reset driver */
+-		_machine_restart = ath79_restart;
+-	}
++	detect_memory_region(0, ATH79_MEM_SIZE_MIN, ATH79_MEM_SIZE_MAX);
+ 
++	_machine_restart = ath79_restart;
+ 	_machine_halt = ath79_halt;
+ 	pm_power_off = ath79_halt;
+ }
+ 
+-static void __init ath79_of_plat_time_init(void)
++void __init plat_time_init(void)
+ {
+ 	struct device_node *np;
+ 	struct clk *clk;
+@@ -284,66 +279,12 @@ static void __init ath79_of_plat_time_in
+ 	clk_put(clk);
+ }
+ 
+-void __init plat_time_init(void)
+-{
+-	unsigned long cpu_clk_rate;
+-	unsigned long ahb_clk_rate;
+-	unsigned long ddr_clk_rate;
+-	unsigned long ref_clk_rate;
+-
+-	if (IS_ENABLED(CONFIG_OF) && mips_machtype == ATH79_MACH_GENERIC_OF) {
+-		ath79_of_plat_time_init();
+-		return;
+-	}
+-
+-	ath79_clocks_init();
+-
+-	cpu_clk_rate = ath79_get_sys_clk_rate("cpu");
+-	ahb_clk_rate = ath79_get_sys_clk_rate("ahb");
+-	ddr_clk_rate = ath79_get_sys_clk_rate("ddr");
+-	ref_clk_rate = ath79_get_sys_clk_rate("ref");
+-
+-	pr_info("Clocks: CPU:%lu.%03luMHz, DDR:%lu.%03luMHz, AHB:%lu.%03luMHz, Ref:%lu.%03luMHz\n",
+-		cpu_clk_rate / 1000000, (cpu_clk_rate / 1000) % 1000,
+-		ddr_clk_rate / 1000000, (ddr_clk_rate / 1000) % 1000,
+-		ahb_clk_rate / 1000000, (ahb_clk_rate / 1000) % 1000,
+-		ref_clk_rate / 1000000, (ref_clk_rate / 1000) % 1000);
+-
+-	mips_hpt_frequency = cpu_clk_rate / 2;
+-}
+-
+ void __init arch_init_irq(void)
+ {
+ 	irqchip_init();
+ }
+ 
+-static int __init ath79_setup(void)
+-{
+-	if  (mips_machtype == ATH79_MACH_GENERIC_OF)
+-		return 0;
+-
+-	ath79_gpio_init();
+-	ath79_register_uart();
+-	ath79_register_wdt();
+-
+-	mips_machine_setup();
+-
+-	return 0;
+-}
+-
+-arch_initcall(ath79_setup);
+-
+ void __init device_tree_init(void)
+ {
+ 	unflatten_and_copy_device_tree();
+ }
+-
+-MIPS_MACHINE(ATH79_MACH_GENERIC,
+-	     "Generic",
+-	     "Generic AR71XX/AR724X/AR913X based board",
+-	     NULL);
+-
+-MIPS_MACHINE(ATH79_MACH_GENERIC_OF,
+-	     "DTB",
+-	     "Generic AR71XX/AR724X/AR913X based board (DT)",
+-	     NULL);
diff --git a/target/linux/ath79/patches-4.19/0029-MIPS-ath79-drop-legacy-pci-code.patch b/target/linux/ath79/patches-4.19/0029-MIPS-ath79-drop-legacy-pci-code.patch
new file mode 100644
index 00000000000..254f2f92534
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/0029-MIPS-ath79-drop-legacy-pci-code.patch
@@ -0,0 +1,379 @@
+From d0f1420702ed47a82572aaf39e7407055518d14e Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Sat, 23 Jun 2018 15:05:19 +0200
+Subject: [PATCH 29/33] MIPS: ath79: drop legacy pci code
+
+With the target now being fully OF based, we can drop the legacy pci
+platform code. The only bits that we need to keep is the fixup code
+which we move to its own code file.
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ arch/mips/ath79/Makefile    |   1 -
+ arch/mips/ath79/pci.c       | 273 --------------------------------------------
+ arch/mips/ath79/pci.h       |  35 ------
+ arch/mips/pci/Makefile      |   1 +
+ arch/mips/pci/fixup-ath79.c |  21 ++++
+ 5 files changed, 22 insertions(+), 309 deletions(-)
+ delete mode 100644 arch/mips/ath79/pci.c
+ delete mode 100644 arch/mips/ath79/pci.h
+ create mode 100644 arch/mips/pci/fixup-ath79.c
+
+--- a/arch/mips/ath79/Makefile
++++ b/arch/mips/ath79/Makefile
+@@ -11,7 +11,6 @@
+ obj-y	:= prom.o setup.o common.o clock.o
+ 
+ obj-$(CONFIG_EARLY_PRINTK)		+= early_printk.o
+-obj-$(CONFIG_PCI)			+= pci.o
+ 
+ #
+ # Devices
+--- a/arch/mips/ath79/pci.c
++++ /dev/null
+@@ -1,273 +0,0 @@
+-/*
+- *  Atheros AR71XX/AR724X specific PCI setup code
+- *
+- *  Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com>
+- *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
+- *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+- *
+- *  Parts of this file are based on Atheros' 2.6.15 BSP
+- *
+- *  This program 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.
+- */
+-
+-#include <linux/init.h>
+-#include <linux/pci.h>
+-#include <linux/resource.h>
+-#include <linux/platform_device.h>
+-#include <asm/mach-ath79/ar71xx_regs.h>
+-#include <asm/mach-ath79/ath79.h>
+-#include <asm/mach-ath79/irq.h>
+-#include "pci.h"
+-
+-static int (*ath79_pci_plat_dev_init)(struct pci_dev *dev);
+-static const struct ath79_pci_irq *ath79_pci_irq_map;
+-static unsigned ath79_pci_nr_irqs;
+-
+-static const struct ath79_pci_irq ar71xx_pci_irq_map[] = {
+-	{
+-		.slot	= 17,
+-		.pin	= 1,
+-		.irq	= ATH79_PCI_IRQ(0),
+-	}, {
+-		.slot	= 18,
+-		.pin	= 1,
+-		.irq	= ATH79_PCI_IRQ(1),
+-	}, {
+-		.slot	= 19,
+-		.pin	= 1,
+-		.irq	= ATH79_PCI_IRQ(2),
+-	}
+-};
+-
+-static const struct ath79_pci_irq ar724x_pci_irq_map[] = {
+-	{
+-		.slot	= 0,
+-		.pin	= 1,
+-		.irq	= ATH79_PCI_IRQ(0),
+-	}
+-};
+-
+-static const struct ath79_pci_irq qca955x_pci_irq_map[] = {
+-	{
+-		.bus	= 0,
+-		.slot	= 0,
+-		.pin	= 1,
+-		.irq	= ATH79_PCI_IRQ(0),
+-	},
+-	{
+-		.bus	= 1,
+-		.slot	= 0,
+-		.pin	= 1,
+-		.irq	= ATH79_PCI_IRQ(1),
+-	},
+-};
+-
+-int pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin)
+-{
+-	int irq = -1;
+-	int i;
+-
+-	if (ath79_pci_nr_irqs == 0 ||
+-	    ath79_pci_irq_map == NULL) {
+-		if (soc_is_ar71xx()) {
+-			ath79_pci_irq_map = ar71xx_pci_irq_map;
+-			ath79_pci_nr_irqs = ARRAY_SIZE(ar71xx_pci_irq_map);
+-		} else if (soc_is_ar724x() ||
+-			   soc_is_ar9342() ||
+-			   soc_is_ar9344()) {
+-			ath79_pci_irq_map = ar724x_pci_irq_map;
+-			ath79_pci_nr_irqs = ARRAY_SIZE(ar724x_pci_irq_map);
+-		} else if (soc_is_qca955x()) {
+-			ath79_pci_irq_map = qca955x_pci_irq_map;
+-			ath79_pci_nr_irqs = ARRAY_SIZE(qca955x_pci_irq_map);
+-		} else {
+-			pr_crit("pci %s: invalid irq map\n",
+-				pci_name((struct pci_dev *) dev));
+-			return irq;
+-		}
+-	}
+-
+-	for (i = 0; i < ath79_pci_nr_irqs; i++) {
+-		const struct ath79_pci_irq *entry;
+-
+-		entry = &ath79_pci_irq_map[i];
+-		if (entry->bus == dev->bus->number &&
+-		    entry->slot == slot &&
+-		    entry->pin == pin) {
+-			irq = entry->irq;
+-			break;
+-		}
+-	}
+-
+-	if (irq < 0)
+-		pr_crit("pci %s: no irq found for pin %u\n",
+-			pci_name((struct pci_dev *) dev), pin);
+-	else
+-		pr_info("pci %s: using irq %d for pin %u\n",
+-			pci_name((struct pci_dev *) dev), irq, pin);
+-
+-	return irq;
+-}
+-
+-int pcibios_plat_dev_init(struct pci_dev *dev)
+-{
+-	if (ath79_pci_plat_dev_init)
+-		return ath79_pci_plat_dev_init(dev);
+-
+-	return 0;
+-}
+-
+-void __init ath79_pci_set_irq_map(unsigned nr_irqs,
+-				  const struct ath79_pci_irq *map)
+-{
+-	ath79_pci_nr_irqs = nr_irqs;
+-	ath79_pci_irq_map = map;
+-}
+-
+-void __init ath79_pci_set_plat_dev_init(int (*func)(struct pci_dev *dev))
+-{
+-	ath79_pci_plat_dev_init = func;
+-}
+-
+-static struct platform_device *
+-ath79_register_pci_ar71xx(void)
+-{
+-	struct platform_device *pdev;
+-	struct resource res[4];
+-
+-	memset(res, 0, sizeof(res));
+-
+-	res[0].name = "cfg_base";
+-	res[0].flags = IORESOURCE_MEM;
+-	res[0].start = AR71XX_PCI_CFG_BASE;
+-	res[0].end = AR71XX_PCI_CFG_BASE + AR71XX_PCI_CFG_SIZE - 1;
+-
+-	res[1].flags = IORESOURCE_IRQ;
+-	res[1].start = ATH79_CPU_IRQ(2);
+-	res[1].end = ATH79_CPU_IRQ(2);
+-
+-	res[2].name = "io_base";
+-	res[2].flags = IORESOURCE_IO;
+-	res[2].start = 0;
+-	res[2].end = 0;
+-
+-	res[3].name = "mem_base";
+-	res[3].flags = IORESOURCE_MEM;
+-	res[3].start = AR71XX_PCI_MEM_BASE;
+-	res[3].end = AR71XX_PCI_MEM_BASE + AR71XX_PCI_MEM_SIZE - 1;
+-
+-	pdev = platform_device_register_simple("ar71xx-pci", -1,
+-					       res, ARRAY_SIZE(res));
+-	return pdev;
+-}
+-
+-static struct platform_device *
+-ath79_register_pci_ar724x(int id,
+-			  unsigned long cfg_base,
+-			  unsigned long ctrl_base,
+-			  unsigned long crp_base,
+-			  unsigned long mem_base,
+-			  unsigned long mem_size,
+-			  unsigned long io_base,
+-			  int irq)
+-{
+-	struct platform_device *pdev;
+-	struct resource res[6];
+-
+-	memset(res, 0, sizeof(res));
+-
+-	res[0].name = "cfg_base";
+-	res[0].flags = IORESOURCE_MEM;
+-	res[0].start = cfg_base;
+-	res[0].end = cfg_base + AR724X_PCI_CFG_SIZE - 1;
+-
+-	res[1].name = "ctrl_base";
+-	res[1].flags = IORESOURCE_MEM;
+-	res[1].start = ctrl_base;
+-	res[1].end = ctrl_base + AR724X_PCI_CTRL_SIZE - 1;
+-
+-	res[2].flags = IORESOURCE_IRQ;
+-	res[2].start = irq;
+-	res[2].end = irq;
+-
+-	res[3].name = "mem_base";
+-	res[3].flags = IORESOURCE_MEM;
+-	res[3].start = mem_base;
+-	res[3].end = mem_base + mem_size - 1;
+-
+-	res[4].name = "io_base";
+-	res[4].flags = IORESOURCE_IO;
+-	res[4].start = io_base;
+-	res[4].end = io_base;
+-
+-	res[5].name = "crp_base";
+-	res[5].flags = IORESOURCE_MEM;
+-	res[5].start = crp_base;
+-	res[5].end = crp_base + AR724X_PCI_CRP_SIZE - 1;
+-
+-	pdev = platform_device_register_simple("ar724x-pci", id,
+-					       res, ARRAY_SIZE(res));
+-	return pdev;
+-}
+-
+-int __init ath79_register_pci(void)
+-{
+-	struct platform_device *pdev = NULL;
+-
+-	if (soc_is_ar71xx()) {
+-		pdev = ath79_register_pci_ar71xx();
+-	} else if (soc_is_ar724x()) {
+-		pdev = ath79_register_pci_ar724x(-1,
+-						 AR724X_PCI_CFG_BASE,
+-						 AR724X_PCI_CTRL_BASE,
+-						 AR724X_PCI_CRP_BASE,
+-						 AR724X_PCI_MEM_BASE,
+-						 AR724X_PCI_MEM_SIZE,
+-						 0,
+-						 ATH79_CPU_IRQ(2));
+-	} else if (soc_is_ar9342() ||
+-		   soc_is_ar9344()) {
+-		u32 bootstrap;
+-
+-		bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP);
+-		if ((bootstrap & AR934X_BOOTSTRAP_PCIE_RC) == 0)
+-			return -ENODEV;
+-
+-		pdev = ath79_register_pci_ar724x(-1,
+-						 AR724X_PCI_CFG_BASE,
+-						 AR724X_PCI_CTRL_BASE,
+-						 AR724X_PCI_CRP_BASE,
+-						 AR724X_PCI_MEM_BASE,
+-						 AR724X_PCI_MEM_SIZE,
+-						 0,
+-						 ATH79_IP2_IRQ(0));
+-	} else if (soc_is_qca9558()) {
+-		pdev = ath79_register_pci_ar724x(0,
+-						 QCA955X_PCI_CFG_BASE0,
+-						 QCA955X_PCI_CTRL_BASE0,
+-						 QCA955X_PCI_CRP_BASE0,
+-						 QCA955X_PCI_MEM_BASE0,
+-						 QCA955X_PCI_MEM_SIZE,
+-						 0,
+-						 ATH79_IP2_IRQ(0));
+-
+-		pdev = ath79_register_pci_ar724x(1,
+-						 QCA955X_PCI_CFG_BASE1,
+-						 QCA955X_PCI_CTRL_BASE1,
+-						 QCA955X_PCI_CRP_BASE1,
+-						 QCA955X_PCI_MEM_BASE1,
+-						 QCA955X_PCI_MEM_SIZE,
+-						 1,
+-						 ATH79_IP3_IRQ(2));
+-	} else {
+-		/* No PCI support */
+-		return -ENODEV;
+-	}
+-
+-	if (!pdev)
+-		pr_err("unable to register PCI controller device\n");
+-
+-	return pdev ? 0 : -ENODEV;
+-}
+--- a/arch/mips/ath79/pci.h
++++ /dev/null
+@@ -1,35 +0,0 @@
+-/*
+- *  Atheros AR71XX/AR724X PCI support
+- *
+- *  Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com>
+- *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
+- *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+- *
+- *  This program 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.
+- */
+-
+-#ifndef _ATH79_PCI_H
+-#define _ATH79_PCI_H
+-
+-struct ath79_pci_irq {
+-	int	bus;
+-	u8	slot;
+-	u8	pin;
+-	int	irq;
+-};
+-
+-#ifdef CONFIG_PCI
+-void ath79_pci_set_irq_map(unsigned nr_irqs, const struct ath79_pci_irq *map);
+-void ath79_pci_set_plat_dev_init(int (*func)(struct pci_dev *dev));
+-int ath79_register_pci(void);
+-#else
+-static inline void
+-ath79_pci_set_irq_map(unsigned nr_irqs, const struct ath79_pci_irq *map) {}
+-static inline void
+-ath79_pci_set_plat_dev_init(int (*func)(struct pci_dev *)) {}
+-static inline int ath79_register_pci(void) { return 0; }
+-#endif
+-
+-#endif /* _ATH79_PCI_H */
+--- a/arch/mips/pci/Makefile
++++ b/arch/mips/pci/Makefile
+@@ -29,6 +29,7 @@ obj-$(CONFIG_MIPS_PCI_VIRTIO)	+= pci-vir
+ #
+ # These are still pretty much in the old state, watch, go blind.
+ #
++obj-$(CONFIG_ATH79)		+= fixup-ath79.o
+ obj-$(CONFIG_LASAT)		+= pci-lasat.o
+ obj-$(CONFIG_MIPS_COBALT)	+= fixup-cobalt.o
+ obj-$(CONFIG_LEMOTE_FULOONG2E)	+= fixup-fuloong2e.o ops-loongson2.o
+--- /dev/null
++++ b/arch/mips/pci/fixup-ath79.c
+@@ -0,0 +1,21 @@
++/*
++ *  Copyright (C) 2018 John Crispin <john@phrozen.org>
++ *
++ *  This program 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.
++ */
++
++#include <linux/pci.h>
++//#include <linux/of_irq.h>
++#include <linux/of_pci.h>
++
++int pcibios_plat_dev_init(struct pci_dev *dev)
++{
++	return PCIBIOS_SUCCESSFUL;
++}
++
++int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
++{
++	return of_irq_parse_and_map_pci(dev, slot, pin);
++}
diff --git a/target/linux/ath79/patches-4.19/0030-MIPS-ath79-drop-platform-device-registration-code.patch b/target/linux/ath79/patches-4.19/0030-MIPS-ath79-drop-platform-device-registration-code.patch
new file mode 100644
index 00000000000..93a133c1dfb
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/0030-MIPS-ath79-drop-platform-device-registration-code.patch
@@ -0,0 +1,933 @@
+From dce930fba8ad3a90ccd164f199e57c2d61937ccd Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Sat, 23 Jun 2018 15:12:38 +0200
+Subject: [PATCH 30/33] MIPS: ath79: drop platform device registration code
+
+With the target now being fully OF based, we can drop the legacy platform
+device registration code. All devices and their drivers are now probed
+via OF.
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ arch/mips/ath79/Makefile           |  10 --
+ arch/mips/ath79/common.h           |   2 -
+ arch/mips/ath79/dev-common.c       | 159 ------------------------
+ arch/mips/ath79/dev-common.h       |  18 ---
+ arch/mips/ath79/dev-gpio-buttons.c |  56 ---------
+ arch/mips/ath79/dev-gpio-buttons.h |  23 ----
+ arch/mips/ath79/dev-leds-gpio.c    |  54 ---------
+ arch/mips/ath79/dev-leds-gpio.h    |  21 ----
+ arch/mips/ath79/dev-spi.c          |  38 ------
+ arch/mips/ath79/dev-spi.h          |  22 ----
+ arch/mips/ath79/dev-usb.c          | 242 -------------------------------------
+ arch/mips/ath79/dev-usb.h          |  17 ---
+ arch/mips/ath79/dev-wmac.c         | 155 ------------------------
+ arch/mips/ath79/dev-wmac.h         |  17 ---
+ arch/mips/ath79/setup.c            |   1 -
+ 15 files changed, 835 deletions(-)
+ delete mode 100644 arch/mips/ath79/dev-common.c
+ delete mode 100644 arch/mips/ath79/dev-common.h
+ delete mode 100644 arch/mips/ath79/dev-gpio-buttons.c
+ delete mode 100644 arch/mips/ath79/dev-gpio-buttons.h
+ delete mode 100644 arch/mips/ath79/dev-leds-gpio.c
+ delete mode 100644 arch/mips/ath79/dev-leds-gpio.h
+ delete mode 100644 arch/mips/ath79/dev-spi.c
+ delete mode 100644 arch/mips/ath79/dev-spi.h
+ delete mode 100644 arch/mips/ath79/dev-usb.c
+ delete mode 100644 arch/mips/ath79/dev-usb.h
+ delete mode 100644 arch/mips/ath79/dev-wmac.c
+ delete mode 100644 arch/mips/ath79/dev-wmac.h
+
+--- a/arch/mips/ath79/Makefile
++++ b/arch/mips/ath79/Makefile
+@@ -11,13 +11,3 @@
+ obj-y	:= prom.o setup.o common.o clock.o
+ 
+ obj-$(CONFIG_EARLY_PRINTK)		+= early_printk.o
+-
+-#
+-# Devices
+-#
+-obj-y					+= dev-common.o
+-obj-$(CONFIG_ATH79_DEV_GPIO_BUTTONS)	+= dev-gpio-buttons.o
+-obj-$(CONFIG_ATH79_DEV_LEDS_GPIO)	+= dev-leds-gpio.o
+-obj-$(CONFIG_ATH79_DEV_SPI)		+= dev-spi.o
+-obj-$(CONFIG_ATH79_DEV_USB)		+= dev-usb.o
+-obj-$(CONFIG_ATH79_DEV_WMAC)		+= dev-wmac.o
+--- a/arch/mips/ath79/common.h
++++ b/arch/mips/ath79/common.h
+@@ -24,6 +24,4 @@ unsigned long ath79_get_sys_clk_rate(con
+ 
+ void ath79_ddr_ctrl_init(void);
+ 
+-void ath79_gpio_init(void);
+-
+ #endif /* __ATH79_COMMON_H */
+--- a/arch/mips/ath79/dev-common.c
++++ /dev/null
+@@ -1,159 +0,0 @@
+-/*
+- *  Atheros AR71XX/AR724X/AR913X common devices
+- *
+- *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
+- *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+- *
+- *  Parts of this file are based on Atheros' 2.6.15 BSP
+- *
+- *  This program 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.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/platform_device.h>
+-#include <linux/platform_data/gpio-ath79.h>
+-#include <linux/serial_8250.h>
+-#include <linux/clk.h>
+-#include <linux/err.h>
+-
+-#include <asm/mach-ath79/ath79.h>
+-#include <asm/mach-ath79/ar71xx_regs.h>
+-#include "common.h"
+-#include "dev-common.h"
+-
+-static struct resource ath79_uart_resources[] = {
+-	{
+-		.start	= AR71XX_UART_BASE,
+-		.end	= AR71XX_UART_BASE + AR71XX_UART_SIZE - 1,
+-		.flags	= IORESOURCE_MEM,
+-	},
+-};
+-
+-#define AR71XX_UART_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP)
+-static struct plat_serial8250_port ath79_uart_data[] = {
+-	{
+-		.mapbase	= AR71XX_UART_BASE,
+-		.irq		= ATH79_MISC_IRQ(3),
+-		.flags		= AR71XX_UART_FLAGS,
+-		.iotype		= UPIO_MEM32,
+-		.regshift	= 2,
+-	}, {
+-		/* terminating entry */
+-	}
+-};
+-
+-static struct platform_device ath79_uart_device = {
+-	.name		= "serial8250",
+-	.id		= PLAT8250_DEV_PLATFORM,
+-	.resource	= ath79_uart_resources,
+-	.num_resources	= ARRAY_SIZE(ath79_uart_resources),
+-	.dev = {
+-		.platform_data	= ath79_uart_data
+-	},
+-};
+-
+-static struct resource ar933x_uart_resources[] = {
+-	{
+-		.start	= AR933X_UART_BASE,
+-		.end	= AR933X_UART_BASE + AR71XX_UART_SIZE - 1,
+-		.flags	= IORESOURCE_MEM,
+-	},
+-	{
+-		.start	= ATH79_MISC_IRQ(3),
+-		.end	= ATH79_MISC_IRQ(3),
+-		.flags	= IORESOURCE_IRQ,
+-	},
+-};
+-
+-static struct platform_device ar933x_uart_device = {
+-	.name		= "ar933x-uart",
+-	.id		= -1,
+-	.resource	= ar933x_uart_resources,
+-	.num_resources	= ARRAY_SIZE(ar933x_uart_resources),
+-};
+-
+-void __init ath79_register_uart(void)
+-{
+-	unsigned long uart_clk_rate;
+-
+-	uart_clk_rate = ath79_get_sys_clk_rate("uart");
+-
+-	if (soc_is_ar71xx() ||
+-	    soc_is_ar724x() ||
+-	    soc_is_ar913x() ||
+-	    soc_is_ar934x() ||
+-	    soc_is_qca955x()) {
+-		ath79_uart_data[0].uartclk = uart_clk_rate;
+-		platform_device_register(&ath79_uart_device);
+-	} else if (soc_is_ar933x()) {
+-		platform_device_register(&ar933x_uart_device);
+-	} else {
+-		BUG();
+-	}
+-}
+-
+-void __init ath79_register_wdt(void)
+-{
+-	struct resource res;
+-
+-	memset(&res, 0, sizeof(res));
+-
+-	res.flags = IORESOURCE_MEM;
+-	res.start = AR71XX_RESET_BASE + AR71XX_RESET_REG_WDOG_CTRL;
+-	res.end = res.start + 0x8 - 1;
+-
+-	platform_device_register_simple("ath79-wdt", -1, &res, 1);
+-}
+-
+-static struct ath79_gpio_platform_data ath79_gpio_pdata;
+-
+-static struct resource ath79_gpio_resources[] = {
+-	{
+-		.flags = IORESOURCE_MEM,
+-		.start = AR71XX_GPIO_BASE,
+-		.end = AR71XX_GPIO_BASE + AR71XX_GPIO_SIZE - 1,
+-	},
+-	{
+-		.start	= ATH79_MISC_IRQ(2),
+-		.end	= ATH79_MISC_IRQ(2),
+-		.flags	= IORESOURCE_IRQ,
+-	},
+-};
+-
+-static struct platform_device ath79_gpio_device = {
+-	.name		= "ath79-gpio",
+-	.id		= -1,
+-	.resource	= ath79_gpio_resources,
+-	.num_resources	= ARRAY_SIZE(ath79_gpio_resources),
+-	.dev = {
+-		.platform_data	= &ath79_gpio_pdata
+-	},
+-};
+-
+-void __init ath79_gpio_init(void)
+-{
+-	if (soc_is_ar71xx()) {
+-		ath79_gpio_pdata.ngpios = AR71XX_GPIO_COUNT;
+-	} else if (soc_is_ar7240()) {
+-		ath79_gpio_pdata.ngpios = AR7240_GPIO_COUNT;
+-	} else if (soc_is_ar7241() || soc_is_ar7242()) {
+-		ath79_gpio_pdata.ngpios = AR7241_GPIO_COUNT;
+-	} else if (soc_is_ar913x()) {
+-		ath79_gpio_pdata.ngpios = AR913X_GPIO_COUNT;
+-	} else if (soc_is_ar933x()) {
+-		ath79_gpio_pdata.ngpios = AR933X_GPIO_COUNT;
+-	} else if (soc_is_ar934x()) {
+-		ath79_gpio_pdata.ngpios = AR934X_GPIO_COUNT;
+-		ath79_gpio_pdata.oe_inverted = 1;
+-	} else if (soc_is_qca955x()) {
+-		ath79_gpio_pdata.ngpios = QCA955X_GPIO_COUNT;
+-		ath79_gpio_pdata.oe_inverted = 1;
+-	} else {
+-		BUG();
+-	}
+-
+-	platform_device_register(&ath79_gpio_device);
+-}
+--- a/arch/mips/ath79/dev-common.h
++++ /dev/null
+@@ -1,18 +0,0 @@
+-/*
+- *  Atheros AR71XX/AR724X/AR913X common devices
+- *
+- *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+- *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+- *
+- *  This program 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.
+- */
+-
+-#ifndef _ATH79_DEV_COMMON_H
+-#define _ATH79_DEV_COMMON_H
+-
+-void ath79_register_uart(void);
+-void ath79_register_wdt(void);
+-
+-#endif /* _ATH79_DEV_COMMON_H */
+--- a/arch/mips/ath79/dev-gpio-buttons.c
++++ /dev/null
+@@ -1,56 +0,0 @@
+-/*
+- *  Atheros AR71XX/AR724X/AR913X GPIO button support
+- *
+- *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+- *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+- *
+- *  This program 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.
+- */
+-
+-#include "linux/init.h"
+-#include "linux/slab.h"
+-#include <linux/platform_device.h>
+-
+-#include "dev-gpio-buttons.h"
+-
+-void __init ath79_register_gpio_keys_polled(int id,
+-					    unsigned poll_interval,
+-					    unsigned nbuttons,
+-					    struct gpio_keys_button *buttons)
+-{
+-	struct platform_device *pdev;
+-	struct gpio_keys_platform_data pdata;
+-	struct gpio_keys_button *p;
+-	int err;
+-
+-	p = kmemdup(buttons, nbuttons * sizeof(*p), GFP_KERNEL);
+-	if (!p)
+-		return;
+-
+-	pdev = platform_device_alloc("gpio-keys-polled", id);
+-	if (!pdev)
+-		goto err_free_buttons;
+-
+-	memset(&pdata, 0, sizeof(pdata));
+-	pdata.poll_interval = poll_interval;
+-	pdata.nbuttons = nbuttons;
+-	pdata.buttons = p;
+-
+-	err = platform_device_add_data(pdev, &pdata, sizeof(pdata));
+-	if (err)
+-		goto err_put_pdev;
+-
+-	err = platform_device_add(pdev);
+-	if (err)
+-		goto err_put_pdev;
+-
+-	return;
+-
+-err_put_pdev:
+-	platform_device_put(pdev);
+-
+-err_free_buttons:
+-	kfree(p);
+-}
+--- a/arch/mips/ath79/dev-gpio-buttons.h
++++ /dev/null
+@@ -1,23 +0,0 @@
+-/*
+- *  Atheros AR71XX/AR724X/AR913X GPIO button support
+- *
+- *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+- *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+- *
+- *  This program 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.
+- */
+-
+-#ifndef _ATH79_DEV_GPIO_BUTTONS_H
+-#define _ATH79_DEV_GPIO_BUTTONS_H
+-
+-#include <linux/input.h>
+-#include <linux/gpio_keys.h>
+-
+-void ath79_register_gpio_keys_polled(int id,
+-				     unsigned poll_interval,
+-				     unsigned nbuttons,
+-				     struct gpio_keys_button *buttons);
+-
+-#endif /* _ATH79_DEV_GPIO_BUTTONS_H */
+--- a/arch/mips/ath79/dev-leds-gpio.c
++++ /dev/null
+@@ -1,54 +0,0 @@
+-/*
+- *  Atheros AR71XX/AR724X/AR913X common GPIO LEDs support
+- *
+- *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+- *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+- *
+- *  This program 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.
+- */
+-
+-#include <linux/init.h>
+-#include <linux/slab.h>
+-#include <linux/platform_device.h>
+-
+-#include "dev-leds-gpio.h"
+-
+-void __init ath79_register_leds_gpio(int id,
+-				     unsigned num_leds,
+-				     struct gpio_led *leds)
+-{
+-	struct platform_device *pdev;
+-	struct gpio_led_platform_data pdata;
+-	struct gpio_led *p;
+-	int err;
+-
+-	p = kmemdup(leds, num_leds * sizeof(*p), GFP_KERNEL);
+-	if (!p)
+-		return;
+-
+-	pdev = platform_device_alloc("leds-gpio", id);
+-	if (!pdev)
+-		goto err_free_leds;
+-
+-	memset(&pdata, 0, sizeof(pdata));
+-	pdata.num_leds = num_leds;
+-	pdata.leds = p;
+-
+-	err = platform_device_add_data(pdev, &pdata, sizeof(pdata));
+-	if (err)
+-		goto err_put_pdev;
+-
+-	err = platform_device_add(pdev);
+-	if (err)
+-		goto err_put_pdev;
+-
+-	return;
+-
+-err_put_pdev:
+-	platform_device_put(pdev);
+-
+-err_free_leds:
+-	kfree(p);
+-}
+--- a/arch/mips/ath79/dev-leds-gpio.h
++++ /dev/null
+@@ -1,21 +0,0 @@
+-/*
+- *  Atheros AR71XX/AR724X/AR913X common GPIO LEDs support
+- *
+- *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+- *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+- *
+- *  This program 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.
+- */
+-
+-#ifndef _ATH79_DEV_LEDS_GPIO_H
+-#define _ATH79_DEV_LEDS_GPIO_H
+-
+-#include <linux/leds.h>
+-
+-void ath79_register_leds_gpio(int id,
+-			      unsigned num_leds,
+-			      struct gpio_led *leds);
+-
+-#endif /* _ATH79_DEV_LEDS_GPIO_H */
+--- a/arch/mips/ath79/dev-spi.c
++++ /dev/null
+@@ -1,38 +0,0 @@
+-/*
+- *  Atheros AR71XX/AR724X/AR913X SPI controller device
+- *
+- *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+- *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+- *
+- *  This program 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.
+- */
+-
+-#include <linux/platform_device.h>
+-#include <asm/mach-ath79/ar71xx_regs.h>
+-#include "dev-spi.h"
+-
+-static struct resource ath79_spi_resources[] = {
+-	{
+-		.start	= AR71XX_SPI_BASE,
+-		.end	= AR71XX_SPI_BASE + AR71XX_SPI_SIZE - 1,
+-		.flags	= IORESOURCE_MEM,
+-	},
+-};
+-
+-static struct platform_device ath79_spi_device = {
+-	.name		= "ath79-spi",
+-	.id		= -1,
+-	.resource	= ath79_spi_resources,
+-	.num_resources	= ARRAY_SIZE(ath79_spi_resources),
+-};
+-
+-void __init ath79_register_spi(struct ath79_spi_platform_data *pdata,
+-			       struct spi_board_info const *info,
+-			       unsigned n)
+-{
+-	spi_register_board_info(info, n);
+-	ath79_spi_device.dev.platform_data = pdata;
+-	platform_device_register(&ath79_spi_device);
+-}
+--- a/arch/mips/ath79/dev-spi.h
++++ /dev/null
+@@ -1,22 +0,0 @@
+-/*
+- *  Atheros AR71XX/AR724X/AR913X SPI controller device
+- *
+- *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+- *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+- *
+- *  This program 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.
+- */
+-
+-#ifndef _ATH79_DEV_SPI_H
+-#define _ATH79_DEV_SPI_H
+-
+-#include <linux/spi/spi.h>
+-#include <asm/mach-ath79/ath79_spi_platform.h>
+-
+-void ath79_register_spi(struct ath79_spi_platform_data *pdata,
+-			 struct spi_board_info const *info,
+-			 unsigned n);
+-
+-#endif /* _ATH79_DEV_SPI_H */
+--- a/arch/mips/ath79/dev-usb.c
++++ /dev/null
+@@ -1,242 +0,0 @@
+-/*
+- *  Atheros AR7XXX/AR9XXX USB Host Controller device
+- *
+- *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
+- *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+- *
+- *  Parts of this file are based on Atheros' 2.6.15 BSP
+- *
+- *  This program 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.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/delay.h>
+-#include <linux/irq.h>
+-#include <linux/dma-mapping.h>
+-#include <linux/platform_device.h>
+-#include <linux/usb/ehci_pdriver.h>
+-#include <linux/usb/ohci_pdriver.h>
+-
+-#include <asm/mach-ath79/ath79.h>
+-#include <asm/mach-ath79/ar71xx_regs.h>
+-#include "common.h"
+-#include "dev-usb.h"
+-
+-static u64 ath79_usb_dmamask = DMA_BIT_MASK(32);
+-
+-static struct usb_ohci_pdata ath79_ohci_pdata = {
+-};
+-
+-static struct usb_ehci_pdata ath79_ehci_pdata_v1 = {
+-	.has_synopsys_hc_bug	= 1,
+-};
+-
+-static struct usb_ehci_pdata ath79_ehci_pdata_v2 = {
+-	.caps_offset		= 0x100,
+-	.has_tt			= 1,
+-};
+-
+-static void __init ath79_usb_register(const char *name, int id,
+-				      unsigned long base, unsigned long size,
+-				      int irq, const void *data,
+-				      size_t data_size)
+-{
+-	struct resource res[2];
+-	struct platform_device *pdev;
+-
+-	memset(res, 0, sizeof(res));
+-
+-	res[0].flags = IORESOURCE_MEM;
+-	res[0].start = base;
+-	res[0].end = base + size - 1;
+-
+-	res[1].flags = IORESOURCE_IRQ;
+-	res[1].start = irq;
+-	res[1].end = irq;
+-
+-	pdev = platform_device_register_resndata(NULL, name, id,
+-						 res, ARRAY_SIZE(res),
+-						 data, data_size);
+-
+-	if (IS_ERR(pdev)) {
+-		pr_err("ath79: unable to register USB at %08lx, err=%d\n",
+-		       base, (int) PTR_ERR(pdev));
+-		return;
+-	}
+-
+-	pdev->dev.dma_mask = &ath79_usb_dmamask;
+-	pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+-}
+-
+-#define AR71XX_USB_RESET_MASK	(AR71XX_RESET_USB_HOST | \
+-				 AR71XX_RESET_USB_PHY | \
+-				 AR71XX_RESET_USB_OHCI_DLL)
+-
+-static void __init ath79_usb_setup(void)
+-{
+-	void __iomem *usb_ctrl_base;
+-
+-	ath79_device_reset_set(AR71XX_USB_RESET_MASK);
+-	mdelay(1000);
+-	ath79_device_reset_clear(AR71XX_USB_RESET_MASK);
+-
+-	usb_ctrl_base = ioremap(AR71XX_USB_CTRL_BASE, AR71XX_USB_CTRL_SIZE);
+-
+-	/* Turning on the Buff and Desc swap bits */
+-	__raw_writel(0xf0000, usb_ctrl_base + AR71XX_USB_CTRL_REG_CONFIG);
+-
+-	/* WAR for HW bug. Here it adjusts the duration between two SOFS */
+-	__raw_writel(0x20c00, usb_ctrl_base + AR71XX_USB_CTRL_REG_FLADJ);
+-
+-	iounmap(usb_ctrl_base);
+-
+-	mdelay(900);
+-
+-	ath79_usb_register("ohci-platform", -1,
+-			   AR71XX_OHCI_BASE, AR71XX_OHCI_SIZE,
+-			   ATH79_MISC_IRQ(6),
+-			   &ath79_ohci_pdata, sizeof(ath79_ohci_pdata));
+-
+-	ath79_usb_register("ehci-platform", -1,
+-			   AR71XX_EHCI_BASE, AR71XX_EHCI_SIZE,
+-			   ATH79_CPU_IRQ(3),
+-			   &ath79_ehci_pdata_v1, sizeof(ath79_ehci_pdata_v1));
+-}
+-
+-static void __init ar7240_usb_setup(void)
+-{
+-	void __iomem *usb_ctrl_base;
+-
+-	ath79_device_reset_clear(AR7240_RESET_OHCI_DLL);
+-	ath79_device_reset_set(AR7240_RESET_USB_HOST);
+-
+-	mdelay(1000);
+-
+-	ath79_device_reset_set(AR7240_RESET_OHCI_DLL);
+-	ath79_device_reset_clear(AR7240_RESET_USB_HOST);
+-
+-	usb_ctrl_base = ioremap(AR7240_USB_CTRL_BASE, AR7240_USB_CTRL_SIZE);
+-
+-	/* WAR for HW bug. Here it adjusts the duration between two SOFS */
+-	__raw_writel(0x3, usb_ctrl_base + AR71XX_USB_CTRL_REG_FLADJ);
+-
+-	iounmap(usb_ctrl_base);
+-
+-	ath79_usb_register("ohci-platform", -1,
+-			   AR7240_OHCI_BASE, AR7240_OHCI_SIZE,
+-			   ATH79_CPU_IRQ(3),
+-			   &ath79_ohci_pdata, sizeof(ath79_ohci_pdata));
+-}
+-
+-static void __init ar724x_usb_setup(void)
+-{
+-	ath79_device_reset_set(AR724X_RESET_USBSUS_OVERRIDE);
+-	mdelay(10);
+-
+-	ath79_device_reset_clear(AR724X_RESET_USB_HOST);
+-	mdelay(10);
+-
+-	ath79_device_reset_clear(AR724X_RESET_USB_PHY);
+-	mdelay(10);
+-
+-	ath79_usb_register("ehci-platform", -1,
+-			   AR724X_EHCI_BASE, AR724X_EHCI_SIZE,
+-			   ATH79_CPU_IRQ(3),
+-			   &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2));
+-}
+-
+-static void __init ar913x_usb_setup(void)
+-{
+-	ath79_device_reset_set(AR913X_RESET_USBSUS_OVERRIDE);
+-	mdelay(10);
+-
+-	ath79_device_reset_clear(AR913X_RESET_USB_HOST);
+-	mdelay(10);
+-
+-	ath79_device_reset_clear(AR913X_RESET_USB_PHY);
+-	mdelay(10);
+-
+-	ath79_usb_register("ehci-platform", -1,
+-			   AR913X_EHCI_BASE, AR913X_EHCI_SIZE,
+-			   ATH79_CPU_IRQ(3),
+-			   &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2));
+-}
+-
+-static void __init ar933x_usb_setup(void)
+-{
+-	ath79_device_reset_set(AR933X_RESET_USBSUS_OVERRIDE);
+-	mdelay(10);
+-
+-	ath79_device_reset_clear(AR933X_RESET_USB_HOST);
+-	mdelay(10);
+-
+-	ath79_device_reset_clear(AR933X_RESET_USB_PHY);
+-	mdelay(10);
+-
+-	ath79_usb_register("ehci-platform", -1,
+-			   AR933X_EHCI_BASE, AR933X_EHCI_SIZE,
+-			   ATH79_CPU_IRQ(3),
+-			   &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2));
+-}
+-
+-static void __init ar934x_usb_setup(void)
+-{
+-	u32 bootstrap;
+-
+-	bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP);
+-	if (bootstrap & AR934X_BOOTSTRAP_USB_MODE_DEVICE)
+-		return;
+-
+-	ath79_device_reset_set(AR934X_RESET_USBSUS_OVERRIDE);
+-	udelay(1000);
+-
+-	ath79_device_reset_clear(AR934X_RESET_USB_PHY);
+-	udelay(1000);
+-
+-	ath79_device_reset_clear(AR934X_RESET_USB_PHY_ANALOG);
+-	udelay(1000);
+-
+-	ath79_device_reset_clear(AR934X_RESET_USB_HOST);
+-	udelay(1000);
+-
+-	ath79_usb_register("ehci-platform", -1,
+-			   AR934X_EHCI_BASE, AR934X_EHCI_SIZE,
+-			   ATH79_CPU_IRQ(3),
+-			   &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2));
+-}
+-
+-static void __init qca955x_usb_setup(void)
+-{
+-	ath79_usb_register("ehci-platform", 0,
+-			   QCA955X_EHCI0_BASE, QCA955X_EHCI_SIZE,
+-			   ATH79_IP3_IRQ(0),
+-			   &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2));
+-
+-	ath79_usb_register("ehci-platform", 1,
+-			   QCA955X_EHCI1_BASE, QCA955X_EHCI_SIZE,
+-			   ATH79_IP3_IRQ(1),
+-			   &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2));
+-}
+-
+-void __init ath79_register_usb(void)
+-{
+-	if (soc_is_ar71xx())
+-		ath79_usb_setup();
+-	else if (soc_is_ar7240())
+-		ar7240_usb_setup();
+-	else if (soc_is_ar7241() || soc_is_ar7242())
+-		ar724x_usb_setup();
+-	else if (soc_is_ar913x())
+-		ar913x_usb_setup();
+-	else if (soc_is_ar933x())
+-		ar933x_usb_setup();
+-	else if (soc_is_ar934x())
+-		ar934x_usb_setup();
+-	else if (soc_is_qca955x())
+-		qca955x_usb_setup();
+-	else
+-		BUG();
+-}
+--- a/arch/mips/ath79/dev-usb.h
++++ /dev/null
+@@ -1,17 +0,0 @@
+-/*
+- *  Atheros AR71XX/AR724X/AR913X USB Host Controller support
+- *
+- *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+- *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+- *
+- *  This program 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.
+- */
+-
+-#ifndef _ATH79_DEV_USB_H
+-#define _ATH79_DEV_USB_H
+-
+-void ath79_register_usb(void);
+-
+-#endif /* _ATH79_DEV_USB_H */
+--- a/arch/mips/ath79/dev-wmac.c
++++ /dev/null
+@@ -1,155 +0,0 @@
+-/*
+- *  Atheros AR913X/AR933X SoC built-in WMAC device support
+- *
+- *  Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com>
+- *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
+- *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+- *
+- *  Parts of this file are based on Atheros 2.6.15/2.6.31 BSP
+- *
+- *  This program 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.
+- */
+-
+-#include <linux/init.h>
+-#include <linux/delay.h>
+-#include <linux/irq.h>
+-#include <linux/platform_device.h>
+-#include <linux/ath9k_platform.h>
+-
+-#include <asm/mach-ath79/ath79.h>
+-#include <asm/mach-ath79/ar71xx_regs.h>
+-#include "dev-wmac.h"
+-
+-static struct ath9k_platform_data ath79_wmac_data;
+-
+-static struct resource ath79_wmac_resources[] = {
+-	{
+-		/* .start and .end fields are filled dynamically */
+-		.flags	= IORESOURCE_MEM,
+-	}, {
+-		/* .start and .end fields are filled dynamically */
+-		.flags	= IORESOURCE_IRQ,
+-	},
+-};
+-
+-static struct platform_device ath79_wmac_device = {
+-	.name		= "ath9k",
+-	.id		= -1,
+-	.resource	= ath79_wmac_resources,
+-	.num_resources	= ARRAY_SIZE(ath79_wmac_resources),
+-	.dev = {
+-		.platform_data = &ath79_wmac_data,
+-	},
+-};
+-
+-static void __init ar913x_wmac_setup(void)
+-{
+-	/* reset the WMAC */
+-	ath79_device_reset_set(AR913X_RESET_AMBA2WMAC);
+-	mdelay(10);
+-
+-	ath79_device_reset_clear(AR913X_RESET_AMBA2WMAC);
+-	mdelay(10);
+-
+-	ath79_wmac_resources[0].start = AR913X_WMAC_BASE;
+-	ath79_wmac_resources[0].end = AR913X_WMAC_BASE + AR913X_WMAC_SIZE - 1;
+-	ath79_wmac_resources[1].start = ATH79_CPU_IRQ(2);
+-	ath79_wmac_resources[1].end = ATH79_CPU_IRQ(2);
+-}
+-
+-
+-static int ar933x_wmac_reset(void)
+-{
+-	ath79_device_reset_set(AR933X_RESET_WMAC);
+-	ath79_device_reset_clear(AR933X_RESET_WMAC);
+-
+-	return 0;
+-}
+-
+-static int ar933x_r1_get_wmac_revision(void)
+-{
+-	return ath79_soc_rev;
+-}
+-
+-static void __init ar933x_wmac_setup(void)
+-{
+-	u32 t;
+-
+-	ar933x_wmac_reset();
+-
+-	ath79_wmac_device.name = "ar933x_wmac";
+-
+-	ath79_wmac_resources[0].start = AR933X_WMAC_BASE;
+-	ath79_wmac_resources[0].end = AR933X_WMAC_BASE + AR933X_WMAC_SIZE - 1;
+-	ath79_wmac_resources[1].start = ATH79_CPU_IRQ(2);
+-	ath79_wmac_resources[1].end = ATH79_CPU_IRQ(2);
+-
+-	t = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP);
+-	if (t & AR933X_BOOTSTRAP_REF_CLK_40)
+-		ath79_wmac_data.is_clk_25mhz = false;
+-	else
+-		ath79_wmac_data.is_clk_25mhz = true;
+-
+-	if (ath79_soc_rev == 1)
+-		ath79_wmac_data.get_mac_revision = ar933x_r1_get_wmac_revision;
+-
+-	ath79_wmac_data.external_reset = ar933x_wmac_reset;
+-}
+-
+-static void ar934x_wmac_setup(void)
+-{
+-	u32 t;
+-
+-	ath79_wmac_device.name = "ar934x_wmac";
+-
+-	ath79_wmac_resources[0].start = AR934X_WMAC_BASE;
+-	ath79_wmac_resources[0].end = AR934X_WMAC_BASE + AR934X_WMAC_SIZE - 1;
+-	ath79_wmac_resources[1].start = ATH79_IP2_IRQ(1);
+-	ath79_wmac_resources[1].end = ATH79_IP2_IRQ(1);
+-
+-	t = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP);
+-	if (t & AR934X_BOOTSTRAP_REF_CLK_40)
+-		ath79_wmac_data.is_clk_25mhz = false;
+-	else
+-		ath79_wmac_data.is_clk_25mhz = true;
+-}
+-
+-static void qca955x_wmac_setup(void)
+-{
+-	u32 t;
+-
+-	ath79_wmac_device.name = "qca955x_wmac";
+-
+-	ath79_wmac_resources[0].start = QCA955X_WMAC_BASE;
+-	ath79_wmac_resources[0].end = QCA955X_WMAC_BASE + QCA955X_WMAC_SIZE - 1;
+-	ath79_wmac_resources[1].start = ATH79_IP2_IRQ(1);
+-	ath79_wmac_resources[1].end = ATH79_IP2_IRQ(1);
+-
+-	t = ath79_reset_rr(QCA955X_RESET_REG_BOOTSTRAP);
+-	if (t & QCA955X_BOOTSTRAP_REF_CLK_40)
+-		ath79_wmac_data.is_clk_25mhz = false;
+-	else
+-		ath79_wmac_data.is_clk_25mhz = true;
+-}
+-
+-void __init ath79_register_wmac(u8 *cal_data)
+-{
+-	if (soc_is_ar913x())
+-		ar913x_wmac_setup();
+-	else if (soc_is_ar933x())
+-		ar933x_wmac_setup();
+-	else if (soc_is_ar934x())
+-		ar934x_wmac_setup();
+-	else if (soc_is_qca955x())
+-		qca955x_wmac_setup();
+-	else
+-		BUG();
+-
+-	if (cal_data)
+-		memcpy(ath79_wmac_data.eeprom_data, cal_data,
+-		       sizeof(ath79_wmac_data.eeprom_data));
+-
+-	platform_device_register(&ath79_wmac_device);
+-}
+--- a/arch/mips/ath79/dev-wmac.h
++++ /dev/null
+@@ -1,17 +0,0 @@
+-/*
+- *  Atheros AR913X/AR933X SoC built-in WMAC device support
+- *
+- *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
+- *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+- *
+- *  This program 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.
+- */
+-
+-#ifndef _ATH79_DEV_WMAC_H
+-#define _ATH79_DEV_WMAC_H
+-
+-void ath79_register_wmac(u8 *cal_data);
+-
+-#endif /* _ATH79_DEV_WMAC_H */
+--- a/arch/mips/ath79/setup.c
++++ b/arch/mips/ath79/setup.c
+@@ -32,7 +32,6 @@
+ #include <asm/mach-ath79/ath79.h>
+ #include <asm/mach-ath79/ar71xx_regs.h>
+ #include "common.h"
+-#include "dev-common.h"
+ 
+ #define ATH79_SYS_TYPE_LEN	64
+ 
diff --git a/target/linux/ath79/patches-4.19/0031-MIPS-ath79-drop-OF-clock-code.patch b/target/linux/ath79/patches-4.19/0031-MIPS-ath79-drop-OF-clock-code.patch
new file mode 100644
index 00000000000..a11be73d7a8
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/0031-MIPS-ath79-drop-OF-clock-code.patch
@@ -0,0 +1,95 @@
+From 00e4313da4609074fff134e61dd9ffe3fd37474d Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Sun, 24 Jun 2018 09:39:41 +0200
+Subject: [PATCH 31/33] MIPS: ath79: drop !OF clock code
+
+With the target now being fully OF based, we can drop the legacy clock
+registration code. All clocks are now probed via devicetree.
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ arch/mips/ath79/clock.c  | 56 ------------------------------------------------
+ arch/mips/ath79/common.h |  3 ---
+ 2 files changed, 59 deletions(-)
+
+--- a/arch/mips/ath79/clock.c
++++ b/arch/mips/ath79/clock.c
+@@ -617,60 +617,6 @@ static void __init qca956x_clocks_init(v
+ 	ath79_set_clk(ATH79_CLK_AHB, ahb_rate);
+ }
+ 
+-void __init ath79_clocks_init(void)
+-{
+-	const char *wdt;
+-	const char *uart;
+-
+-	if (soc_is_ar71xx())
+-		ar71xx_clocks_init(ath79_pll_base);
+-	else if (soc_is_ar724x() || soc_is_ar913x())
+-		ar724x_clocks_init(ath79_pll_base);
+-	else if (soc_is_ar933x())
+-		ar933x_clocks_init(ath79_pll_base);
+-	else if (soc_is_ar934x())
+-		ar934x_clocks_init(ath79_pll_base);
+-	else if (soc_is_qca953x())
+-		qca953x_clocks_init(ath79_pll_base);
+-	else if (soc_is_qca955x())
+-		qca955x_clocks_init(ath79_pll_base);
+-	else if (soc_is_qca956x() || soc_is_tp9343())
+-		qca956x_clocks_init(ath79_pll_base);
+-	else
+-		BUG();
+-
+-	if (soc_is_ar71xx() || soc_is_ar724x() || soc_is_ar913x()) {
+-		wdt = "ahb";
+-		uart = "ahb";
+-	} else if (soc_is_ar933x()) {
+-		wdt = "ahb";
+-		uart = "ref";
+-	} else {
+-		wdt = "ref";
+-		uart = "ref";
+-	}
+-
+-	clk_add_alias("wdt", NULL, wdt, NULL);
+-	clk_add_alias("uart", NULL, uart, NULL);
+-}
+-
+-unsigned long __init
+-ath79_get_sys_clk_rate(const char *id)
+-{
+-	struct clk *clk;
+-	unsigned long rate;
+-
+-	clk = clk_get(NULL, id);
+-	if (IS_ERR(clk))
+-		panic("unable to get %s clock, err=%d", id, (int) PTR_ERR(clk));
+-
+-	rate = clk_get_rate(clk);
+-	clk_put(clk);
+-
+-	return rate;
+-}
+-
+-#ifdef CONFIG_OF
+ static void __init ath79_clocks_init_dt(struct device_node *np)
+ {
+ 	struct clk *ref_clk;
+@@ -727,5 +673,3 @@ CLK_OF_DECLARE(ar9340_clk, "qca,ar9340-p
+ CLK_OF_DECLARE(ar9530_clk, "qca,qca9530-pll", ath79_clocks_init_dt);
+ CLK_OF_DECLARE(ar9550_clk, "qca,qca9550-pll", ath79_clocks_init_dt);
+ CLK_OF_DECLARE(ar9560_clk, "qca,qca9560-pll", ath79_clocks_init_dt);
+-
+-#endif
+--- a/arch/mips/ath79/common.h
++++ b/arch/mips/ath79/common.h
+@@ -19,9 +19,6 @@
+ #define ATH79_MEM_SIZE_MIN	(2 * 1024 * 1024)
+ #define ATH79_MEM_SIZE_MAX	(256 * 1024 * 1024)
+ 
+-void ath79_clocks_init(void);
+-unsigned long ath79_get_sys_clk_rate(const char *id);
+-
+ void ath79_ddr_ctrl_init(void);
+ 
+ #endif /* __ATH79_COMMON_H */
diff --git a/target/linux/ath79/patches-4.19/0032-MIPS-ath79-sanitize-symbols.patch b/target/linux/ath79/patches-4.19/0032-MIPS-ath79-sanitize-symbols.patch
new file mode 100644
index 00000000000..1c38139323e
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/0032-MIPS-ath79-sanitize-symbols.patch
@@ -0,0 +1,93 @@
+From 3fc8585cf76022dba7496627074d42af88c30718 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Sat, 23 Jun 2018 15:16:55 +0200
+Subject: [PATCH 32/33] MIPS: ath79: sanitize symbols
+
+We no longer need to select which SoCs are supported as the whole arch
+code is always built. So lets drop all the SoC symbols
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ arch/mips/Kconfig       |  2 ++
+ arch/mips/ath79/Kconfig | 44 +++++---------------------------------------
+ arch/mips/pci/Makefile  |  2 +-
+ 3 files changed, 8 insertions(+), 40 deletions(-)
+
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -208,6 +208,8 @@ config ATH79
+ 	select SYS_SUPPORTS_BIG_ENDIAN
+ 	select SYS_SUPPORTS_MIPS16
+ 	select SYS_SUPPORTS_ZBOOT_UART_PROM
++	select HW_HAS_PCI
++	select USB_ARCH_HAS_EHCI
+ 	select USE_OF
+ 	select USB_EHCI_ROOT_HUB_TT if USB_EHCI_HCD_PLATFORM
+ 	help
+--- a/arch/mips/ath79/Kconfig
++++ b/arch/mips/ath79/Kconfig
+@@ -1,48 +1,14 @@
+ # SPDX-License-Identifier: GPL-2.0
+ if ATH79
+ 
+-config SOC_AR71XX
+-	select HW_HAS_PCI
+-	def_bool n
+-
+-config SOC_AR724X
+-	select HW_HAS_PCI
+-	select PCI_AR724X if PCI
+-	def_bool n
+-
+-config SOC_AR913X
+-	def_bool n
+-
+-config SOC_AR933X
+-	def_bool n
+-
+-config SOC_AR934X
+-	select HW_HAS_PCI
+-	select PCI_AR724X if PCI
+-	def_bool n
+-
+-config SOC_QCA955X
+-	select HW_HAS_PCI
+-	select PCI_AR724X if PCI
++config PCI_AR71XX
++	bool "PCI support for AR7100 type SoCs"
++	depends on PCI
+ 	def_bool n
+ 
+ config PCI_AR724X
+-	def_bool n
+-
+-config ATH79_DEV_GPIO_BUTTONS
+-	def_bool n
+-
+-config ATH79_DEV_LEDS_GPIO
+-	def_bool n
+-
+-config ATH79_DEV_SPI
+-	def_bool n
+-
+-config ATH79_DEV_USB
+-	def_bool n
+-
+-config ATH79_DEV_WMAC
+-	depends on (SOC_AR913X || SOC_AR933X || SOC_AR934X || SOC_QCA955X)
++	bool "PCI support for AR724x type SoCs"
++	depends on PCI
+ 	def_bool n
+ 
+ endif
+--- a/arch/mips/pci/Makefile
++++ b/arch/mips/pci/Makefile
+@@ -23,7 +23,7 @@ obj-$(CONFIG_BCM63XX)		+= pci-bcm63xx.o
+ 					ops-bcm63xx.o
+ obj-$(CONFIG_MIPS_ALCHEMY)	+= pci-alchemy.o
+ obj-$(CONFIG_PCI_AR2315)	+= pci-ar2315.o
+-obj-$(CONFIG_SOC_AR71XX)	+= pci-ar71xx.o
++obj-$(CONFIG_PCI_AR71XX)	+= pci-ar71xx.o
+ obj-$(CONFIG_PCI_AR724X)	+= pci-ar724x.o
+ obj-$(CONFIG_MIPS_PCI_VIRTIO)	+= pci-virtio-guest.o
+ #
diff --git a/target/linux/ath79/patches-4.19/0033-spi-ath79-drop-pdata-support.patch b/target/linux/ath79/patches-4.19/0033-spi-ath79-drop-pdata-support.patch
new file mode 100644
index 00000000000..aeb50c9b1ca
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/0033-spi-ath79-drop-pdata-support.patch
@@ -0,0 +1,73 @@
+From c4e197bbcecc7233aa9e553e7047fa50e4e1fe77 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Mon, 25 Jun 2018 15:52:34 +0200
+Subject: [PATCH 33/33] spi: ath79: drop pdata support
+
+The target is being converted to pure OF. We can therefore drop all of the
+platform data code from the driver.
+
+Cc: linux-spi@vger.kernel.org
+Acked-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ arch/mips/include/asm/mach-ath79/ath79_spi_platform.h | 19 -------------------
+ drivers/spi/spi-ath79.c                               |  8 --------
+ 2 files changed, 27 deletions(-)
+ delete mode 100644 arch/mips/include/asm/mach-ath79/ath79_spi_platform.h
+
+--- a/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h
++++ /dev/null
+@@ -1,19 +0,0 @@
+-/*
+- *  Platform data definition for Atheros AR71XX/AR724X/AR913X SPI controller
+- *
+- *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+- *
+- *  This program 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.
+- */
+-
+-#ifndef _ATH79_SPI_PLATFORM_H
+-#define _ATH79_SPI_PLATFORM_H
+-
+-struct ath79_spi_platform_data {
+-	unsigned	bus_num;
+-	unsigned	num_chipselect;
+-};
+-
+-#endif /* _ATH79_SPI_PLATFORM_H */
+--- a/drivers/spi/spi-ath79.c
++++ b/drivers/spi/spi-ath79.c
+@@ -26,7 +26,6 @@
+ #include <linux/err.h>
+ 
+ #include <asm/mach-ath79/ar71xx_regs.h>
+-#include <asm/mach-ath79/ath79_spi_platform.h>
+ 
+ #define DRV_NAME	"ath79-spi"
+ 
+@@ -208,7 +207,6 @@ static int ath79_spi_probe(struct platfo
+ {
+ 	struct spi_master *master;
+ 	struct ath79_spi *sp;
+-	struct ath79_spi_platform_data *pdata;
+ 	struct resource	*r;
+ 	unsigned long rate;
+ 	int ret;
+@@ -223,15 +221,9 @@ static int ath79_spi_probe(struct platfo
+ 	master->dev.of_node = pdev->dev.of_node;
+ 	platform_set_drvdata(pdev, sp);
+ 
+-	pdata = dev_get_platdata(&pdev->dev);
+-
+ 	master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
+ 	master->setup = ath79_spi_setup;
+ 	master->cleanup = ath79_spi_cleanup;
+-	if (pdata) {
+-		master->bus_num = pdata->bus_num;
+-		master->num_chipselect = pdata->num_chipselect;
+-	}
+ 
+ 	sp->bitbang.master = master;
+ 	sp->bitbang.chipselect = ath79_spi_chipselect;
diff --git a/target/linux/ath79/patches-4.19/0034-MIPS-ath79-ath9k-exports.patch b/target/linux/ath79/patches-4.19/0034-MIPS-ath79-ath9k-exports.patch
new file mode 100644
index 00000000000..6eec142c746
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/0034-MIPS-ath79-ath9k-exports.patch
@@ -0,0 +1,27 @@
+--- a/arch/mips/ath79/common.c
++++ b/arch/mips/ath79/common.c
+@@ -34,11 +34,13 @@ EXPORT_SYMBOL_GPL(ath79_ddr_freq);
+ 
+ enum ath79_soc_type ath79_soc;
+ unsigned int ath79_soc_rev;
++EXPORT_SYMBOL_GPL(ath79_soc_rev);
+ 
+ void __iomem *ath79_pll_base;
+ void __iomem *ath79_reset_base;
+ EXPORT_SYMBOL_GPL(ath79_reset_base);
+-static void __iomem *ath79_ddr_base;
++void __iomem *ath79_ddr_base;
++EXPORT_SYMBOL_GPL(ath79_ddr_base);
+ static void __iomem *ath79_ddr_wb_flush_base;
+ static void __iomem *ath79_ddr_pci_win_base;
+ 
+--- a/arch/mips/include/asm/mach-ath79/ath79.h
++++ b/arch/mips/include/asm/mach-ath79/ath79.h
+@@ -152,6 +152,7 @@ void ath79_ddr_wb_flush(unsigned int reg
+ void ath79_ddr_set_pci_windows(void);
+ 
+ extern void __iomem *ath79_pll_base;
++extern void __iomem *ath79_ddr_base;
+ extern void __iomem *ath79_reset_base;
+ 
+ static inline void ath79_pll_wr(unsigned reg, u32 val)
diff --git a/target/linux/ath79/patches-4.19/0036-GPIO-add-named-gpio-exports.patch b/target/linux/ath79/patches-4.19/0036-GPIO-add-named-gpio-exports.patch
new file mode 100644
index 00000000000..9c728b91f5e
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/0036-GPIO-add-named-gpio-exports.patch
@@ -0,0 +1,165 @@
+From 4267880319bc1a2270d352e0ded6d6386242a7ef Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Tue, 12 Aug 2014 20:49:27 +0200
+Subject: [PATCH 24/53] GPIO: add named gpio exports
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/gpio/gpiolib-of.c     |   68 +++++++++++++++++++++++++++++++++++++++++
+ drivers/gpio/gpiolib-sysfs.c  |   10 +++++-
+ include/asm-generic/gpio.h    |    6 ++++
+ include/linux/gpio/consumer.h |    8 +++++
+ 4 files changed, 91 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpio/gpiolib-of.c
++++ b/drivers/gpio/gpiolib-of.c
+@@ -23,6 +23,8 @@
+ #include <linux/pinctrl/pinctrl.h>
+ #include <linux/slab.h>
+ #include <linux/gpio/machine.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
+ 
+ #include "gpiolib.h"
+ 
+@@ -654,3 +656,68 @@ void of_gpiochip_remove(struct gpio_chip
+ 	gpiochip_remove_pin_ranges(chip);
+ 	of_node_put(chip->of_node);
+ }
++
++static struct of_device_id gpio_export_ids[] = {
++	{ .compatible = "gpio-export" },
++	{ /* sentinel */ }
++};
++
++static int of_gpio_export_probe(struct platform_device *pdev)
++{
++	struct device_node *np = pdev->dev.of_node;
++	struct device_node *cnp;
++	u32 val;
++	int nb = 0;
++
++	for_each_child_of_node(np, cnp) {
++		const char *name = NULL;
++		int gpio;
++		bool dmc;
++		int max_gpio = 1;
++		int i;
++
++		of_property_read_string(cnp, "gpio-export,name", &name);
++
++		if (!name)
++			max_gpio = of_gpio_count(cnp);
++
++		for (i = 0; i < max_gpio; i++) {
++			unsigned flags = 0;
++			enum of_gpio_flags of_flags;
++
++			gpio = of_get_gpio_flags(cnp, i, &of_flags);
++			if (!gpio_is_valid(gpio))
++				return gpio;
++
++			if (of_flags == OF_GPIO_ACTIVE_LOW)
++				flags |= GPIOF_ACTIVE_LOW;
++
++			if (!of_property_read_u32(cnp, "gpio-export,output", &val))
++				flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
++			else
++				flags |= GPIOF_IN;
++
++			if (devm_gpio_request_one(&pdev->dev, gpio, flags, name ? name : of_node_full_name(np)))
++				continue;
++
++			dmc = of_property_read_bool(cnp, "gpio-export,direction_may_change");
++			gpio_export_with_name(gpio, dmc, name);
++			nb++;
++		}
++	}
++
++	dev_info(&pdev->dev, "%d gpio(s) exported\n", nb);
++
++	return 0;
++}
++
++static struct platform_driver gpio_export_driver = {
++	.driver		= {
++		.name		= "gpio-export",
++		.owner	= THIS_MODULE,
++		.of_match_table	= of_match_ptr(gpio_export_ids),
++	},
++	.probe		= of_gpio_export_probe,
++};
++
++module_platform_driver(gpio_export_driver);
+--- a/drivers/gpio/gpiolib-sysfs.c
++++ b/drivers/gpio/gpiolib-sysfs.c
+@@ -568,7 +568,7 @@ static struct class gpio_class = {
+  *
+  * Returns zero on success, else an error.
+  */
+-int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
++int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name)
+ {
+ 	struct gpio_chip	*chip;
+ 	struct gpio_device	*gdev;
+@@ -630,6 +630,8 @@ int gpiod_export(struct gpio_desc *desc,
+ 	offset = gpio_chip_hwgpio(desc);
+ 	if (chip->names && chip->names[offset])
+ 		ioname = chip->names[offset];
++	if (name)
++		ioname = name;
+ 
+ 	dev = device_create_with_groups(&gpio_class, &gdev->dev,
+ 					MKDEV(0, 0), data, gpio_groups,
+@@ -651,6 +653,12 @@ err_unlock:
+ 	gpiod_dbg(desc, "%s: status %d\n", __func__, status);
+ 	return status;
+ }
++EXPORT_SYMBOL_GPL(__gpiod_export);
++
++int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
++{
++	return __gpiod_export(desc, direction_may_change, NULL);
++}
+ EXPORT_SYMBOL_GPL(gpiod_export);
+ 
+ static int match_export(struct device *dev, const void *desc)
+--- a/include/asm-generic/gpio.h
++++ b/include/asm-generic/gpio.h
+@@ -127,6 +127,12 @@ static inline int gpio_export(unsigned g
+ 	return gpiod_export(gpio_to_desc(gpio), direction_may_change);
+ }
+ 
++int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name);
++static inline int gpio_export_with_name(unsigned gpio, bool direction_may_change, const char *name)
++{
++	return __gpiod_export(gpio_to_desc(gpio), direction_may_change, name);
++}
++
+ static inline int gpio_export_link(struct device *dev, const char *name,
+ 				   unsigned gpio)
+ {
+--- a/include/linux/gpio/consumer.h
++++ b/include/linux/gpio/consumer.h
+@@ -531,6 +531,7 @@ struct gpio_desc *devm_fwnode_get_gpiod_
+ 
+ #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS)
+ 
++int _gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name);
+ int gpiod_export(struct gpio_desc *desc, bool direction_may_change);
+ int gpiod_export_link(struct device *dev, const char *name,
+ 		      struct gpio_desc *desc);
+@@ -538,6 +539,13 @@ void gpiod_unexport(struct gpio_desc *de
+ 
+ #else  /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */
+ 
++static inline int _gpiod_export(struct gpio_desc *desc,
++			       bool direction_may_change,
++			       const char *name)
++{
++	return -ENOSYS;
++}
++
+ static inline int gpiod_export(struct gpio_desc *desc,
+ 			       bool direction_may_change)
+ {
diff --git a/target/linux/ath79/patches-4.19/0036-MIPS-ath79-remove-irq-code-from-pci.patch b/target/linux/ath79/patches-4.19/0036-MIPS-ath79-remove-irq-code-from-pci.patch
new file mode 100644
index 00000000000..460c4580eed
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/0036-MIPS-ath79-remove-irq-code-from-pci.patch
@@ -0,0 +1,139 @@
+--- a/arch/mips/pci/pci-ar71xx.c
++++ b/arch/mips/pci/pci-ar71xx.c
+@@ -54,11 +54,9 @@
+ struct ar71xx_pci_controller {
+ 	struct device_node *np;
+ 	void __iomem *cfg_base;
+-	int irq;
+ 	struct pci_controller pci_ctrl;
+ 	struct resource io_res;
+ 	struct resource mem_res;
+-	struct irq_domain *domain;
+ };
+ 
+ /* Byte lane enable bits */
+@@ -230,104 +228,6 @@ static struct pci_ops ar71xx_pci_ops = {
+ 	.write	= ar71xx_pci_write_config,
+ };
+ 
+-static void ar71xx_pci_irq_handler(struct irq_desc *desc)
+-{
+-	void __iomem *base = ath79_reset_base;
+-	struct irq_chip *chip = irq_desc_get_chip(desc);
+-	struct ar71xx_pci_controller *apc = irq_desc_get_handler_data(desc);
+-	u32 pending;
+-
+-	chained_irq_enter(chip, desc);
+-	pending = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_STATUS) &
+-		  __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+-
+-	if (pending & AR71XX_PCI_INT_DEV0)
+-		generic_handle_irq(irq_linear_revmap(apc->domain, 1));
+-
+-	else if (pending & AR71XX_PCI_INT_DEV1)
+-		generic_handle_irq(irq_linear_revmap(apc->domain, 2));
+-
+-	else if (pending & AR71XX_PCI_INT_DEV2)
+-		generic_handle_irq(irq_linear_revmap(apc->domain, 3));
+-
+-	else if (pending & AR71XX_PCI_INT_CORE)
+-		generic_handle_irq(irq_linear_revmap(apc->domain, 4));
+-
+-	else
+-		spurious_interrupt();
+-	chained_irq_exit(chip, desc);
+-}
+-
+-static void ar71xx_pci_irq_unmask(struct irq_data *d)
+-{
+-	struct ar71xx_pci_controller *apc;
+-	unsigned int irq;
+-	void __iomem *base = ath79_reset_base;
+-	u32 t;
+-
+-	apc = irq_data_get_irq_chip_data(d);
+-	irq = irq_linear_revmap(apc->domain, d->irq);
+-
+-	t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+-	__raw_writel(t | (1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+-
+-	/* flush write */
+-	__raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+-}
+-
+-static void ar71xx_pci_irq_mask(struct irq_data *d)
+-{
+-	struct ar71xx_pci_controller *apc;
+-	unsigned int irq;
+-	void __iomem *base = ath79_reset_base;
+-	u32 t;
+-
+-	apc = irq_data_get_irq_chip_data(d);
+-	irq = irq_linear_revmap(apc->domain, d->irq);
+-
+-	t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+-	__raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+-
+-	/* flush write */
+-	__raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+-}
+-
+-static struct irq_chip ar71xx_pci_irq_chip = {
+-	.name		= "AR71XX PCI",
+-	.irq_mask	= ar71xx_pci_irq_mask,
+-	.irq_unmask	= ar71xx_pci_irq_unmask,
+-	.irq_mask_ack	= ar71xx_pci_irq_mask,
+-};
+-
+-static int ar71xx_pci_irq_map(struct irq_domain *d,
+-			      unsigned int irq, irq_hw_number_t hw)
+-{
+-	struct ar71xx_pci_controller *apc = d->host_data;
+-
+-	irq_set_chip_and_handler(irq, &ar71xx_pci_irq_chip, handle_level_irq);
+-	irq_set_chip_data(irq, apc);
+-
+-	return 0;
+-}
+-
+-static const struct irq_domain_ops ar71xx_pci_domain_ops = {
+-	.xlate = irq_domain_xlate_onecell,
+-	.map = ar71xx_pci_irq_map,
+-};
+-
+-static void ar71xx_pci_irq_init(struct ar71xx_pci_controller *apc)
+-{
+-	void __iomem *base = ath79_reset_base;
+-
+-	__raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+-	__raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_STATUS);
+-
+-	apc->domain = irq_domain_add_linear(apc->np, AR71XX_PCI_IRQ_COUNT,
+-					    &ar71xx_pci_domain_ops, apc);
+-	irq_set_chained_handler_and_data(apc->irq, ar71xx_pci_irq_handler,
+-					 apc);
+-}
+-
+ static void ar71xx_pci_reset(void)
+ {
+ 	ath79_device_reset_set(AR71XX_RESET_PCI_BUS | AR71XX_RESET_PCI_CORE);
+@@ -361,10 +261,6 @@ static int ar71xx_pci_probe(struct platf
+ 	if (IS_ERR(apc->cfg_base))
+ 		return PTR_ERR(apc->cfg_base);
+ 
+-	apc->irq = platform_get_irq(pdev, 0);
+-	if (apc->irq < 0)
+-		return -EINVAL;
+-
+ 	ar71xx_pci_reset();
+ 
+ 	/* setup COMMAND register */
+@@ -375,8 +271,6 @@ static int ar71xx_pci_probe(struct platf
+ 	/* clear bus errors */
+ 	ar71xx_pci_check_error(apc, 1);
+ 
+-	ar71xx_pci_irq_init(apc);
+-
+ 	apc->np = pdev->dev.of_node;
+ 	apc->pci_ctrl.pci_ops = &ar71xx_pci_ops;
+ 	apc->pci_ctrl.mem_resource = &apc->mem_res;
diff --git a/target/linux/ath79/patches-4.19/0037-missing-registers.patch b/target/linux/ath79/patches-4.19/0037-missing-registers.patch
new file mode 100644
index 00000000000..9fde3d39df9
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/0037-missing-registers.patch
@@ -0,0 +1,21 @@
+commit f3ffac90bc7266b7d917616f3233f58e8c08a196
+Author: Christian Lamparter <chunkeey@gmail.com>
+Date:   Fri Aug 10 23:24:47 2018 +0200
+
+    ath79: gmac: add parsers for rxd(v)- and tx(d|en)-delay for AR9344
+
+    Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
+
+--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
++++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
+@@ -1229,6 +1229,10 @@
+ #define AR934X_ETH_CFG_RDV_DELAY        BIT(16)
+ #define AR934X_ETH_CFG_RDV_DELAY_MASK   0x3
+ #define AR934X_ETH_CFG_RDV_DELAY_SHIFT  16
++#define AR934X_ETH_CFG_TXD_DELAY_MASK   0x3
++#define AR934X_ETH_CFG_TXD_DELAY_SHIFT  18
++#define AR934X_ETH_CFG_TXE_DELAY_MASK   0x3
++#define AR934X_ETH_CFG_TXE_DELAY_SHIFT  20
+ 
+ /*
+  * QCA953X GMAC Interface
diff --git a/target/linux/ath79/patches-4.19/004-register_gpio_driver_earlier.patch b/target/linux/ath79/patches-4.19/004-register_gpio_driver_earlier.patch
new file mode 100644
index 00000000000..78899c45e3d
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/004-register_gpio_driver_earlier.patch
@@ -0,0 +1,18 @@
+HACK: register the GPIO driver earlier to ensure that gpio_request calls
+from mach files succeed.
+
+--- a/drivers/gpio/gpio-ath79.c
++++ b/drivers/gpio/gpio-ath79.c
+@@ -325,7 +325,11 @@ static struct platform_driver ath79_gpio
+ 	.remove = ath79_gpio_remove,
+ };
+ 
+-module_platform_driver(ath79_gpio_driver);
++static int __init ath79_gpio_init(void)
++{
++	return platform_driver_register(&ath79_gpio_driver);
++}
++postcore_initcall(ath79_gpio_init);
+ 
+ MODULE_DESCRIPTION("Atheros AR71XX/AR724X/AR913X GPIO API support");
+ MODULE_LICENSE("GPL v2");
diff --git a/target/linux/ath79/patches-4.19/403-mtd_fix_cfi_cmdset_0002_status_check.patch b/target/linux/ath79/patches-4.19/403-mtd_fix_cfi_cmdset_0002_status_check.patch
new file mode 100644
index 00000000000..eeda6209573
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/403-mtd_fix_cfi_cmdset_0002_status_check.patch
@@ -0,0 +1,64 @@
+--- a/drivers/mtd/chips/cfi_cmdset_0002.c
++++ b/drivers/mtd/chips/cfi_cmdset_0002.c
+@@ -1634,8 +1634,8 @@ static int __xipram do_write_oneword(str
+ 			break;
+ 		}
+ 
+-		if (chip_ready(map, adr))
+-			break;
++		if (chip_good(map, adr, datum))
++			goto enable_xip;
+ 
+ 		/* Latency issues. Drop the lock, wait a while and retry */
+ 		UDELAY(map, chip, adr, 1);
+@@ -1651,6 +1651,8 @@ static int __xipram do_write_oneword(str
+ 
+ 		ret = -EIO;
+ 	}
++
++ enable_xip:
+ 	xip_enable(map, chip, adr);
+  op_done:
+ 	if (mode == FL_OTP_WRITE)
+@@ -2229,7 +2231,6 @@ static int cfi_amdstd_panic_write(struct
+ 	return 0;
+ }
+ 
+-
+ /*
+  * Handle devices with one erase region, that only implement
+  * the chip erase command.
+@@ -2297,7 +2298,7 @@ static int __xipram do_erase_chip(struct
+ 		}
+ 
+ 		if (chip_good(map, adr, map_word_ff(map)))
+-			break;
++			goto op_done;
+ 
+ 		if (time_after(jiffies, timeo)) {
+ 			printk(KERN_WARNING "MTD %s(): software timeout\n",
+@@ -2321,6 +2322,7 @@ static int __xipram do_erase_chip(struct
+ 		}
+ 	}
+ 
++ op_done:
+ 	chip->state = FL_READY;
+ 	xip_enable(map, chip, adr);
+ 	DISABLE_VPP(map);
+@@ -2393,7 +2395,7 @@ static int __xipram do_erase_oneblock(st
+ 		}
+ 
+ 		if (chip_good(map, adr, map_word_ff(map)))
+-			break;
++			goto op_done;
+ 
+ 		if (time_after(jiffies, timeo)) {
+ 			printk(KERN_WARNING "MTD %s(): software timeout\n",
+@@ -2417,6 +2419,7 @@ static int __xipram do_erase_oneblock(st
+ 		}
+ 	}
+ 
++ op_done:
+ 	chip->state = FL_READY;
+ 	xip_enable(map, chip, adr);
+ 	DISABLE_VPP(map);
diff --git a/target/linux/ath79/patches-4.19/404-mtd-cybertan-trx-parser.patch b/target/linux/ath79/patches-4.19/404-mtd-cybertan-trx-parser.patch
new file mode 100644
index 00000000000..22e31db3fab
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/404-mtd-cybertan-trx-parser.patch
@@ -0,0 +1,20 @@
+--- a/drivers/mtd/parsers/Makefile
++++ b/drivers/mtd/parsers/Makefile
+@@ -1,2 +1,3 @@
++obj-$(CONFIG_MTD_PARSER_CYBERTAN)	+= parser_cybertan.o
+ obj-$(CONFIG_MTD_PARSER_TRX)		+= parser_trx.o
+ obj-$(CONFIG_MTD_SHARPSL_PARTS)		+= sharpslpart.o
+--- a/drivers/mtd/parsers/Kconfig
++++ b/drivers/mtd/parsers/Kconfig
+@@ -1,3 +1,11 @@
++config MTD_PARSER_CYBERTAN
++	tristate "Parser for Cybertan format partitions"
++	depends on MTD && (ATH79 || COMPILE_TEST)
++	help
++	  Cybertan has a proprietory header than encompasses a Broadcom trx
++	  header. This driver will parse the header and take care of the
++	  special offsets that result in the extra headers.
++
+ config MTD_PARSER_TRX
+ 	tristate "Parser for TRX format partitions"
+ 	depends on MTD && (BCM47XX || ARCH_BCM_5301X || COMPILE_TEST)
diff --git a/target/linux/ath79/patches-4.19/405-mtd-tp-link-partition-parser.patch b/target/linux/ath79/patches-4.19/405-mtd-tp-link-partition-parser.patch
new file mode 100644
index 00000000000..16fe5ed2720
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/405-mtd-tp-link-partition-parser.patch
@@ -0,0 +1,25 @@
+--- a/drivers/mtd/Kconfig
++++ b/drivers/mtd/Kconfig
+@@ -193,6 +193,12 @@ config MTD_MYLOADER_PARTS
+ 	  You will still need the parsing functions to be called by the driver
+ 	  for your particular device. It won't happen automatically.
+ 
++config MTD_TPLINK_PARTS
++	tristate "TP-Link AR7XXX/AR9XXX partitioning support"
++	depends on ATH79
++	---help---
++	  TBD.
++
+ comment "User Modules And Translation Layers"
+ 
+ #
+--- a/drivers/mtd/Makefile
++++ b/drivers/mtd/Makefile
+@@ -18,6 +18,7 @@ obj-$(CONFIG_MTD_BCM63XX_PARTS)	+= bcm63
+ obj-$(CONFIG_MTD_BCM47XX_PARTS)	+= bcm47xxpart.o
+ obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o
+ obj-y				+= parsers/
++obj-$(CONFIG_MTD_TPLINK_PARTS)	+= tplinkpart.o
+ 
+ # 'Users' - code which presents functionality to userspace.
+ obj-$(CONFIG_MTD_BLKDEVS)	+= mtd_blkdevs.o
diff --git a/target/linux/ath79/patches-4.19/420-net-ar71xx_mac_driver.patch b/target/linux/ath79/patches-4.19/420-net-ar71xx_mac_driver.patch
new file mode 100644
index 00000000000..6377db0ac22
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/420-net-ar71xx_mac_driver.patch
@@ -0,0 +1,28 @@
+--- a/drivers/net/ethernet/atheros/Kconfig
++++ b/drivers/net/ethernet/atheros/Kconfig
+@@ -5,7 +5,7 @@
+ config NET_VENDOR_ATHEROS
+ 	bool "Atheros devices"
+ 	default y
+-	depends on PCI
++	depends on (PCI || ATH79)
+ 	---help---
+ 	  If you have a network (Ethernet) card belonging to this class, say Y.
+ 
+@@ -78,4 +78,6 @@ config ALX
+ 	  To compile this driver as a module, choose M here.  The module
+ 	  will be called alx.
+ 
++source drivers/net/ethernet/atheros/ag71xx/Kconfig
++
+ endif # NET_VENDOR_ATHEROS
+--- a/drivers/net/ethernet/atheros/Makefile
++++ b/drivers/net/ethernet/atheros/Makefile
+@@ -3,6 +3,7 @@
+ # Makefile for the Atheros network device drivers.
+ #
+ 
++obj-$(CONFIG_AG71XX) += ag71xx/
+ obj-$(CONFIG_ATL1) += atlx/
+ obj-$(CONFIG_ATL2) += atlx/
+ obj-$(CONFIG_ATL1E) += atl1e/
diff --git a/target/linux/ath79/patches-4.19/430-drivers-link-spi-before-mtd.patch b/target/linux/ath79/patches-4.19/430-drivers-link-spi-before-mtd.patch
new file mode 100644
index 00000000000..4c6558db90c
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/430-drivers-link-spi-before-mtd.patch
@@ -0,0 +1,12 @@
+--- a/drivers/Makefile
++++ b/drivers/Makefile
+@@ -80,8 +80,8 @@ obj-y				+= scsi/
+ obj-y				+= nvme/
+ obj-$(CONFIG_ATA)		+= ata/
+ obj-$(CONFIG_TARGET_CORE)	+= target/
+-obj-$(CONFIG_MTD)		+= mtd/
+ obj-$(CONFIG_SPI)		+= spi/
++obj-$(CONFIG_MTD)		+= mtd/
+ obj-$(CONFIG_SPMI)		+= spmi/
+ obj-$(CONFIG_HSI)		+= hsi/
+ obj-$(CONFIG_SLIMBUS)		+= slimbus/
diff --git a/target/linux/ath79/patches-4.19/470-MIPS-ath79-swizzle-pci-address-for-ar71xx.patch b/target/linux/ath79/patches-4.19/470-MIPS-ath79-swizzle-pci-address-for-ar71xx.patch
new file mode 100644
index 00000000000..634ce563542
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/470-MIPS-ath79-swizzle-pci-address-for-ar71xx.patch
@@ -0,0 +1,98 @@
+--- /dev/null
++++ b/arch/mips/include/asm/mach-ath79/mangle-port.h
+@@ -0,0 +1,37 @@
++/*
++ *  Copyright (C) 2012 Gabor Juhos <juhosg@openwrt.org>
++ *
++ *  This file was derived from: inlude/asm-mips/mach-generic/mangle-port.h
++ *      Copyright (C) 2003, 2004 Ralf Baechle
++ *
++ *  This program 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.
++ */
++
++#ifndef __ASM_MACH_ATH79_MANGLE_PORT_H
++#define __ASM_MACH_ATH79_MANGLE_PORT_H
++
++#ifdef CONFIG_PCI_AR71XX
++extern unsigned long (ath79_pci_swizzle_b)(unsigned long port);
++extern unsigned long (ath79_pci_swizzle_w)(unsigned long port);
++#else
++#define ath79_pci_swizzle_b(port) (port)
++#define ath79_pci_swizzle_w(port) (port)
++#endif
++
++#define __swizzle_addr_b(port)	ath79_pci_swizzle_b(port)
++#define __swizzle_addr_w(port)	ath79_pci_swizzle_w(port)
++#define __swizzle_addr_l(port)	(port)
++#define __swizzle_addr_q(port)	(port)
++
++# define ioswabb(a, x)           (x)
++# define __mem_ioswabb(a, x)     (x)
++# define ioswabw(a, x)           (x)
++# define __mem_ioswabw(a, x)     cpu_to_le16(x)
++# define ioswabl(a, x)           (x)
++# define __mem_ioswabl(a, x)     cpu_to_le32(x)
++# define ioswabq(a, x)           (x)
++# define __mem_ioswabq(a, x)     cpu_to_le64(x)
++
++#endif /* __ASM_MACH_ATH79_MANGLE_PORT_H */
+--- a/arch/mips/pci/pci-ar71xx.c
++++ b/arch/mips/pci/pci-ar71xx.c
+@@ -71,6 +71,45 @@ static const u32 ar71xx_pci_read_mask[8]
+ 	0, 0xff, 0xffff, 0, 0xffffffff, 0, 0, 0
+ };
+ 
++static unsigned long (*__ath79_pci_swizzle_b)(unsigned long port);
++static unsigned long (*__ath79_pci_swizzle_w)(unsigned long port);
++
++static inline bool ar71xx_is_pci_addr(unsigned long port)
++{
++	unsigned long phys = CPHYSADDR(port);
++
++	return (phys >= AR71XX_PCI_MEM_BASE &&
++		phys < AR71XX_PCI_MEM_BASE + AR71XX_PCI_MEM_SIZE);
++}
++
++static unsigned long ar71xx_pci_swizzle_b(unsigned long port)
++{
++	return ar71xx_is_pci_addr(port) ? port ^ 3 : port;
++}
++
++static unsigned long ar71xx_pci_swizzle_w(unsigned long port)
++{
++	return ar71xx_is_pci_addr(port) ? port ^ 2 : port;
++}
++
++unsigned long ath79_pci_swizzle_b(unsigned long port)
++{
++	if (__ath79_pci_swizzle_b)
++		return __ath79_pci_swizzle_b(port);
++
++	return port;
++}
++EXPORT_SYMBOL(ath79_pci_swizzle_b);
++
++unsigned long ath79_pci_swizzle_w(unsigned long port)
++{
++	if (__ath79_pci_swizzle_w)
++		return __ath79_pci_swizzle_w(port);
++
++	return port;
++}
++EXPORT_SYMBOL(ath79_pci_swizzle_w);
++
+ static inline u32 ar71xx_pci_get_ble(int where, int size, int local)
+ {
+ 	u32 t;
+@@ -279,6 +318,9 @@ static int ar71xx_pci_probe(struct platf
+ 
+ 	register_pci_controller(&apc->pci_ctrl);
+ 
++	__ath79_pci_swizzle_b = ar71xx_pci_swizzle_b;
++	__ath79_pci_swizzle_w = ar71xx_pci_swizzle_w;
++
+ 	return 0;
+ }
+ 
diff --git a/target/linux/ath79/patches-4.19/490-usb-ehci-add-quirks-for-qca-socs.patch b/target/linux/ath79/patches-4.19/490-usb-ehci-add-quirks-for-qca-socs.patch
new file mode 100644
index 00000000000..4e2a6fecee7
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/490-usb-ehci-add-quirks-for-qca-socs.patch
@@ -0,0 +1,103 @@
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -239,6 +239,37 @@ int ehci_reset(struct ehci_hcd *ehci)
+ 	command |= CMD_RESET;
+ 	dbg_cmd (ehci, "reset", command);
+ 	ehci_writel(ehci, command, &ehci->regs->command);
++
++	if (ehci->qca_force_host_mode) {
++		u32 usbmode;
++
++		udelay(1000);
++
++		usbmode = ehci_readl(ehci, &ehci->regs->usbmode);
++		usbmode |= USBMODE_CM_HC | (1 << 4);
++		ehci_writel(ehci, usbmode, &ehci->regs->usbmode);
++
++		ehci_dbg(ehci, "forced host mode, usbmode: %08x\n",
++			 ehci_readl(ehci, &ehci->regs->usbmode));
++	}
++
++	if (ehci->qca_force_16bit_ptw) {
++		u32 port_status;
++
++		udelay(1000);
++
++		/* enable 16-bit UTMI interface */
++		port_status = ehci_readl(ehci, &ehci->regs->port_status[0]);
++		port_status |= BIT(28);
++		ehci_writel(ehci, port_status, &ehci->regs->port_status[0]);
++
++		ehci_dbg(ehci, "16-bit UTMI interface enabled, status: %08x\n",
++			 ehci_readl(ehci, &ehci->regs->port_status[0]));
++	}
++
++	if (ehci->reset_notifier)
++		ehci->reset_notifier(ehci_to_hcd(ehci));
++
+ 	ehci->rh_state = EHCI_RH_HALTED;
+ 	ehci->next_statechange = jiffies;
+ 	retval = ehci_handshake(ehci, &ehci->regs->command,
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -219,6 +219,10 @@ struct ehci_hcd {			/* one per controlle
+ 	unsigned		need_oc_pp_cycle:1; /* MPC834X port power */
+ 	unsigned		imx28_write_fix:1; /* For Freescale i.MX28 */
+ 	unsigned		ignore_oc:1;
++	unsigned		qca_force_host_mode:1;
++	unsigned		qca_force_16bit_ptw:1; /* force 16 bit UTMI */
++
++	void (*reset_notifier)(struct usb_hcd *hcd);
+ 
+ 	/* required for usb32 quirk */
+ 	#define OHCI_CTRL_HCFS          (3 << 6)
+--- a/include/linux/usb/ehci_pdriver.h
++++ b/include/linux/usb/ehci_pdriver.h
+@@ -51,6 +51,8 @@ struct usb_ehci_pdata {
+ 	unsigned	reset_on_resume:1;
+ 	unsigned	dma_mask_64:1;
+ 	unsigned	ignore_oc:1;
++	unsigned	qca_force_host_mode:1;
++	unsigned	qca_force_16bit_ptw:1;
+ 
+ 	/* Turn on all power and clocks */
+ 	int (*power_on)(struct platform_device *pdev);
+@@ -60,6 +62,7 @@ struct usb_ehci_pdata {
+ 	 * turn off everything else */
+ 	void (*power_suspend)(struct platform_device *pdev);
+ 	int (*pre_setup)(struct usb_hcd *hcd);
++	void (*reset_notifier)(struct platform_device *pdev);
+ };
+ 
+ #endif /* __USB_CORE_EHCI_PDRIVER_H */
+--- a/drivers/usb/host/ehci-platform.c
++++ b/drivers/usb/host/ehci-platform.c
+@@ -48,6 +48,14 @@ struct ehci_platform_priv {
+ 
+ static const char hcd_name[] = "ehci-platform";
+ 
++static void ehci_platform_reset_notifier(struct usb_hcd *hcd)
++{
++	struct platform_device *pdev = to_platform_device(hcd->self.controller);
++	struct usb_ehci_pdata *pdata = pdev->dev.platform_data;
++
++	pdata->reset_notifier(pdev);
++}
++
+ static int ehci_platform_reset(struct usb_hcd *hcd)
+ {
+ 	struct platform_device *pdev = to_platform_device(hcd->self.controller);
+@@ -215,6 +223,13 @@ static int ehci_platform_probe(struct pl
+ 		priv->reset_on_resume = true;
+ 	if (pdata->ignore_oc)
+ 		ehci->ignore_oc = 1;
++	if (pdata->qca_force_host_mode)
++		ehci->qca_force_host_mode = 1;
++	if (pdata->qca_force_16bit_ptw)
++		ehci->qca_force_16bit_ptw = 1;
++
++	if (pdata->reset_notifier)
++		ehci->reset_notifier = ehci_platform_reset_notifier;
+ 
+ #ifndef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
+ 	if (ehci->big_endian_mmio) {
diff --git a/target/linux/ath79/patches-4.19/900-mdio_bitbang_ignore_ta_value.patch b/target/linux/ath79/patches-4.19/900-mdio_bitbang_ignore_ta_value.patch
new file mode 100644
index 00000000000..8f8f349a660
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/900-mdio_bitbang_ignore_ta_value.patch
@@ -0,0 +1,32 @@
+--- a/drivers/net/phy/mdio-bitbang.c
++++ b/drivers/net/phy/mdio-bitbang.c
+@@ -155,7 +155,7 @@ static int mdiobb_cmd_addr(struct mdiobb
+ static int mdiobb_read(struct mii_bus *bus, int phy, int reg)
+ {
+ 	struct mdiobb_ctrl *ctrl = bus->priv;
+-	int ret, i;
++	int ret;
+ 
+ 	if (reg & MII_ADDR_C45) {
+ 		reg = mdiobb_cmd_addr(ctrl, phy, reg);
+@@ -165,19 +165,7 @@ static int mdiobb_read(struct mii_bus *b
+ 
+ 	ctrl->ops->set_mdio_dir(ctrl, 0);
+ 
+-	/* check the turnaround bit: the PHY should be driving it to zero, if this
+-	 * PHY is listed in phy_ignore_ta_mask as having broken TA, skip that
+-	 */
+-	if (mdiobb_get_bit(ctrl) != 0 &&
+-	    !(bus->phy_ignore_ta_mask & (1 << phy))) {
+-		/* PHY didn't drive TA low -- flush any bits it
+-		 * may be trying to send.
+-		 */
+-		for (i = 0; i < 32; i++)
+-			mdiobb_get_bit(ctrl);
+-
+-		return 0xffff;
+-	}
++	mdiobb_get_bit(ctrl);
+ 
+ 	ret = mdiobb_get_num(ctrl, 16);
+ 	mdiobb_get_bit(ctrl);
diff --git a/target/linux/ath79/patches-4.19/901-phy-mdio-bitbang-prevent-rescheduling-during-command.patch b/target/linux/ath79/patches-4.19/901-phy-mdio-bitbang-prevent-rescheduling-during-command.patch
new file mode 100644
index 00000000000..a830346a31e
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/901-phy-mdio-bitbang-prevent-rescheduling-during-command.patch
@@ -0,0 +1,61 @@
+From 66e584435ac0de6e0abeb6d7166fe4fe25d6bb73 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jogo@openwrt.org>
+Date: Tue, 16 Jun 2015 13:15:08 +0200
+Subject: [PATCH] phy/mdio-bitbang: prevent rescheduling during command
+
+It seems some phys have some maximum timings for accessing the MDIO line,
+resulting in bit errors under cpu stress. Prevent this from happening by
+disabling interrupts when sending commands.
+
+Signed-off-by: Jonas Gorski <jogo@openwrt.org>
+---
+ drivers/net/phy/mdio-bitbang.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/drivers/net/phy/mdio-bitbang.c
++++ b/drivers/net/phy/mdio-bitbang.c
+@@ -17,6 +17,7 @@
+  * kind, whether express or implied.
+  */
+ 
++#include <linux/irqflags.h>
+ #include <linux/module.h>
+ #include <linux/mdio-bitbang.h>
+ #include <linux/types.h>
+@@ -156,7 +157,9 @@ static int mdiobb_read(struct mii_bus *b
+ {
+ 	struct mdiobb_ctrl *ctrl = bus->priv;
+ 	int ret;
++	unsigned long flags;
+ 
++	local_irq_save(flags);
+ 	if (reg & MII_ADDR_C45) {
+ 		reg = mdiobb_cmd_addr(ctrl, phy, reg);
+ 		mdiobb_cmd(ctrl, MDIO_C45_READ, phy, reg);
+@@ -169,13 +172,17 @@ static int mdiobb_read(struct mii_bus *b
+ 
+ 	ret = mdiobb_get_num(ctrl, 16);
+ 	mdiobb_get_bit(ctrl);
++	local_irq_restore(flags);
++
+ 	return ret;
+ }
+ 
+ static int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val)
+ {
+ 	struct mdiobb_ctrl *ctrl = bus->priv;
++	unsigned long flags;
+ 
++	local_irq_save(flags);
+ 	if (reg & MII_ADDR_C45) {
+ 		reg = mdiobb_cmd_addr(ctrl, phy, reg);
+ 		mdiobb_cmd(ctrl, MDIO_C45_WRITE, phy, reg);
+@@ -190,6 +197,8 @@ static int mdiobb_write(struct mii_bus *
+ 
+ 	ctrl->ops->set_mdio_dir(ctrl, 0);
+ 	mdiobb_get_bit(ctrl);
++	local_irq_restore(flags);
++
+ 	return 0;
+ }
+ 
diff --git a/target/linux/ath79/patches-4.19/910-unaligned_access_hacks.patch b/target/linux/ath79/patches-4.19/910-unaligned_access_hacks.patch
new file mode 100644
index 00000000000..dcc0e8b3c6a
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/910-unaligned_access_hacks.patch
@@ -0,0 +1,891 @@
+--- a/arch/mips/include/asm/checksum.h
++++ b/arch/mips/include/asm/checksum.h
+@@ -134,26 +134,30 @@ static inline __sum16 ip_fast_csum(const
+ 	const unsigned int *stop = word + ihl;
+ 	unsigned int csum;
+ 	int carry;
++	unsigned int w;
+ 
+-	csum = word[0];
+-	csum += word[1];
+-	carry = (csum < word[1]);
++	csum = net_hdr_word(word++);
++
++	w = net_hdr_word(word++);
++	csum += w;
++	carry = (csum < w);
+ 	csum += carry;
+ 
+-	csum += word[2];
+-	carry = (csum < word[2]);
++	w = net_hdr_word(word++);
++	csum += w;
++	carry = (csum < w);
+ 	csum += carry;
+ 
+-	csum += word[3];
+-	carry = (csum < word[3]);
++	w = net_hdr_word(word++);
++	csum += w;
++	carry = (csum < w);
+ 	csum += carry;
+ 
+-	word += 4;
+ 	do {
+-		csum += *word;
+-		carry = (csum < *word);
++		w = net_hdr_word(word++);
++		csum += w;
++		carry = (csum < w);
+ 		csum += carry;
+-		word++;
+ 	} while (word != stop);
+ 
+ 	return csum_fold(csum);
+@@ -214,73 +218,6 @@ static inline __sum16 ip_compute_csum(co
+ 	return csum_fold(csum_partial(buff, len, 0));
+ }
+ 
+-#define _HAVE_ARCH_IPV6_CSUM
+-static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+-					  const struct in6_addr *daddr,
+-					  __u32 len, __u8 proto,
+-					  __wsum sum)
+-{
+-	__wsum tmp;
+-
+-	__asm__(
+-	"	.set	push		# csum_ipv6_magic\n"
+-	"	.set	noreorder	\n"
+-	"	.set	noat		\n"
+-	"	addu	%0, %5		# proto (long in network byte order)\n"
+-	"	sltu	$1, %0, %5	\n"
+-	"	addu	%0, $1		\n"
+-
+-	"	addu	%0, %6		# csum\n"
+-	"	sltu	$1, %0, %6	\n"
+-	"	lw	%1, 0(%2)	# four words source address\n"
+-	"	addu	%0, $1		\n"
+-	"	addu	%0, %1		\n"
+-	"	sltu	$1, %0, %1	\n"
+-
+-	"	lw	%1, 4(%2)	\n"
+-	"	addu	%0, $1		\n"
+-	"	addu	%0, %1		\n"
+-	"	sltu	$1, %0, %1	\n"
+-
+-	"	lw	%1, 8(%2)	\n"
+-	"	addu	%0, $1		\n"
+-	"	addu	%0, %1		\n"
+-	"	sltu	$1, %0, %1	\n"
+-
+-	"	lw	%1, 12(%2)	\n"
+-	"	addu	%0, $1		\n"
+-	"	addu	%0, %1		\n"
+-	"	sltu	$1, %0, %1	\n"
+-
+-	"	lw	%1, 0(%3)	\n"
+-	"	addu	%0, $1		\n"
+-	"	addu	%0, %1		\n"
+-	"	sltu	$1, %0, %1	\n"
+-
+-	"	lw	%1, 4(%3)	\n"
+-	"	addu	%0, $1		\n"
+-	"	addu	%0, %1		\n"
+-	"	sltu	$1, %0, %1	\n"
+-
+-	"	lw	%1, 8(%3)	\n"
+-	"	addu	%0, $1		\n"
+-	"	addu	%0, %1		\n"
+-	"	sltu	$1, %0, %1	\n"
+-
+-	"	lw	%1, 12(%3)	\n"
+-	"	addu	%0, $1		\n"
+-	"	addu	%0, %1		\n"
+-	"	sltu	$1, %0, %1	\n"
+-
+-	"	addu	%0, $1		# Add final carry\n"
+-	"	.set	pop"
+-	: "=&r" (sum), "=&r" (tmp)
+-	: "r" (saddr), "r" (daddr),
+-	  "0" (htonl(len)), "r" (htonl(proto)), "r" (sum));
+-
+-	return csum_fold(sum);
+-}
+-
+ #include <asm-generic/checksum.h>
+ #endif /* CONFIG_GENERIC_CSUM */
+ 
+--- a/include/uapi/linux/ip.h
++++ b/include/uapi/linux/ip.h
+@@ -103,7 +103,7 @@ struct iphdr {
+ 	__be32	saddr;
+ 	__be32	daddr;
+ 	/*The options start here. */
+-};
++} __attribute__((packed, aligned(2)));
+ 
+ 
+ struct ip_auth_hdr {
+--- a/include/uapi/linux/ipv6.h
++++ b/include/uapi/linux/ipv6.h
+@@ -131,7 +131,7 @@ struct ipv6hdr {
+ 
+ 	struct	in6_addr	saddr;
+ 	struct	in6_addr	daddr;
+-};
++} __attribute__((packed, aligned(2)));
+ 
+ 
+ /* index values for the variables in ipv6_devconf */
+--- a/include/uapi/linux/tcp.h
++++ b/include/uapi/linux/tcp.h
+@@ -55,7 +55,7 @@ struct tcphdr {
+ 	__be16	window;
+ 	__sum16	check;
+ 	__be16	urg_ptr;
+-};
++} __attribute__((packed, aligned(2)));
+ 
+ /*
+  *	The union cast uses a gcc extension to avoid aliasing problems
+@@ -65,7 +65,7 @@ struct tcphdr {
+ union tcp_word_hdr { 
+ 	struct tcphdr hdr;
+ 	__be32 		  words[5];
+-}; 
++} __attribute__((packed, aligned(2)));
+ 
+ #define tcp_flag_word(tp) ( ((union tcp_word_hdr *)(tp))->words [3]) 
+ 
+--- a/include/uapi/linux/udp.h
++++ b/include/uapi/linux/udp.h
+@@ -25,7 +25,7 @@ struct udphdr {
+ 	__be16	dest;
+ 	__be16	len;
+ 	__sum16	check;
+-};
++} __attribute__((packed, aligned(2)));
+ 
+ /* UDP socket options */
+ #define UDP_CORK	1	/* Never send partially complete segments */
+--- a/net/netfilter/nf_conntrack_core.c
++++ b/net/netfilter/nf_conntrack_core.c
+@@ -262,8 +262,8 @@ static bool ipv4_pkt_to_tuple(const stru
+ 
+ 	switch (l3num) {
+ 	case NFPROTO_IPV4:
+-		tuple->src.u3.ip = ap[0];
+-		tuple->dst.u3.ip = ap[1];
++		tuple->src.u3.ip = net_hdr_word(ap++);
++		tuple->dst.u3.ip = net_hdr_word(ap);
+ 		break;
+ 	case NFPROTO_IPV6:
+ 		memcpy(tuple->src.u3.ip6, ap, sizeof(tuple->src.u3.ip6));
+--- a/include/uapi/linux/icmp.h
++++ b/include/uapi/linux/icmp.h
+@@ -82,7 +82,7 @@ struct icmphdr {
+ 	} frag;
+ 	__u8	reserved[4];
+   } un;
+-};
++} __attribute__((packed, aligned(2)));
+ 
+ 
+ /*
+--- a/include/uapi/linux/in6.h
++++ b/include/uapi/linux/in6.h
+@@ -43,7 +43,7 @@ struct in6_addr {
+ #define s6_addr16		in6_u.u6_addr16
+ #define s6_addr32		in6_u.u6_addr32
+ #endif
+-};
++} __attribute__((packed, aligned(2)));
+ #endif /* __UAPI_DEF_IN6_ADDR */
+ 
+ #if __UAPI_DEF_SOCKADDR_IN6
+--- a/net/ipv6/tcp_ipv6.c
++++ b/net/ipv6/tcp_ipv6.c
+@@ -39,6 +39,7 @@
+ #include <linux/ipsec.h>
+ #include <linux/times.h>
+ #include <linux/slab.h>
++#include <asm/unaligned.h>
+ #include <linux/uaccess.h>
+ #include <linux/ipv6.h>
+ #include <linux/icmpv6.h>
+@@ -836,10 +837,10 @@ static void tcp_v6_send_response(const s
+ 	topt = (__be32 *)(t1 + 1);
+ 
+ 	if (tsecr) {
+-		*topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
+-				(TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
+-		*topt++ = htonl(tsval);
+-		*topt++ = htonl(tsecr);
++		put_unaligned_be32((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
++				(TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP, topt++);
++		put_unaligned_be32(tsval, topt++);
++		put_unaligned_be32(tsecr, topt++);
+ 	}
+ 
+ #ifdef CONFIG_TCP_MD5SIG
+--- a/include/linux/ipv6.h
++++ b/include/linux/ipv6.h
+@@ -6,6 +6,7 @@
+ 
+ #define ipv6_optlen(p)  (((p)->hdrlen+1) << 3)
+ #define ipv6_authlen(p) (((p)->hdrlen+2) << 2)
++
+ /*
+  * This structure contains configuration options per IPv6 link.
+  */
+--- a/net/ipv6/datagram.c
++++ b/net/ipv6/datagram.c
+@@ -477,7 +477,7 @@ int ipv6_recv_error(struct sock *sk, str
+ 				ipv6_iface_scope_id(&sin->sin6_addr,
+ 						    IP6CB(skb)->iif);
+ 		} else {
+-			ipv6_addr_set_v4mapped(*(__be32 *)(nh + serr->addr_offset),
++			ipv6_addr_set_v4mapped(net_hdr_word(nh + serr->addr_offset),
+ 					       &sin->sin6_addr);
+ 			sin->sin6_scope_id = 0;
+ 		}
+@@ -829,12 +829,12 @@ int ip6_datagram_send_ctl(struct net *ne
+ 			}
+ 
+ 			if (fl6->flowlabel&IPV6_FLOWINFO_MASK) {
+-				if ((fl6->flowlabel^*(__be32 *)CMSG_DATA(cmsg))&~IPV6_FLOWINFO_MASK) {
++				if ((fl6->flowlabel^net_hdr_word(CMSG_DATA(cmsg)))&~IPV6_FLOWINFO_MASK) {
+ 					err = -EINVAL;
+ 					goto exit_f;
+ 				}
+ 			}
+-			fl6->flowlabel = IPV6_FLOWINFO_MASK & *(__be32 *)CMSG_DATA(cmsg);
++			fl6->flowlabel = IPV6_FLOWINFO_MASK & net_hdr_word(CMSG_DATA(cmsg));
+ 			break;
+ 
+ 		case IPV6_2292HOPOPTS:
+--- a/net/ipv6/ip6_gre.c
++++ b/net/ipv6/ip6_gre.c
+@@ -452,7 +452,7 @@ static void ip6gre_err(struct sk_buff *s
+ 		return;
+ 	ipv6h = (const struct ipv6hdr *)skb->data;
+ 	greh = (const struct gre_base_hdr *)(skb->data + offset);
+-	key = key_off ? *(__be32 *)(skb->data + key_off) : 0;
++	key = key_off ? net_hdr_word((__be32 *)(skb->data + key_off)) : 0;
+ 
+ 	t = ip6gre_tunnel_lookup(skb->dev, &ipv6h->daddr, &ipv6h->saddr,
+ 				 key, greh->protocol);
+--- a/net/ipv6/exthdrs.c
++++ b/net/ipv6/exthdrs.c
+@@ -756,7 +756,7 @@ static bool ipv6_hop_jumbo(struct sk_buf
+ 		goto drop;
+ 	}
+ 
+-	pkt_len = ntohl(*(__be32 *)(nh + optoff + 2));
++	pkt_len = ntohl(net_hdr_word(nh + optoff + 2));
+ 	if (pkt_len <= IPV6_MAXPLEN) {
+ 		__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
+ 		icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
+--- a/include/linux/types.h
++++ b/include/linux/types.h
+@@ -230,5 +230,11 @@ struct callback_head {
+ typedef void (*rcu_callback_t)(struct rcu_head *head);
+ typedef void (*call_rcu_func_t)(struct rcu_head *head, rcu_callback_t func);
+ 
++struct net_hdr_word {
++       u32 words[1];
++} __attribute__((packed, aligned(2)));
++
++#define net_hdr_word(_p) (((struct net_hdr_word *) (_p))->words[0])
++
+ #endif /*  __ASSEMBLY__ */
+ #endif /* _LINUX_TYPES_H */
+--- a/net/ipv4/af_inet.c
++++ b/net/ipv4/af_inet.c
+@@ -1422,8 +1422,8 @@ struct sk_buff **inet_gro_receive(struct
+ 	if (unlikely(ip_fast_csum((u8 *)iph, 5)))
+ 		goto out_unlock;
+ 
+-	id = ntohl(*(__be32 *)&iph->id);
+-	flush = (u16)((ntohl(*(__be32 *)iph) ^ skb_gro_len(skb)) | (id & ~IP_DF));
++	id = ntohl(net_hdr_word(&iph->id));
++	flush = (u16)((ntohl(net_hdr_word(iph)) ^ skb_gro_len(skb)) | (id & ~IP_DF));
+ 	id >>= 16;
+ 
+ 	list_for_each_entry(p, head, list) {
+--- a/net/ipv4/route.c
++++ b/net/ipv4/route.c
+@@ -448,7 +448,7 @@ static struct neighbour *ipv4_neigh_look
+ 	else if (skb)
+ 		pkey = &ip_hdr(skb)->daddr;
+ 
+-	n = __ipv4_neigh_lookup(dev, *(__force u32 *)pkey);
++	n = __ipv4_neigh_lookup(dev, net_hdr_word(pkey));
+ 	if (n)
+ 		return n;
+ 	return neigh_create(&arp_tbl, pkey, dev);
+--- a/net/ipv4/tcp_output.c
++++ b/net/ipv4/tcp_output.c
+@@ -461,48 +461,53 @@ static void tcp_options_write(__be32 *pt
+ 	u16 options = opts->options;	/* mungable copy */
+ 
+ 	if (unlikely(OPTION_MD5 & options)) {
+-		*ptr++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
+-			       (TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG);
++		net_hdr_word(ptr++) =
++			htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
++			      (TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG);
+ 		/* overload cookie hash location */
+ 		opts->hash_location = (__u8 *)ptr;
+ 		ptr += 4;
+ 	}
+ 
+ 	if (unlikely(opts->mss)) {
+-		*ptr++ = htonl((TCPOPT_MSS << 24) |
+-			       (TCPOLEN_MSS << 16) |
+-			       opts->mss);
++		net_hdr_word(ptr++) =
++			htonl((TCPOPT_MSS << 24) | (TCPOLEN_MSS << 16) |
++			      opts->mss);
+ 	}
+ 
+ 	if (likely(OPTION_TS & options)) {
+ 		if (unlikely(OPTION_SACK_ADVERTISE & options)) {
+-			*ptr++ = htonl((TCPOPT_SACK_PERM << 24) |
+-				       (TCPOLEN_SACK_PERM << 16) |
+-				       (TCPOPT_TIMESTAMP << 8) |
+-				       TCPOLEN_TIMESTAMP);
++			net_hdr_word(ptr++) =
++				htonl((TCPOPT_SACK_PERM << 24) |
++				      (TCPOLEN_SACK_PERM << 16) |
++				      (TCPOPT_TIMESTAMP << 8) |
++				      TCPOLEN_TIMESTAMP);
+ 			options &= ~OPTION_SACK_ADVERTISE;
+ 		} else {
+-			*ptr++ = htonl((TCPOPT_NOP << 24) |
+-				       (TCPOPT_NOP << 16) |
+-				       (TCPOPT_TIMESTAMP << 8) |
+-				       TCPOLEN_TIMESTAMP);
++			net_hdr_word(ptr++) =
++				htonl((TCPOPT_NOP << 24) |
++				      (TCPOPT_NOP << 16) |
++				      (TCPOPT_TIMESTAMP << 8) |
++				      TCPOLEN_TIMESTAMP);
+ 		}
+-		*ptr++ = htonl(opts->tsval);
+-		*ptr++ = htonl(opts->tsecr);
++		net_hdr_word(ptr++) = htonl(opts->tsval);
++		net_hdr_word(ptr++) = htonl(opts->tsecr);
+ 	}
+ 
+ 	if (unlikely(OPTION_SACK_ADVERTISE & options)) {
+-		*ptr++ = htonl((TCPOPT_NOP << 24) |
+-			       (TCPOPT_NOP << 16) |
+-			       (TCPOPT_SACK_PERM << 8) |
+-			       TCPOLEN_SACK_PERM);
++		net_hdr_word(ptr++) =
++			htonl((TCPOPT_NOP << 24) |
++			      (TCPOPT_NOP << 16) |
++			      (TCPOPT_SACK_PERM << 8) |
++			      TCPOLEN_SACK_PERM);
+ 	}
+ 
+ 	if (unlikely(OPTION_WSCALE & options)) {
+-		*ptr++ = htonl((TCPOPT_NOP << 24) |
+-			       (TCPOPT_WINDOW << 16) |
+-			       (TCPOLEN_WINDOW << 8) |
+-			       opts->ws);
++		net_hdr_word(ptr++) =
++			htonl((TCPOPT_NOP << 24) |
++			      (TCPOPT_WINDOW << 16) |
++			      (TCPOLEN_WINDOW << 8) |
++			      opts->ws);
+ 	}
+ 
+ 	if (unlikely(opts->num_sack_blocks)) {
+@@ -510,16 +515,17 @@ static void tcp_options_write(__be32 *pt
+ 			tp->duplicate_sack : tp->selective_acks;
+ 		int this_sack;
+ 
+-		*ptr++ = htonl((TCPOPT_NOP  << 24) |
+-			       (TCPOPT_NOP  << 16) |
+-			       (TCPOPT_SACK <<  8) |
+-			       (TCPOLEN_SACK_BASE + (opts->num_sack_blocks *
++		net_hdr_word(ptr++) =
++			htonl((TCPOPT_NOP << 24) |
++			      (TCPOPT_NOP << 16) |
++			      (TCPOPT_SACK << 8) |
++			      (TCPOLEN_SACK_BASE + (opts->num_sack_blocks *
+ 						     TCPOLEN_SACK_PERBLOCK)));
+ 
+ 		for (this_sack = 0; this_sack < opts->num_sack_blocks;
+ 		     ++this_sack) {
+-			*ptr++ = htonl(sp[this_sack].start_seq);
+-			*ptr++ = htonl(sp[this_sack].end_seq);
++			net_hdr_word(ptr++) = htonl(sp[this_sack].start_seq);
++			net_hdr_word(ptr++) = htonl(sp[this_sack].end_seq);
+ 		}
+ 
+ 		tp->rx_opt.dsack = 0;
+@@ -532,13 +538,14 @@ static void tcp_options_write(__be32 *pt
+ 
+ 		if (foc->exp) {
+ 			len = TCPOLEN_EXP_FASTOPEN_BASE + foc->len;
+-			*ptr = htonl((TCPOPT_EXP << 24) | (len << 16) |
++			net_hdr_word(ptr) =
++				htonl((TCPOPT_EXP << 24) | (len << 16) |
+ 				     TCPOPT_FASTOPEN_MAGIC);
+ 			p += TCPOLEN_EXP_FASTOPEN_BASE;
+ 		} else {
+ 			len = TCPOLEN_FASTOPEN_BASE + foc->len;
+-			*p++ = TCPOPT_FASTOPEN;
+-			*p++ = len;
++			net_hdr_word(p++) = TCPOPT_FASTOPEN;
++			net_hdr_word(p++) = len;
+ 		}
+ 
+ 		memcpy(p, foc->val, foc->len);
+--- a/include/uapi/linux/igmp.h
++++ b/include/uapi/linux/igmp.h
+@@ -33,7 +33,7 @@ struct igmphdr {
+ 	__u8 code;		/* For newer IGMP */
+ 	__sum16 csum;
+ 	__be32 group;
+-};
++} __attribute__((packed, aligned(2)));
+ 
+ /* V3 group record types [grec_type] */
+ #define IGMPV3_MODE_IS_INCLUDE		1
+@@ -49,7 +49,7 @@ struct igmpv3_grec {
+ 	__be16	grec_nsrcs;
+ 	__be32	grec_mca;
+ 	__be32	grec_src[0];
+-};
++} __attribute__((packed, aligned(2)));
+ 
+ struct igmpv3_report {
+ 	__u8 type;
+@@ -58,7 +58,7 @@ struct igmpv3_report {
+ 	__be16 resv2;
+ 	__be16 ngrec;
+ 	struct igmpv3_grec grec[0];
+-};
++} __attribute__((packed, aligned(2)));
+ 
+ struct igmpv3_query {
+ 	__u8 type;
+@@ -79,7 +79,7 @@ struct igmpv3_query {
+ 	__u8 qqic;
+ 	__be16 nsrcs;
+ 	__be32 srcs[0];
+-};
++} __attribute__((packed, aligned(2)));
+ 
+ #define IGMP_HOST_MEMBERSHIP_QUERY	0x11	/* From RFC1112 */
+ #define IGMP_HOST_MEMBERSHIP_REPORT	0x12	/* Ditto */
+--- a/net/core/flow_dissector.c
++++ b/net/core/flow_dissector.c
+@@ -111,7 +111,7 @@ __be32 __skb_flow_get_ports(const struct
+ 		ports = __skb_header_pointer(skb, thoff + poff,
+ 					     sizeof(_ports), data, hlen, &_ports);
+ 		if (ports)
+-			return *ports;
++			return (__be32)net_hdr_word(ports);
+ 	}
+ 
+ 	return 0;
+--- a/include/uapi/linux/icmpv6.h
++++ b/include/uapi/linux/icmpv6.h
+@@ -77,7 +77,7 @@ struct icmp6hdr {
+ #define icmp6_addrconf_other	icmp6_dataun.u_nd_ra.other
+ #define icmp6_rt_lifetime	icmp6_dataun.u_nd_ra.rt_lifetime
+ #define icmp6_router_pref	icmp6_dataun.u_nd_ra.router_pref
+-};
++} __attribute__((packed, aligned(2)));
+ 
+ 
+ #define ICMPV6_ROUTER_PREF_LOW		0x3
+--- a/include/net/ndisc.h
++++ b/include/net/ndisc.h
+@@ -89,7 +89,7 @@ struct ra_msg {
+         struct icmp6hdr		icmph;
+ 	__be32			reachable_time;
+ 	__be32			retrans_timer;
+-};
++} __attribute__((packed, aligned(2)));
+ 
+ struct rd_msg {
+ 	struct icmp6hdr icmph;
+@@ -368,10 +368,10 @@ static inline u32 ndisc_hashfn(const voi
+ {
+ 	const u32 *p32 = pkey;
+ 
+-	return (((p32[0] ^ hash32_ptr(dev)) * hash_rnd[0]) +
+-		(p32[1] * hash_rnd[1]) +
+-		(p32[2] * hash_rnd[2]) +
+-		(p32[3] * hash_rnd[3]));
++	return (((net_hdr_word(&p32[0]) ^ hash32_ptr(dev)) * hash_rnd[0]) +
++		(net_hdr_word(&p32[1]) * hash_rnd[1]) +
++		(net_hdr_word(&p32[2]) * hash_rnd[2]) +
++		(net_hdr_word(&p32[3]) * hash_rnd[3]));
+ }
+ 
+ static inline struct neighbour *__ipv6_neigh_lookup_noref(struct net_device *dev, const void *pkey)
+--- a/net/sched/cls_u32.c
++++ b/net/sched/cls_u32.c
+@@ -165,7 +165,7 @@ next_knode:
+ 			data = skb_header_pointer(skb, toff, 4, &hdata);
+ 			if (!data)
+ 				goto out;
+-			if ((*data ^ key->val) & key->mask) {
++			if ((net_hdr_word(data) ^ key->val) & key->mask) {
+ 				n = rcu_dereference_bh(n->next);
+ 				goto next_knode;
+ 			}
+@@ -218,8 +218,8 @@ check_terminal:
+ 						  &hdata);
+ 			if (!data)
+ 				goto out;
+-			sel = ht->divisor & u32_hash_fold(*data, &n->sel,
+-							  n->fshift);
++			sel = ht->divisor & u32_hash_fold(net_hdr_word(data),
++							  &n->sel, n->fshift);
+ 		}
+ 		if (!(n->sel.flags & (TC_U32_VAROFFSET | TC_U32_OFFSET | TC_U32_EAT)))
+ 			goto next_ht;
+--- a/net/ipv6/ip6_offload.c
++++ b/net/ipv6/ip6_offload.c
+@@ -223,7 +223,7 @@ static struct sk_buff **ipv6_gro_receive
+ 			continue;
+ 
+ 		iph2 = (struct ipv6hdr *)(p->data + off);
+-		first_word = *(__be32 *)iph ^ *(__be32 *)iph2;
++		first_word = net_hdr_word(iph) ^ net_hdr_word(iph2);
+ 
+ 		/* All fields must match except length and Traffic Class.
+ 		 * XXX skbs on the gro_list have all been parsed and pulled
+--- a/include/net/addrconf.h
++++ b/include/net/addrconf.h
+@@ -47,7 +47,7 @@ struct prefix_info {
+ 	__be32			reserved2;
+ 
+ 	struct in6_addr		prefix;
+-};
++} __attribute__((packed, aligned(2)));
+ 
+ #include <linux/netdevice.h>
+ #include <net/if_inet6.h>
+--- a/include/net/inet_ecn.h
++++ b/include/net/inet_ecn.h
+@@ -125,9 +125,9 @@ static inline int IP6_ECN_set_ce(struct
+ 	if (INET_ECN_is_not_ect(ipv6_get_dsfield(iph)))
+ 		return 0;
+ 
+-	from = *(__be32 *)iph;
++	from = net_hdr_word(iph);
+ 	to = from | htonl(INET_ECN_CE << 20);
+-	*(__be32 *)iph = to;
++	net_hdr_word(iph) = to;
+ 	if (skb->ip_summed == CHECKSUM_COMPLETE)
+ 		skb->csum = csum_add(csum_sub(skb->csum, (__force __wsum)from),
+ 				     (__force __wsum)to);
+--- a/include/net/ipv6.h
++++ b/include/net/ipv6.h
+@@ -149,7 +149,7 @@ struct frag_hdr {
+ 	__u8	reserved;
+ 	__be16	frag_off;
+ 	__be32	identification;
+-};
++} __attribute__((packed, aligned(2)));
+ 
+ #define	IP6_MF		0x0001
+ #define	IP6_OFFSET	0xFFF8
+@@ -499,8 +499,8 @@ static inline void __ipv6_addr_set_half(
+ 	}
+ #endif
+ #endif
+-	addr[0] = wh;
+-	addr[1] = wl;
++	net_hdr_word(&addr[0]) = wh;
++	net_hdr_word(&addr[1]) = wl;
+ }
+ 
+ static inline void ipv6_addr_set(struct in6_addr *addr,
+@@ -559,6 +559,8 @@ static inline bool ipv6_prefix_equal(con
+ 	const __be32 *a1 = addr1->s6_addr32;
+ 	const __be32 *a2 = addr2->s6_addr32;
+ 	unsigned int pdw, pbi;
++	/* Used for last <32-bit fraction of prefix */
++	u32 pbia1, pbia2;
+ 
+ 	/* check complete u32 in prefix */
+ 	pdw = prefixlen >> 5;
+@@ -567,7 +569,9 @@ static inline bool ipv6_prefix_equal(con
+ 
+ 	/* check incomplete u32 in prefix */
+ 	pbi = prefixlen & 0x1f;
+-	if (pbi && ((a1[pdw] ^ a2[pdw]) & htonl((0xffffffff) << (32 - pbi))))
++	pbia1 = net_hdr_word(&a1[pdw]);
++	pbia2 = net_hdr_word(&a2[pdw]);
++	if (pbi && ((pbia1 ^ pbia2) & htonl((0xffffffff) << (32 - pbi))))
+ 		return false;
+ 
+ 	return true;
+@@ -683,13 +687,13 @@ static inline void ipv6_addr_set_v4mappe
+  */
+ static inline int __ipv6_addr_diff32(const void *token1, const void *token2, int addrlen)
+ {
+-	const __be32 *a1 = token1, *a2 = token2;
++	const struct in6_addr *a1 = token1, *a2 = token2;
+ 	int i;
+ 
+ 	addrlen >>= 2;
+ 
+ 	for (i = 0; i < addrlen; i++) {
+-		__be32 xb = a1[i] ^ a2[i];
++		__be32 xb = a1->s6_addr32[i] ^ a2->s6_addr32[i];
+ 		if (xb)
+ 			return i * 32 + 31 - __fls(ntohl(xb));
+ 	}
+@@ -876,17 +880,18 @@ static inline int ip6_default_np_autolab
+ static inline void ip6_flow_hdr(struct ipv6hdr *hdr, unsigned int tclass,
+ 				__be32 flowlabel)
+ {
+-	*(__be32 *)hdr = htonl(0x60000000 | (tclass << 20)) | flowlabel;
++	net_hdr_word((__be32 *)hdr) =
++		htonl(0x60000000 | (tclass << 20)) | flowlabel;
+ }
+ 
+ static inline __be32 ip6_flowinfo(const struct ipv6hdr *hdr)
+ {
+-	return *(__be32 *)hdr & IPV6_FLOWINFO_MASK;
++	return net_hdr_word((__be32 *)hdr) & IPV6_FLOWINFO_MASK;
+ }
+ 
+ static inline __be32 ip6_flowlabel(const struct ipv6hdr *hdr)
+ {
+-	return *(__be32 *)hdr & IPV6_FLOWLABEL_MASK;
++	return net_hdr_word((__be32 *)hdr) & IPV6_FLOWLABEL_MASK;
+ }
+ 
+ static inline u8 ip6_tclass(__be32 flowinfo)
+--- a/include/net/secure_seq.h
++++ b/include/net/secure_seq.h
+@@ -3,6 +3,7 @@
+ #define _NET_SECURE_SEQ
+ 
+ #include <linux/types.h>
++#include <linux/in6.h>
+ 
+ u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport);
+ u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
+--- a/include/uapi/linux/in.h
++++ b/include/uapi/linux/in.h
+@@ -84,7 +84,7 @@ enum {
+ /* Internet address. */
+ struct in_addr {
+ 	__be32	s_addr;
+-};
++} __attribute__((packed, aligned(2)));
+ #endif
+ 
+ #define IP_TOS		1
+--- a/net/ipv6/ip6_fib.c
++++ b/net/ipv6/ip6_fib.c
+@@ -142,7 +142,7 @@ static __be32 addr_bit_set(const void *t
+ 	 * See include/asm-generic/bitops/le.h.
+ 	 */
+ 	return (__force __be32)(1 << ((~fn_bit ^ BITOP_BE32_SWIZZLE) & 0x1f)) &
+-	       addr[fn_bit >> 5];
++	       net_hdr_word(&addr[fn_bit >> 5]);
+ }
+ 
+ struct fib6_info *fib6_info_alloc(gfp_t gfp_flags)
+--- a/net/netfilter/nf_conntrack_proto_tcp.c
++++ b/net/netfilter/nf_conntrack_proto_tcp.c
+@@ -423,7 +423,7 @@ static void tcp_sack(const struct sk_buf
+ 
+ 	/* Fast path for timestamp-only option */
+ 	if (length == TCPOLEN_TSTAMP_ALIGNED
+-	    && *(__be32 *)ptr == htonl((TCPOPT_NOP << 24)
++	    && net_hdr_word(ptr) == htonl((TCPOPT_NOP << 24)
+ 				       | (TCPOPT_NOP << 16)
+ 				       | (TCPOPT_TIMESTAMP << 8)
+ 				       | TCPOLEN_TIMESTAMP))
+--- a/net/xfrm/xfrm_input.c
++++ b/net/xfrm/xfrm_input.c
+@@ -194,8 +194,8 @@ int xfrm_parse_spi(struct sk_buff *skb,
+ 	if (!pskb_may_pull(skb, hlen))
+ 		return -EINVAL;
+ 
+-	*spi = *(__be32 *)(skb_transport_header(skb) + offset);
+-	*seq = *(__be32 *)(skb_transport_header(skb) + offset_seq);
++	*spi = net_hdr_word(skb_transport_header(skb) + offset);
++	*seq = net_hdr_word(skb_transport_header(skb) + offset_seq);
+ 	return 0;
+ }
+ EXPORT_SYMBOL(xfrm_parse_spi);
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -3898,14 +3898,16 @@ static bool tcp_parse_aligned_timestamp(
+ {
+ 	const __be32 *ptr = (const __be32 *)(th + 1);
+ 
+-	if (*ptr == htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16)
+-			  | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) {
++	if (net_hdr_word(ptr) ==
++	    htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
++		  (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) {
+ 		tp->rx_opt.saw_tstamp = 1;
+ 		++ptr;
+-		tp->rx_opt.rcv_tsval = ntohl(*ptr);
++		tp->rx_opt.rcv_tsval = get_unaligned_be32(ptr);
+ 		++ptr;
+-		if (*ptr)
+-			tp->rx_opt.rcv_tsecr = ntohl(*ptr) - tp->tsoffset;
++		if (net_hdr_word(ptr))
++			tp->rx_opt.rcv_tsecr = get_unaligned_be32(ptr) -
++					       tp->tsoffset;
+ 		else
+ 			tp->rx_opt.rcv_tsecr = 0;
+ 		return true;
+--- a/include/uapi/linux/if_pppox.h
++++ b/include/uapi/linux/if_pppox.h
+@@ -51,6 +51,7 @@ struct pppoe_addr {
+  */
+ struct pptp_addr {
+ 	__u16		call_id;
++	__u16		pad;
+ 	struct in_addr	sin_addr;
+ };
+ 
+--- a/net/ipv6/netfilter/nf_log_ipv6.c
++++ b/net/ipv6/netfilter/nf_log_ipv6.c
+@@ -66,9 +66,9 @@ static void dump_ipv6_packet(struct nf_l
+ 	/* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */
+ 	nf_log_buf_add(m, "LEN=%zu TC=%u HOPLIMIT=%u FLOWLBL=%u ",
+ 	       ntohs(ih->payload_len) + sizeof(struct ipv6hdr),
+-	       (ntohl(*(__be32 *)ih) & 0x0ff00000) >> 20,
++	       (ntohl(net_hdr_word(ih)) & 0x0ff00000) >> 20,
+ 	       ih->hop_limit,
+-	       (ntohl(*(__be32 *)ih) & 0x000fffff));
++	       (ntohl(net_hdr_word(ih)) & 0x000fffff));
+ 
+ 	fragment = 0;
+ 	ptr = ip6hoff + sizeof(struct ipv6hdr);
+--- a/include/net/neighbour.h
++++ b/include/net/neighbour.h
+@@ -266,8 +266,10 @@ static inline bool neigh_key_eq128(const
+ 	const u32 *n32 = (const u32 *)n->primary_key;
+ 	const u32 *p32 = pkey;
+ 
+-	return ((n32[0] ^ p32[0]) | (n32[1] ^ p32[1]) |
+-		(n32[2] ^ p32[2]) | (n32[3] ^ p32[3])) == 0;
++	return ((n32[0] ^ net_hdr_word(&p32[0])) |
++		(n32[1] ^ net_hdr_word(&p32[1])) |
++		(n32[2] ^ net_hdr_word(&p32[2])) |
++		(n32[3] ^ net_hdr_word(&p32[3]))) == 0;
+ }
+ 
+ static inline struct neighbour *___neigh_lookup_noref(
+--- a/include/uapi/linux/netfilter_arp/arp_tables.h
++++ b/include/uapi/linux/netfilter_arp/arp_tables.h
+@@ -70,7 +70,7 @@ struct arpt_arp {
+ 	__u8 flags;
+ 	/* Inverse flags */
+ 	__u16 invflags;
+-};
++} __attribute__((aligned(4)));
+ 
+ /* Values for "flag" field in struct arpt_ip (general arp structure).
+  * No flags defined yet.
+--- a/net/core/utils.c
++++ b/net/core/utils.c
+@@ -447,8 +447,14 @@ void inet_proto_csum_replace16(__sum16 *
+ 			       bool pseudohdr)
+ {
+ 	__be32 diff[] = {
+-		~from[0], ~from[1], ~from[2], ~from[3],
+-		to[0], to[1], to[2], to[3],
++		~net_hdr_word(&from[0]),
++		~net_hdr_word(&from[1]),
++		~net_hdr_word(&from[2]),
++		~net_hdr_word(&from[3]),
++		net_hdr_word(&to[0]),
++		net_hdr_word(&to[1]),
++		net_hdr_word(&to[2]),
++		net_hdr_word(&to[3]),
+ 	};
+ 	if (skb->ip_summed != CHECKSUM_PARTIAL) {
+ 		*sum = csum_fold(csum_partial(diff, sizeof(diff),
+--- a/include/linux/etherdevice.h
++++ b/include/linux/etherdevice.h
+@@ -480,7 +480,7 @@ static inline bool is_etherdev_addr(cons
+  * @b: Pointer to Ethernet header
+  *
+  * Compare two Ethernet headers, returns 0 if equal.
+- * This assumes that the network header (i.e., IP header) is 4-byte
++ * This assumes that the network header (i.e., IP header) is 2-byte
+  * aligned OR the platform can handle unaligned access.  This is the
+  * case for all packets coming into netif_receive_skb or similar
+  * entry points.
+@@ -503,11 +503,12 @@ static inline unsigned long compare_ethe
+ 	fold |= *(unsigned long *)(a + 6) ^ *(unsigned long *)(b + 6);
+ 	return fold;
+ #else
+-	u32 *a32 = (u32 *)((u8 *)a + 2);
+-	u32 *b32 = (u32 *)((u8 *)b + 2);
++	const u16 *a16 = a;
++	const u16 *b16 = b;
+ 
+-	return (*(u16 *)a ^ *(u16 *)b) | (a32[0] ^ b32[0]) |
+-	       (a32[1] ^ b32[1]) | (a32[2] ^ b32[2]);
++	return (a16[0] ^ b16[0]) | (a16[1] ^ b16[1]) | (a16[2] ^ b16[2]) |
++	       (a16[3] ^ b16[3]) | (a16[4] ^ b16[4]) | (a16[5] ^ b16[5]) |
++	       (a16[6] ^ b16[6]);
+ #endif
+ }
+ 
+--- a/net/ipv4/tcp_offload.c
++++ b/net/ipv4/tcp_offload.c
+@@ -226,7 +226,7 @@ struct sk_buff **tcp_gro_receive(struct
+ 
+ 		th2 = tcp_hdr(p);
+ 
+-		if (*(u32 *)&th->source ^ *(u32 *)&th2->source) {
++		if (net_hdr_word(&th->source) ^ net_hdr_word(&th2->source)) {
+ 			NAPI_GRO_CB(p)->same_flow = 0;
+ 			continue;
+ 		}
+@@ -244,8 +244,8 @@ found:
+ 		  ~(TCP_FLAG_CWR | TCP_FLAG_FIN | TCP_FLAG_PSH));
+ 	flush |= (__force int)(th->ack_seq ^ th2->ack_seq);
+ 	for (i = sizeof(*th); i < thlen; i += 4)
+-		flush |= *(u32 *)((u8 *)th + i) ^
+-			 *(u32 *)((u8 *)th2 + i);
++		flush |= net_hdr_word((u8 *)th + i) ^
++			 net_hdr_word((u8 *)th2 + i);
+ 
+ 	/* When we receive our second frame we can made a decision on if we
+ 	 * continue this flow as an atomic flow with a fixed ID or if we use
+--- a/net/ipv6/netfilter/ip6table_mangle.c
++++ b/net/ipv6/netfilter/ip6table_mangle.c
+@@ -50,7 +50,7 @@ ip6t_mangle_out(struct sk_buff *skb, con
+ 	hop_limit = ipv6_hdr(skb)->hop_limit;
+ 
+ 	/* flowlabel and prio (includes version, which shouldn't change either */
+-	flowlabel = *((u_int32_t *)ipv6_hdr(skb));
++	flowlabel = net_hdr_word(ipv6_hdr(skb));
+ 
+ 	ret = ip6t_do_table(skb, state, state->net->ipv6.ip6table_mangle);
+ 
+@@ -59,7 +59,7 @@ ip6t_mangle_out(struct sk_buff *skb, con
+ 	     !ipv6_addr_equal(&ipv6_hdr(skb)->daddr, &daddr) ||
+ 	     skb->mark != mark ||
+ 	     ipv6_hdr(skb)->hop_limit != hop_limit ||
+-	     flowlabel != *((u_int32_t *)ipv6_hdr(skb)))) {
++	     flowlabel != net_hdr_word(ipv6_hdr(skb)))) {
+ 		err = ip6_route_me_harder(state->net, skb);
+ 		if (err < 0)
+ 			ret = NF_DROP_ERR(err);
-- 
GitLab