[Feature]add MT2731_MP2_MR2_SVN388 baseline version

Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/Kconfig b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/Kconfig
new file mode 100644
index 0000000..c342dc4
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/Kconfig
@@ -0,0 +1,240 @@
+if ARCH_IXP4XX
+
+menu "Intel IXP4xx Implementation Options"
+
+comment "IXP4xx Platforms"
+
+config MACH_NSLU2
+	bool
+	prompt "Linksys NSLU2"
+	select PCI
+	help
+	  Say 'Y' here if you want your kernel to support Linksys's
+	  NSLU2 NAS device. For more information on this platform,
+	  see http://www.nslu2-linux.org
+
+config MACH_AVILA
+	bool "Avila"
+	select PCI
+	help
+	  Say 'Y' here if you want your kernel to support the Gateworks
+	  Avila Network Platform. For more information on this platform,
+	  see <file:Documentation/arm/IXP4xx>.
+
+config MACH_LOFT
+    bool "Loft"
+    depends on MACH_AVILA
+    help
+	  Say 'Y' here if you want your kernel to support the Giant
+	  Shoulder Inc Loft board (a minor variation on the standard
+	  Gateworks Avila Network Platform).
+
+config ARCH_ADI_COYOTE
+	bool "Coyote"
+	select PCI
+	help
+	  Say 'Y' here if you want your kernel to support the ADI 
+	  Engineering Coyote Gateway Reference Platform. For more
+	  information on this platform, see <file:Documentation/arm/IXP4xx>.
+
+config MACH_GATEWAY7001
+	bool "Gateway 7001"
+	select PCI
+	help
+	  Say 'Y' here if you want your kernel to support Gateway's
+	  7001 Access Point. For more information on this platform,
+	  see http://openwrt.org
+
+config MACH_WG302V2
+	bool "Netgear WG302 v2 / WAG302 v2"
+	select PCI
+	help
+	  Say 'Y' here if you want your kernel to support Netgear's
+	  WG302 v2 or WAG302 v2 Access Points. For more information
+	  on this platform, see http://openwrt.org
+
+config ARCH_IXDP425
+	bool "IXDP425"
+	help
+	  Say 'Y' here if you want your kernel to support Intel's 
+	  IXDP425 Development Platform (Also known as Richfield).  
+	  For more information on this platform, see <file:Documentation/arm/IXP4xx>.
+
+config MACH_IXDPG425
+	bool "IXDPG425"
+	help
+	  Say 'Y' here if you want your kernel to support Intel's
+	  IXDPG425 Development Platform (Also known as Montajade).
+	  For more information on this platform, see <file:Documentation/arm/IXP4xx>.
+
+config MACH_IXDP465
+	bool "IXDP465"
+	help
+	  Say 'Y' here if you want your kernel to support Intel's
+	  IXDP465 Development Platform (Also known as BMP).
+	  For more information on this platform, see <file:Documentation/arm/IXP4xx>.
+
+config MACH_GORAMO_MLR
+	bool "GORAMO Multi Link Router"
+	help
+	  Say 'Y' here if you want your kernel to support GORAMO
+	  MultiLink router.
+
+config MACH_KIXRP435
+	bool "KIXRP435"
+	help
+	  Say 'Y' here if you want your kernel to support Intel's
+	  KIXRP435 Reference Platform.
+	  For more information on this platform, see <file:Documentation/arm/IXP4xx>.
+
+#
+# IXCDP1100 is the exact same HW as IXDP425, but with a different machine 
+# number from the bootloader due to marketing monkeys, so we just enable it 
+# by default if IXDP425 is enabled.
+#
+config ARCH_IXCDP1100
+	bool 
+	depends on ARCH_IXDP425
+	default y
+
+config ARCH_PRPMC1100
+	bool "PrPMC1100"
+	help
+	  Say 'Y' here if you want your kernel to support the Motorola
+	  PrPCM1100 Processor Mezanine Module. For more information on
+	  this platform, see <file:Documentation/arm/IXP4xx>.
+
+config MACH_NAS100D
+	bool
+	prompt "NAS100D"
+	select PCI
+	help
+	  Say 'Y' here if you want your kernel to support Iomega's
+	  NAS 100d device. For more information on this platform,
+	  see http://www.nslu2-linux.org/wiki/NAS100d/HomePage
+
+config MACH_DSMG600
+	bool
+	prompt "D-Link DSM-G600 RevA"
+	select PCI
+	help
+	  Say 'Y' here if you want your kernel to support D-Link's
+	  DSM-G600 RevA device. For more information on this platform,
+	  see http://www.nslu2-linux.org/wiki/DSMG600/HomePage
+
+config	ARCH_IXDP4XX
+	bool
+	depends on ARCH_IXDP425 || MACH_IXDP465 || MACH_KIXRP435
+	default y
+
+config MACH_FSG
+	bool
+	prompt "Freecom FSG-3"
+	select PCI
+	help
+	  Say 'Y' here if you want your kernel to support Freecom's
+	  FSG-3 device. For more information on this platform,
+	  see http://www.nslu2-linux.org/wiki/FSG3/HomePage
+
+config MACH_ARCOM_VULCAN
+	bool
+	prompt "Arcom/Eurotech Vulcan"
+	select PCI
+	help
+	  Say 'Y' here if you want your kernel to support Arcom's
+	  Vulcan board.
+
+#
+# Certain registers and IRQs are only enabled if supporting IXP465 CPUs
+#
+config CPU_IXP46X
+	bool
+	depends on MACH_IXDP465
+	default y
+
+config CPU_IXP43X
+	bool
+	depends on MACH_KIXRP435
+	default y
+
+config MACH_GTWX5715
+	bool "Gemtek WX5715 (Linksys WRV54G)"
+	depends on ARCH_IXP4XX
+	select PCI
+	help
+		This board is currently inside the Linksys WRV54G Gateways.
+
+		IXP425 - 266mhz
+		32mb SDRAM
+		8mb Flash
+		miniPCI slot 0 does not have a card connector soldered to the board
+		miniPCI slot 1 has an ISL3880 802.11g card (Prism54)
+		npe0 is connected to a Kendin KS8995M Switch (4 ports)
+		npe1 is the "wan" port
+		"Console" UART is available on J11 as console
+		"High Speed" UART is n/c (as far as I can tell)
+		20 Pin ARM/Xscale JTAG interface on J2
+
+config MACH_DEVIXP
+	bool "Omicron DEVIXP"
+	help
+	  Say 'Y' here if you want your kernel to support the DEVIXP
+	  board from OMICRON electronics GmbH.
+
+config MACH_MICCPT
+	bool "Omicron MICCPT"
+	select PCI
+	help
+	  Say 'Y' here if you want your kernel to support the MICCPT
+	  board from OMICRON electronics GmbH.
+
+config MACH_MIC256
+	bool "Omicron MIC256"
+	help
+	  Say 'Y' here if you want your kernel to support the MIC256
+	  board from OMICRON electronics GmbH.
+
+comment "IXP4xx Options"
+
+config IXP4XX_INDIRECT_PCI
+	bool "Use indirect PCI memory access"
+	depends on PCI
+	help
+          IXP4xx provides two methods of accessing PCI memory space:
+
+          1) A direct mapped window from 0x48000000 to 0x4BFFFFFF (64MB).
+             To access PCI via this space, we simply ioremap() the BAR
+             into the kernel and we can use the standard read[bwl]/write[bwl]
+             macros. This is the preferred method due to speed but it
+             limits the system to just 64MB of PCI memory. This can be
+             problematic if using video cards and other memory-heavy devices.
+
+	  2) If > 64MB of memory space is required, the IXP4xx can be
+	     configured to use indirect registers to access the whole PCI
+	     memory space. This currently allows for up to 1 GB (0x10000000
+	     to 0x4FFFFFFF) of memory on the bus. The disadvantage of this
+	     is that every PCI access requires three local register accesses
+	     plus a spinlock, but in some cases the performance hit is
+	     acceptable. In addition, you cannot mmap() PCI devices in this
+	     case due to the indirect nature of the PCI window.
+
+	  By default, the direct method is used. Choose this option if you
+	  need to use the indirect method instead. If you don't know
+	  what you need, leave this option unselected.
+
+config IXP4XX_QMGR
+	tristate "IXP4xx Queue Manager support"
+	help
+	  This driver supports IXP4xx built-in hardware queue manager
+	  and is automatically selected by Ethernet and HSS drivers.
+
+config IXP4XX_NPE
+	tristate "IXP4xx Network Processor Engine support"
+	select FW_LOADER
+	help
+	  This driver supports IXP4xx built-in network coprocessors
+	  and is automatically selected by Ethernet and HSS drivers.
+
+endmenu
+
+endif
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/Makefile b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/Makefile
new file mode 100644
index 0000000..f099945
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/Makefile
@@ -0,0 +1,44 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for the linux kernel.
+#
+
+obj-pci-y	:=
+obj-pci-n	:=
+
+obj-pci-$(CONFIG_ARCH_IXDP4XX)		+= ixdp425-pci.o
+obj-pci-$(CONFIG_MACH_AVILA)		+= avila-pci.o
+obj-pci-$(CONFIG_MACH_IXDPG425)		+= ixdpg425-pci.o
+obj-pci-$(CONFIG_ARCH_ADI_COYOTE)	+= coyote-pci.o
+obj-pci-$(CONFIG_MACH_GTWX5715)		+= gtwx5715-pci.o
+obj-pci-$(CONFIG_MACH_MICCPT)		+= miccpt-pci.o
+obj-pci-$(CONFIG_MACH_NSLU2)		+= nslu2-pci.o
+obj-pci-$(CONFIG_MACH_NAS100D)		+= nas100d-pci.o
+obj-pci-$(CONFIG_MACH_DSMG600)		+= dsmg600-pci.o
+obj-pci-$(CONFIG_MACH_GATEWAY7001)	+= gateway7001-pci.o
+obj-pci-$(CONFIG_MACH_WG302V2)		+= wg302v2-pci.o
+obj-pci-$(CONFIG_MACH_FSG)		+= fsg-pci.o
+obj-pci-$(CONFIG_MACH_ARCOM_VULCAN)	+= vulcan-pci.o
+
+obj-y	+= common.o
+
+obj-$(CONFIG_ARCH_IXDP4XX)	+= ixdp425-setup.o
+obj-$(CONFIG_MACH_AVILA)	+= avila-setup.o
+obj-$(CONFIG_MACH_IXDPG425)	+= coyote-setup.o
+obj-$(CONFIG_ARCH_ADI_COYOTE)	+= coyote-setup.o
+obj-$(CONFIG_MACH_GTWX5715)	+= gtwx5715-setup.o
+obj-$(CONFIG_MACH_DEVIXP)	+= omixp-setup.o
+obj-$(CONFIG_MACH_MICCPT)	+= omixp-setup.o
+obj-$(CONFIG_MACH_MIC256)	+= omixp-setup.o
+obj-$(CONFIG_MACH_NSLU2)	+= nslu2-setup.o
+obj-$(CONFIG_MACH_NAS100D)	+= nas100d-setup.o
+obj-$(CONFIG_MACH_DSMG600)      += dsmg600-setup.o
+obj-$(CONFIG_MACH_GATEWAY7001)	+= gateway7001-setup.o
+obj-$(CONFIG_MACH_WG302V2)	+= wg302v2-setup.o
+obj-$(CONFIG_MACH_FSG)		+= fsg-setup.o
+obj-$(CONFIG_MACH_GORAMO_MLR)	+= goramo_mlr.o
+obj-$(CONFIG_MACH_ARCOM_VULCAN)	+= vulcan-setup.o
+
+obj-$(CONFIG_PCI)		+= $(obj-pci-$(CONFIG_PCI)) common-pci.o
+obj-$(CONFIG_IXP4XX_QMGR)	+= ixp4xx_qmgr.o
+obj-$(CONFIG_IXP4XX_NPE)	+= ixp4xx_npe.o
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/Makefile.boot b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/Makefile.boot
new file mode 100644
index 0000000..9c7af91
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/Makefile.boot
@@ -0,0 +1,3 @@
+   zreladdr-y	+= 0x00008000
+params_phys-y	:= 0x00000100
+
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/avila-pci.c b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/avila-pci.c
new file mode 100644
index 0000000..548c7d4
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/avila-pci.c
@@ -0,0 +1,81 @@
+/*
+ * arch/arm/mach-ixp4xx/avila-pci.c
+ *
+ * Gateworks Avila board-level PCI initialization
+ *
+ * Author: Michael-Luke Jones <mlj28@cam.ac.uk>
+ *
+ * Based on ixdp-pci.c
+ * Copyright (C) 2002 Intel Corporation.
+ * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * 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/pci.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <asm/mach/pci.h>
+#include <asm/irq.h>
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+
+#define AVILA_MAX_DEV	4
+#define LOFT_MAX_DEV	6
+#define IRQ_LINES	4
+
+/* PCI controller GPIO to IRQ pin mappings */
+#define INTA		11
+#define INTB		10
+#define INTC		9
+#define INTD		8
+
+void __init avila_pci_preinit(void)
+{
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW);
+	ixp4xx_pci_preinit();
+}
+
+static int __init avila_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	static int pci_irq_table[IRQ_LINES] = {
+		IXP4XX_GPIO_IRQ(INTA),
+		IXP4XX_GPIO_IRQ(INTB),
+		IXP4XX_GPIO_IRQ(INTC),
+		IXP4XX_GPIO_IRQ(INTD)
+	};
+
+	if (slot >= 1 &&
+	    slot <= (machine_is_loft() ? LOFT_MAX_DEV : AVILA_MAX_DEV) &&
+	    pin >= 1 && pin <= IRQ_LINES)
+		return pci_irq_table[(slot + pin - 2) % 4];
+
+	return -1;
+}
+
+struct hw_pci avila_pci __initdata = {
+	.nr_controllers = 1,
+	.ops		= &ixp4xx_ops,
+	.preinit	= avila_pci_preinit,
+	.setup		= ixp4xx_setup,
+	.map_irq	= avila_map_irq,
+};
+
+int __init avila_pci_init(void)
+{
+	if (machine_is_avila() || machine_is_loft())
+		pci_common_init(&avila_pci);
+	return 0;
+}
+
+subsys_initcall(avila_pci_init);
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/avila-setup.c b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/avila-setup.c
new file mode 100644
index 0000000..186df64
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/avila-setup.c
@@ -0,0 +1,200 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * arch/arm/mach-ixp4xx/avila-setup.c
+ *
+ * Gateworks Avila board-setup
+ *
+ * Author: Michael-Luke Jones <mlj28@cam.ac.uk>
+ *
+ * Based on ixdp-setup.c
+ * Copyright (C) 2003-2005 MontaVista Software, Inc.
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_8250.h>
+#include <linux/i2c-gpio.h>
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+#define AVILA_SDA_PIN	7
+#define AVILA_SCL_PIN	6
+
+static struct flash_platform_data avila_flash_data = {
+	.map_name	= "cfi_probe",
+	.width		= 2,
+};
+
+static struct resource avila_flash_resource = {
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device avila_flash = {
+	.name		= "IXP4XX-Flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &avila_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &avila_flash_resource,
+};
+
+static struct i2c_gpio_platform_data avila_i2c_gpio_data = {
+	.sda_pin	= AVILA_SDA_PIN,
+	.scl_pin	= AVILA_SCL_PIN,
+};
+
+static struct platform_device avila_i2c_gpio = {
+	.name		= "i2c-gpio",
+	.id		= 0,
+	.dev	 = {
+		.platform_data	= &avila_i2c_gpio_data,
+	},
+};
+
+static struct resource avila_uart_resources[] = {
+	{
+		.start		= IXP4XX_UART1_BASE_PHYS,
+		.end		= IXP4XX_UART1_BASE_PHYS + 0x0fff,
+		.flags		= IORESOURCE_MEM
+	},
+	{
+		.start		= IXP4XX_UART2_BASE_PHYS,
+		.end		= IXP4XX_UART2_BASE_PHYS + 0x0fff,
+		.flags		= IORESOURCE_MEM
+	}
+};
+
+static struct plat_serial8250_port avila_uart_data[] = {
+	{
+		.mapbase	= IXP4XX_UART1_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART1,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	},
+	{
+		.mapbase	= IXP4XX_UART2_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART2,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	},
+	{ },
+};
+
+static struct platform_device avila_uart = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev.platform_data	= avila_uart_data,
+	.num_resources		= 2,
+	.resource		= avila_uart_resources
+};
+
+static struct resource avila_pata_resources[] = {
+	{
+		.flags	= IORESOURCE_MEM
+	},
+	{
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "intrq",
+		.start	= IRQ_IXP4XX_GPIO12,
+		.end	= IRQ_IXP4XX_GPIO12,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct ixp4xx_pata_data avila_pata_data = {
+	.cs0_bits	= 0xbfff0043,
+	.cs1_bits	= 0xbfff0043,
+};
+
+static struct platform_device avila_pata = {
+	.name			= "pata_ixp4xx_cf",
+	.id			= 0,
+	.dev.platform_data      = &avila_pata_data,
+	.num_resources		= ARRAY_SIZE(avila_pata_resources),
+	.resource		= avila_pata_resources,
+};
+
+static struct platform_device *avila_devices[] __initdata = {
+	&avila_i2c_gpio,
+	&avila_flash,
+	&avila_uart
+};
+
+static void __init avila_init(void)
+{
+	ixp4xx_sys_init();
+
+	avila_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+	avila_flash_resource.end =
+		IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
+
+	platform_add_devices(avila_devices, ARRAY_SIZE(avila_devices));
+
+	avila_pata_resources[0].start = IXP4XX_EXP_BUS_BASE(1);
+	avila_pata_resources[0].end = IXP4XX_EXP_BUS_END(1);
+
+	avila_pata_resources[1].start = IXP4XX_EXP_BUS_BASE(2);
+	avila_pata_resources[1].end = IXP4XX_EXP_BUS_END(2);
+
+	avila_pata_data.cs0_cfg = IXP4XX_EXP_CS1;
+	avila_pata_data.cs1_cfg = IXP4XX_EXP_CS2;
+
+	platform_device_register(&avila_pata);
+
+}
+
+MACHINE_START(AVILA, "Gateworks Avila Network Platform")
+	/* Maintainer: Deepak Saxena <dsaxena@plexity.net> */
+	.map_io		= ixp4xx_map_io,
+	.init_early	= ixp4xx_init_early,
+	.init_irq	= ixp4xx_init_irq,
+	.init_time	= ixp4xx_timer_init,
+	.atag_offset	= 0x100,
+	.init_machine	= avila_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
+	.restart	= ixp4xx_restart,
+MACHINE_END
+
+ /*
+  * Loft is functionally equivalent to Avila except that it has a
+  * different number for the maximum PCI devices.  The MACHINE
+  * structure below is identical to Avila except for the comment.
+  */
+#ifdef CONFIG_MACH_LOFT
+MACHINE_START(LOFT, "Giant Shoulder Inc Loft board")
+	/* Maintainer: Tom Billman <kernel@giantshoulderinc.com> */
+	.map_io		= ixp4xx_map_io,
+	.init_early	= ixp4xx_init_early,
+	.init_irq	= ixp4xx_init_irq,
+	.init_time	= ixp4xx_timer_init,
+	.atag_offset	= 0x100,
+	.init_machine	= avila_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
+	.restart	= ixp4xx_restart,
+MACHINE_END
+#endif
+
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/common-pci.c b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/common-pci.c
new file mode 100644
index 0000000..bcf3df5
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/common-pci.c
@@ -0,0 +1,455 @@
+/*
+ * arch/arm/mach-ixp4xx/common-pci.c 
+ *
+ * IXP4XX PCI routines for all platforms
+ *
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (C) 2002 Intel Corporation.
+ * Copyright (C) 2003 Greg Ungerer <gerg@snapgear.com>
+ * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ * 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/sched.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/export.h>
+#include <asm/dma-mapping.h>
+
+#include <asm/cputype.h>
+#include <asm/irq.h>
+#include <asm/sizes.h>
+#include <asm/mach/pci.h>
+#include <mach/hardware.h>
+
+
+/*
+ * IXP4xx PCI read function is dependent on whether we are 
+ * running A0 or B0 (AppleGate) silicon.
+ */
+int (*ixp4xx_pci_read)(u32 addr, u32 cmd, u32* data);
+
+/*
+ * Base address for PCI register region
+ */
+unsigned long ixp4xx_pci_reg_base = 0;
+
+/*
+ * PCI cfg an I/O routines are done by programming a 
+ * command/byte enable register, and then read/writing
+ * the data from a data register. We need to ensure
+ * these transactions are atomic or we will end up
+ * with corrupt data on the bus or in a driver.
+ */
+static DEFINE_RAW_SPINLOCK(ixp4xx_pci_lock);
+
+/*
+ * Read from PCI config space
+ */
+static void crp_read(u32 ad_cbe, u32 *data)
+{
+	unsigned long flags;
+	raw_spin_lock_irqsave(&ixp4xx_pci_lock, flags);
+	*PCI_CRP_AD_CBE = ad_cbe;
+	*data = *PCI_CRP_RDATA;
+	raw_spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
+}
+
+/*
+ * Write to PCI config space
+ */
+static void crp_write(u32 ad_cbe, u32 data)
+{ 
+	unsigned long flags;
+	raw_spin_lock_irqsave(&ixp4xx_pci_lock, flags);
+	*PCI_CRP_AD_CBE = CRP_AD_CBE_WRITE | ad_cbe;
+	*PCI_CRP_WDATA = data;
+	raw_spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
+}
+
+static inline int check_master_abort(void)
+{
+	/* check Master Abort bit after access */
+	unsigned long isr = *PCI_ISR;
+
+	if (isr & PCI_ISR_PFE) {
+		/* make sure the Master Abort bit is reset */    
+		*PCI_ISR = PCI_ISR_PFE;
+		pr_debug("%s failed\n", __func__);
+		return 1;
+	}
+
+	return 0;
+}
+
+int ixp4xx_pci_read_errata(u32 addr, u32 cmd, u32* data)
+{
+	unsigned long flags;
+	int retval = 0;
+	int i;
+
+	raw_spin_lock_irqsave(&ixp4xx_pci_lock, flags);
+
+	*PCI_NP_AD = addr;
+
+	/* 
+	 * PCI workaround  - only works if NP PCI space reads have 
+	 * no side effects!!! Read 8 times. last one will be good.
+	 */
+	for (i = 0; i < 8; i++) {
+		*PCI_NP_CBE = cmd;
+		*data = *PCI_NP_RDATA;
+		*data = *PCI_NP_RDATA;
+	}
+
+	if(check_master_abort())
+		retval = 1;
+
+	raw_spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
+	return retval;
+}
+
+int ixp4xx_pci_read_no_errata(u32 addr, u32 cmd, u32* data)
+{
+	unsigned long flags;
+	int retval = 0;
+
+	raw_spin_lock_irqsave(&ixp4xx_pci_lock, flags);
+
+	*PCI_NP_AD = addr;
+
+	/* set up and execute the read */    
+	*PCI_NP_CBE = cmd;
+
+	/* the result of the read is now in NP_RDATA */
+	*data = *PCI_NP_RDATA; 
+
+	if(check_master_abort())
+		retval = 1;
+
+	raw_spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
+	return retval;
+}
+
+int ixp4xx_pci_write(u32 addr, u32 cmd, u32 data)
+{    
+	unsigned long flags;
+	int retval = 0;
+
+	raw_spin_lock_irqsave(&ixp4xx_pci_lock, flags);
+
+	*PCI_NP_AD = addr;
+
+	/* set up the write */
+	*PCI_NP_CBE = cmd;
+
+	/* execute the write by writing to NP_WDATA */
+	*PCI_NP_WDATA = data;
+
+	if(check_master_abort())
+		retval = 1;
+
+	raw_spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
+	return retval;
+}
+
+static u32 ixp4xx_config_addr(u8 bus_num, u16 devfn, int where)
+{
+	u32 addr;
+	if (!bus_num) {
+		/* type 0 */
+		addr = BIT(32-PCI_SLOT(devfn)) | ((PCI_FUNC(devfn)) << 8) | 
+		    (where & ~3);	
+	} else {
+		/* type 1 */
+		addr = (bus_num << 16) | ((PCI_SLOT(devfn)) << 11) | 
+			((PCI_FUNC(devfn)) << 8) | (where & ~3) | 1;
+	}
+	return addr;
+}
+
+/*
+ * Mask table, bits to mask for quantity of size 1, 2 or 4 bytes.
+ * 0 and 3 are not valid indexes...
+ */
+static u32 bytemask[] = {
+	/*0*/	0,
+	/*1*/	0xff,
+	/*2*/	0xffff,
+	/*3*/	0,
+	/*4*/	0xffffffff,
+};
+
+static u32 local_byte_lane_enable_bits(u32 n, int size)
+{
+	if (size == 1)
+		return (0xf & ~BIT(n)) << CRP_AD_CBE_BESL;
+	if (size == 2)
+		return (0xf & ~(BIT(n) | BIT(n+1))) << CRP_AD_CBE_BESL;
+	if (size == 4)
+		return 0;
+	return 0xffffffff;
+}
+
+static int local_read_config(int where, int size, u32 *value)
+{ 
+	u32 n, data;
+	pr_debug("local_read_config from %d size %d\n", where, size);
+	n = where % 4;
+	crp_read(where & ~3, &data);
+	*value = (data >> (8*n)) & bytemask[size];
+	pr_debug("local_read_config read %#x\n", *value);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int local_write_config(int where, int size, u32 value)
+{
+	u32 n, byte_enables, data;
+	pr_debug("local_write_config %#x to %d size %d\n", value, where, size);
+	n = where % 4;
+	byte_enables = local_byte_lane_enable_bits(n, size);
+	if (byte_enables == 0xffffffff)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	data = value << (8*n);
+	crp_write((where & ~3) | byte_enables, data);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static u32 byte_lane_enable_bits(u32 n, int size)
+{
+	if (size == 1)
+		return (0xf & ~BIT(n)) << 4;
+	if (size == 2)
+		return (0xf & ~(BIT(n) | BIT(n+1))) << 4;
+	if (size == 4)
+		return 0;
+	return 0xffffffff;
+}
+
+static int ixp4xx_pci_read_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
+{
+	u32 n, byte_enables, addr, data;
+	u8 bus_num = bus->number;
+
+	pr_debug("read_config from %d size %d dev %d:%d:%d\n", where, size,
+		bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn));
+
+	*value = 0xffffffff;
+	n = where % 4;
+	byte_enables = byte_lane_enable_bits(n, size);
+	if (byte_enables == 0xffffffff)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	addr = ixp4xx_config_addr(bus_num, devfn, where);
+	if (ixp4xx_pci_read(addr, byte_enables | NP_CMD_CONFIGREAD, &data))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	*value = (data >> (8*n)) & bytemask[size];
+	pr_debug("read_config_byte read %#x\n", *value);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int ixp4xx_pci_write_config(struct pci_bus *bus,  unsigned int devfn, int where, int size, u32 value)
+{
+	u32 n, byte_enables, addr, data;
+	u8 bus_num = bus->number;
+
+	pr_debug("write_config_byte %#x to %d size %d dev %d:%d:%d\n", value, where,
+		size, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn));
+
+	n = where % 4;
+	byte_enables = byte_lane_enable_bits(n, size);
+	if (byte_enables == 0xffffffff)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	addr = ixp4xx_config_addr(bus_num, devfn, where);
+	data = value << (8*n);
+	if (ixp4xx_pci_write(addr, byte_enables | NP_CMD_CONFIGWRITE, data))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops ixp4xx_ops = {
+	.read =  ixp4xx_pci_read_config,
+	.write = ixp4xx_pci_write_config,
+};
+
+/*
+ * PCI abort handler
+ */
+static int abort_handler(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+{
+	u32 isr, status;
+
+	isr = *PCI_ISR;
+	local_read_config(PCI_STATUS, 2, &status);
+	pr_debug("PCI: abort_handler addr = %#lx, isr = %#x, "
+		"status = %#x\n", addr, isr, status);
+
+	/* make sure the Master Abort bit is reset */    
+	*PCI_ISR = PCI_ISR_PFE;
+	status |= PCI_STATUS_REC_MASTER_ABORT;
+	local_write_config(PCI_STATUS, 2, status);
+
+	/*
+	 * If it was an imprecise abort, then we need to correct the
+	 * return address to be _after_ the instruction.
+	 */
+	if (fsr & (1 << 10))
+		regs->ARM_pc += 4;
+
+	return 0;
+}
+
+void __init ixp4xx_pci_preinit(void)
+{
+	unsigned long cpuid = read_cpuid_id();
+
+#ifdef CONFIG_IXP4XX_INDIRECT_PCI
+	pcibios_min_mem = 0x10000000; /* 1 GB of indirect PCI MMIO space */
+#else
+	pcibios_min_mem = 0x48000000; /* 64 MB of PCI MMIO space */
+#endif
+	/*
+	 * Determine which PCI read method to use.
+	 * Rev 0 IXP425 requires workaround.
+	 */
+	if (!(cpuid & 0xf) && cpu_is_ixp42x()) {
+		printk("PCI: IXP42x A0 silicon detected - "
+			"PCI Non-Prefetch Workaround Enabled\n");
+		ixp4xx_pci_read = ixp4xx_pci_read_errata;
+	} else
+		ixp4xx_pci_read = ixp4xx_pci_read_no_errata;
+
+
+	/* hook in our fault handler for PCI errors */
+	hook_fault_code(16+6, abort_handler, SIGBUS, 0,
+			"imprecise external abort");
+
+	pr_debug("setup PCI-AHB(inbound) and AHB-PCI(outbound) address mappings\n");
+
+	/*
+	 * We use identity AHB->PCI address translation
+	 * in the 0x48000000 to 0x4bffffff address space
+	 */
+	*PCI_PCIMEMBASE = 0x48494A4B;
+
+	/*
+	 * We also use identity PCI->AHB address translation
+	 * in 4 16MB BARs that begin at the physical memory start
+	 */
+	*PCI_AHBMEMBASE = (PHYS_OFFSET & 0xFF000000) +
+		((PHYS_OFFSET & 0xFF000000) >> 8) +
+		((PHYS_OFFSET & 0xFF000000) >> 16) +
+		((PHYS_OFFSET & 0xFF000000) >> 24) +
+		0x00010203;
+
+	if (*PCI_CSR & PCI_CSR_HOST) {
+		printk("PCI: IXP4xx is host\n");
+
+		pr_debug("setup BARs in controller\n");
+
+		/*
+		 * We configure the PCI inbound memory windows to be
+		 * 1:1 mapped to SDRAM
+		 */
+		local_write_config(PCI_BASE_ADDRESS_0, 4, PHYS_OFFSET);
+		local_write_config(PCI_BASE_ADDRESS_1, 4, PHYS_OFFSET + SZ_16M);
+		local_write_config(PCI_BASE_ADDRESS_2, 4, PHYS_OFFSET + SZ_32M);
+		local_write_config(PCI_BASE_ADDRESS_3, 4,
+					PHYS_OFFSET + SZ_32M + SZ_16M);
+
+		/*
+		 * Enable CSR window at 64 MiB to allow PCI masters
+		 * to continue prefetching past 64 MiB boundary.
+		 */
+		local_write_config(PCI_BASE_ADDRESS_4, 4, PHYS_OFFSET + SZ_64M);
+
+		/*
+		 * Enable the IO window to be way up high, at 0xfffffc00
+		 */
+		local_write_config(PCI_BASE_ADDRESS_5, 4, 0xfffffc01);
+		local_write_config(0x40, 4, 0x000080FF); /* No TRDY time limit */
+	} else {
+		printk("PCI: IXP4xx is target - No bus scan performed\n");
+	}
+
+	printk("PCI: IXP4xx Using %s access for memory space\n",
+#ifndef CONFIG_IXP4XX_INDIRECT_PCI
+			"direct"
+#else
+			"indirect"
+#endif
+		);
+
+	pr_debug("clear error bits in ISR\n");
+	*PCI_ISR = PCI_ISR_PSE | PCI_ISR_PFE | PCI_ISR_PPE | PCI_ISR_AHBE;
+
+	/*
+	 * Set Initialize Complete in PCI Control Register: allow IXP4XX to
+	 * respond to PCI configuration cycles. Specify that the AHB bus is
+	 * operating in big endian mode. Set up byte lane swapping between 
+	 * little-endian PCI and the big-endian AHB bus 
+	 */
+#ifdef __ARMEB__
+	*PCI_CSR = PCI_CSR_IC | PCI_CSR_ABE | PCI_CSR_PDS | PCI_CSR_ADS;
+#else
+	*PCI_CSR = PCI_CSR_IC | PCI_CSR_ABE;
+#endif
+
+	pr_debug("DONE\n");
+}
+
+int ixp4xx_setup(int nr, struct pci_sys_data *sys)
+{
+	struct resource *res;
+
+	if (nr >= 1)
+		return 0;
+
+	res = kzalloc(sizeof(*res) * 2, GFP_KERNEL);
+	if (res == NULL) {
+		/* 
+		 * If we're out of memory this early, something is wrong,
+		 * so we might as well catch it here.
+		 */
+		panic("PCI: unable to allocate resources?\n");
+	}
+
+	local_write_config(PCI_COMMAND, 2, PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
+
+	res[0].name = "PCI I/O Space";
+	res[0].start = 0x00000000;
+	res[0].end = 0x0000ffff;
+	res[0].flags = IORESOURCE_IO;
+
+	res[1].name = "PCI Memory Space";
+	res[1].start = PCIBIOS_MIN_MEM;
+	res[1].end = PCIBIOS_MAX_MEM;
+	res[1].flags = IORESOURCE_MEM;
+
+	request_resource(&ioport_resource, &res[0]);
+	request_resource(&iomem_resource, &res[1]);
+
+	pci_add_resource_offset(&sys->resources, &res[0], sys->io_offset);
+	pci_add_resource_offset(&sys->resources, &res[1], sys->mem_offset);
+
+	return 1;
+}
+
+EXPORT_SYMBOL(ixp4xx_pci_read);
+EXPORT_SYMBOL(ixp4xx_pci_write);
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/common.c b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/common.c
new file mode 100644
index 0000000..846e033
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/common.c
@@ -0,0 +1,684 @@
+/*
+ * arch/arm/mach-ixp4xx/common.c
+ *
+ * Generic code shared across all IXP4XX platforms
+ *
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2002 (c) Intel Corporation
+ * Copyright 2003-2004 (c) MontaVista, Software, Inc. 
+ * 
+ * This file is licensed under  the terms of the GNU General Public 
+ * License version 2. This program is licensed "as is" without any 
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/platform_device.h>
+#include <linux/serial_core.h>
+#include <linux/interrupt.h>
+#include <linux/bitops.h>
+#include <linux/time.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/io.h>
+#include <linux/export.h>
+#include <linux/gpio/driver.h>
+#include <linux/cpu.h>
+#include <linux/pci.h>
+#include <linux/sched_clock.h>
+#include <mach/udc.h>
+#include <mach/hardware.h>
+#include <mach/io.h>
+#include <linux/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/irq.h>
+#include <asm/system_misc.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+
+#define IXP4XX_TIMER_FREQ 66666000
+
+/*
+ * The timer register doesn't allow to specify the two least significant bits of
+ * the timeout value and assumes them being zero. So make sure IXP4XX_LATCH is
+ * the best value with the two least significant bits unset.
+ */
+#define IXP4XX_LATCH DIV_ROUND_CLOSEST(IXP4XX_TIMER_FREQ, \
+				       (IXP4XX_OST_RELOAD_MASK + 1) * HZ) * \
+			(IXP4XX_OST_RELOAD_MASK + 1)
+
+static void __init ixp4xx_clocksource_init(void);
+static void __init ixp4xx_clockevent_init(void);
+static struct clock_event_device clockevent_ixp4xx;
+
+/*************************************************************************
+ * IXP4xx chipset I/O mapping
+ *************************************************************************/
+static struct map_desc ixp4xx_io_desc[] __initdata = {
+	{	/* UART, Interrupt ctrl, GPIO, timers, NPEs, MACs, USB .... */
+		.virtual	= (unsigned long)IXP4XX_PERIPHERAL_BASE_VIRT,
+		.pfn		= __phys_to_pfn(IXP4XX_PERIPHERAL_BASE_PHYS),
+		.length		= IXP4XX_PERIPHERAL_REGION_SIZE,
+		.type		= MT_DEVICE
+	}, {	/* Expansion Bus Config Registers */
+		.virtual	= (unsigned long)IXP4XX_EXP_CFG_BASE_VIRT,
+		.pfn		= __phys_to_pfn(IXP4XX_EXP_CFG_BASE_PHYS),
+		.length		= IXP4XX_EXP_CFG_REGION_SIZE,
+		.type		= MT_DEVICE
+	}, {	/* PCI Registers */
+		.virtual	= (unsigned long)IXP4XX_PCI_CFG_BASE_VIRT,
+		.pfn		= __phys_to_pfn(IXP4XX_PCI_CFG_BASE_PHYS),
+		.length		= IXP4XX_PCI_CFG_REGION_SIZE,
+		.type		= MT_DEVICE
+	}, {	/* Queue Manager */
+		.virtual	= (unsigned long)IXP4XX_QMGR_BASE_VIRT,
+		.pfn		= __phys_to_pfn(IXP4XX_QMGR_BASE_PHYS),
+		.length		= IXP4XX_QMGR_REGION_SIZE,
+		.type		= MT_DEVICE
+	},
+};
+
+void __init ixp4xx_map_io(void)
+{
+  	iotable_init(ixp4xx_io_desc, ARRAY_SIZE(ixp4xx_io_desc));
+}
+
+/*
+ * GPIO-functions
+ */
+/*
+ * The following converted to the real HW bits the gpio_line_config
+ */
+/* GPIO pin types */
+#define IXP4XX_GPIO_OUT 		0x1
+#define IXP4XX_GPIO_IN  		0x2
+
+/* GPIO signal types */
+#define IXP4XX_GPIO_LOW			0
+#define IXP4XX_GPIO_HIGH		1
+
+/* GPIO Clocks */
+#define IXP4XX_GPIO_CLK_0		14
+#define IXP4XX_GPIO_CLK_1		15
+
+static void gpio_line_config(u8 line, u32 direction)
+{
+	if (direction == IXP4XX_GPIO_IN)
+		*IXP4XX_GPIO_GPOER |= (1 << line);
+	else
+		*IXP4XX_GPIO_GPOER &= ~(1 << line);
+}
+
+static void gpio_line_get(u8 line, int *value)
+{
+	*value = (*IXP4XX_GPIO_GPINR >> line) & 0x1;
+}
+
+static void gpio_line_set(u8 line, int value)
+{
+	if (value == IXP4XX_GPIO_HIGH)
+	    *IXP4XX_GPIO_GPOUTR |= (1 << line);
+	else if (value == IXP4XX_GPIO_LOW)
+	    *IXP4XX_GPIO_GPOUTR &= ~(1 << line);
+}
+
+/*************************************************************************
+ * IXP4xx chipset IRQ handling
+ *
+ * TODO: GPIO IRQs should be marked invalid until the user of the IRQ
+ *       (be it PCI or something else) configures that GPIO line
+ *       as an IRQ.
+ **************************************************************************/
+enum ixp4xx_irq_type {
+	IXP4XX_IRQ_LEVEL, IXP4XX_IRQ_EDGE
+};
+
+/* Each bit represents an IRQ: 1: edge-triggered, 0: level triggered */
+static unsigned long long ixp4xx_irq_edge = 0;
+
+/*
+ * IRQ -> GPIO mapping table
+ */
+static signed char irq2gpio[32] = {
+	-1, -1, -1, -1, -1, -1,  0,  1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1,  2,  3,  4,  5,  6,
+	 7,  8,  9, 10, 11, 12, -1, -1,
+};
+
+static int ixp4xx_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
+{
+	int irq;
+
+	for (irq = 0; irq < 32; irq++) {
+		if (irq2gpio[irq] == gpio)
+			return irq;
+	}
+	return -EINVAL;
+}
+
+static int ixp4xx_set_irq_type(struct irq_data *d, unsigned int type)
+{
+	int line = irq2gpio[d->irq];
+	u32 int_style;
+	enum ixp4xx_irq_type irq_type;
+	volatile u32 *int_reg;
+
+	/*
+	 * Only for GPIO IRQs
+	 */
+	if (line < 0)
+		return -EINVAL;
+
+	switch (type){
+	case IRQ_TYPE_EDGE_BOTH:
+		int_style = IXP4XX_GPIO_STYLE_TRANSITIONAL;
+		irq_type = IXP4XX_IRQ_EDGE;
+		break;
+	case IRQ_TYPE_EDGE_RISING:
+		int_style = IXP4XX_GPIO_STYLE_RISING_EDGE;
+		irq_type = IXP4XX_IRQ_EDGE;
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		int_style = IXP4XX_GPIO_STYLE_FALLING_EDGE;
+		irq_type = IXP4XX_IRQ_EDGE;
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH;
+		irq_type = IXP4XX_IRQ_LEVEL;
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW;
+		irq_type = IXP4XX_IRQ_LEVEL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (irq_type == IXP4XX_IRQ_EDGE)
+		ixp4xx_irq_edge |= (1 << d->irq);
+	else
+		ixp4xx_irq_edge &= ~(1 << d->irq);
+
+	if (line >= 8) {	/* pins 8-15 */
+		line -= 8;
+		int_reg = IXP4XX_GPIO_GPIT2R;
+	} else {		/* pins 0-7 */
+		int_reg = IXP4XX_GPIO_GPIT1R;
+	}
+
+	/* Clear the style for the appropriate pin */
+	*int_reg &= ~(IXP4XX_GPIO_STYLE_CLEAR <<
+	    		(line * IXP4XX_GPIO_STYLE_SIZE));
+
+	*IXP4XX_GPIO_GPISR = (1 << line);
+
+	/* Set the new style */
+	*int_reg |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE));
+
+	/* Configure the line as an input */
+	gpio_line_config(irq2gpio[d->irq], IXP4XX_GPIO_IN);
+
+	return 0;
+}
+
+static void ixp4xx_irq_mask(struct irq_data *d)
+{
+	if ((cpu_is_ixp46x() || cpu_is_ixp43x()) && d->irq >= 32)
+		*IXP4XX_ICMR2 &= ~(1 << (d->irq - 32));
+	else
+		*IXP4XX_ICMR &= ~(1 << d->irq);
+}
+
+static void ixp4xx_irq_ack(struct irq_data *d)
+{
+	int line = (d->irq < 32) ? irq2gpio[d->irq] : -1;
+
+	if (line >= 0)
+		*IXP4XX_GPIO_GPISR = (1 << line);
+}
+
+/*
+ * Level triggered interrupts on GPIO lines can only be cleared when the
+ * interrupt condition disappears.
+ */
+static void ixp4xx_irq_unmask(struct irq_data *d)
+{
+	if (!(ixp4xx_irq_edge & (1 << d->irq)))
+		ixp4xx_irq_ack(d);
+
+	if ((cpu_is_ixp46x() || cpu_is_ixp43x()) && d->irq >= 32)
+		*IXP4XX_ICMR2 |= (1 << (d->irq - 32));
+	else
+		*IXP4XX_ICMR |= (1 << d->irq);
+}
+
+static struct irq_chip ixp4xx_irq_chip = {
+	.name		= "IXP4xx",
+	.irq_ack	= ixp4xx_irq_ack,
+	.irq_mask	= ixp4xx_irq_mask,
+	.irq_unmask	= ixp4xx_irq_unmask,
+	.irq_set_type	= ixp4xx_set_irq_type,
+};
+
+void __init ixp4xx_init_irq(void)
+{
+	int i = 0;
+
+	/*
+	 * ixp4xx does not implement the XScale PWRMODE register
+	 * so it must not call cpu_do_idle().
+	 */
+	cpu_idle_poll_ctrl(true);
+
+	/* Route all sources to IRQ instead of FIQ */
+	*IXP4XX_ICLR = 0x0;
+
+	/* Disable all interrupt */
+	*IXP4XX_ICMR = 0x0; 
+
+	if (cpu_is_ixp46x() || cpu_is_ixp43x()) {
+		/* Route upper 32 sources to IRQ instead of FIQ */
+		*IXP4XX_ICLR2 = 0x00;
+
+		/* Disable upper 32 interrupts */
+		*IXP4XX_ICMR2 = 0x00;
+	}
+
+        /* Default to all level triggered */
+	for(i = 0; i < NR_IRQS; i++) {
+		irq_set_chip_and_handler(i, &ixp4xx_irq_chip,
+					 handle_level_irq);
+		irq_clear_status_flags(i, IRQ_NOREQUEST);
+	}
+}
+
+
+/*************************************************************************
+ * IXP4xx timer tick
+ * We use OS timer1 on the CPU for the timer tick and the timestamp 
+ * counter as a source of real clock ticks to account for missed jiffies.
+ *************************************************************************/
+
+static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = dev_id;
+
+	/* Clear Pending Interrupt by writing '1' to it */
+	*IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND;
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction ixp4xx_timer_irq = {
+	.name		= "timer1",
+	.flags		= IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= ixp4xx_timer_interrupt,
+	.dev_id		= &clockevent_ixp4xx,
+};
+
+void __init ixp4xx_timer_init(void)
+{
+	/* Reset/disable counter */
+	*IXP4XX_OSRT1 = 0;
+
+	/* Clear Pending Interrupt by writing '1' to it */
+	*IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND;
+
+	/* Reset time-stamp counter */
+	*IXP4XX_OSTS = 0;
+
+	/* Connect the interrupt handler and enable the interrupt */
+	setup_irq(IRQ_IXP4XX_TIMER1, &ixp4xx_timer_irq);
+
+	ixp4xx_clocksource_init();
+	ixp4xx_clockevent_init();
+}
+
+static struct pxa2xx_udc_mach_info ixp4xx_udc_info;
+
+void __init ixp4xx_set_udc_info(struct pxa2xx_udc_mach_info *info)
+{
+	memcpy(&ixp4xx_udc_info, info, sizeof *info);
+}
+
+static struct resource ixp4xx_udc_resources[] = {
+	[0] = {
+		.start  = 0xc800b000,
+		.end    = 0xc800bfff,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = IRQ_IXP4XX_USB,
+		.end    = IRQ_IXP4XX_USB,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+/*
+ * USB device controller. The IXP4xx uses the same controller as PXA25X,
+ * so we just use the same device.
+ */
+static struct platform_device ixp4xx_udc_device = {
+	.name           = "pxa25x-udc",
+	.id             = -1,
+	.num_resources  = 2,
+	.resource       = ixp4xx_udc_resources,
+	.dev            = {
+		.platform_data = &ixp4xx_udc_info,
+	},
+};
+
+static struct platform_device *ixp4xx_devices[] __initdata = {
+	&ixp4xx_udc_device,
+};
+
+static struct resource ixp46x_i2c_resources[] = {
+	[0] = {
+		.start 	= 0xc8011000,
+		.end	= 0xc801101c,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start 	= IRQ_IXP4XX_I2C,
+		.end	= IRQ_IXP4XX_I2C,
+		.flags	= IORESOURCE_IRQ
+	}
+};
+
+/*
+ * I2C controller. The IXP46x uses the same block as the IOP3xx, so
+ * we just use the same device name.
+ */
+static struct platform_device ixp46x_i2c_controller = {
+	.name		= "IOP3xx-I2C",
+	.id		= 0,
+	.num_resources	= 2,
+	.resource	= ixp46x_i2c_resources
+};
+
+static struct platform_device *ixp46x_devices[] __initdata = {
+	&ixp46x_i2c_controller
+};
+
+unsigned long ixp4xx_exp_bus_size;
+EXPORT_SYMBOL(ixp4xx_exp_bus_size);
+
+static int ixp4xx_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+{
+	gpio_line_config(gpio, IXP4XX_GPIO_IN);
+
+	return 0;
+}
+
+static int ixp4xx_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,
+					int level)
+{
+	gpio_line_set(gpio, level);
+	gpio_line_config(gpio, IXP4XX_GPIO_OUT);
+
+	return 0;
+}
+
+static int ixp4xx_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
+{
+	int value;
+
+	gpio_line_get(gpio, &value);
+
+	return value;
+}
+
+static void ixp4xx_gpio_set_value(struct gpio_chip *chip, unsigned gpio,
+				  int value)
+{
+	gpio_line_set(gpio, value);
+}
+
+static struct gpio_chip ixp4xx_gpio_chip = {
+	.label			= "IXP4XX_GPIO_CHIP",
+	.direction_input	= ixp4xx_gpio_direction_input,
+	.direction_output	= ixp4xx_gpio_direction_output,
+	.get			= ixp4xx_gpio_get_value,
+	.set			= ixp4xx_gpio_set_value,
+	.to_irq			= ixp4xx_gpio_to_irq,
+	.base			= 0,
+	.ngpio			= 16,
+};
+
+void __init ixp4xx_sys_init(void)
+{
+	ixp4xx_exp_bus_size = SZ_16M;
+
+	platform_add_devices(ixp4xx_devices, ARRAY_SIZE(ixp4xx_devices));
+
+	gpiochip_add_data(&ixp4xx_gpio_chip, NULL);
+
+	if (cpu_is_ixp46x()) {
+		int region;
+
+		platform_add_devices(ixp46x_devices,
+				ARRAY_SIZE(ixp46x_devices));
+
+		for (region = 0; region < 7; region++) {
+			if((*(IXP4XX_EXP_REG(0x4 * region)) & 0x200)) {
+				ixp4xx_exp_bus_size = SZ_32M;
+				break;
+			}
+		}
+	}
+
+	printk("IXP4xx: Using %luMiB expansion bus window size\n",
+			ixp4xx_exp_bus_size >> 20);
+}
+
+/*
+ * sched_clock()
+ */
+static u64 notrace ixp4xx_read_sched_clock(void)
+{
+	return *IXP4XX_OSTS;
+}
+
+/*
+ * clocksource
+ */
+
+static u64 ixp4xx_clocksource_read(struct clocksource *c)
+{
+	return *IXP4XX_OSTS;
+}
+
+unsigned long ixp4xx_timer_freq = IXP4XX_TIMER_FREQ;
+EXPORT_SYMBOL(ixp4xx_timer_freq);
+static void __init ixp4xx_clocksource_init(void)
+{
+	sched_clock_register(ixp4xx_read_sched_clock, 32, ixp4xx_timer_freq);
+
+	clocksource_mmio_init(NULL, "OSTS", ixp4xx_timer_freq, 200, 32,
+			ixp4xx_clocksource_read);
+}
+
+/*
+ * clockevents
+ */
+static int ixp4xx_set_next_event(unsigned long evt,
+				 struct clock_event_device *unused)
+{
+	unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK;
+
+	*IXP4XX_OSRT1 = (evt & ~IXP4XX_OST_RELOAD_MASK) | opts;
+
+	return 0;
+}
+
+static int ixp4xx_shutdown(struct clock_event_device *evt)
+{
+	unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK;
+	unsigned long osrt = *IXP4XX_OSRT1 & ~IXP4XX_OST_RELOAD_MASK;
+
+	opts &= ~IXP4XX_OST_ENABLE;
+	*IXP4XX_OSRT1 = osrt | opts;
+	return 0;
+}
+
+static int ixp4xx_set_oneshot(struct clock_event_device *evt)
+{
+	unsigned long opts = IXP4XX_OST_ENABLE | IXP4XX_OST_ONE_SHOT;
+	unsigned long osrt = 0;
+
+	/* period set by 'set next_event' */
+	*IXP4XX_OSRT1 = osrt | opts;
+	return 0;
+}
+
+static int ixp4xx_set_periodic(struct clock_event_device *evt)
+{
+	unsigned long opts = IXP4XX_OST_ENABLE;
+	unsigned long osrt = IXP4XX_LATCH & ~IXP4XX_OST_RELOAD_MASK;
+
+	*IXP4XX_OSRT1 = osrt | opts;
+	return 0;
+}
+
+static int ixp4xx_resume(struct clock_event_device *evt)
+{
+	unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK;
+	unsigned long osrt = *IXP4XX_OSRT1 & ~IXP4XX_OST_RELOAD_MASK;
+
+	opts |= IXP4XX_OST_ENABLE;
+	*IXP4XX_OSRT1 = osrt | opts;
+	return 0;
+}
+
+static struct clock_event_device clockevent_ixp4xx = {
+	.name			= "ixp4xx timer1",
+	.features		= CLOCK_EVT_FEAT_PERIODIC |
+				  CLOCK_EVT_FEAT_ONESHOT,
+	.rating			= 200,
+	.set_state_shutdown	= ixp4xx_shutdown,
+	.set_state_periodic	= ixp4xx_set_periodic,
+	.set_state_oneshot	= ixp4xx_set_oneshot,
+	.tick_resume		= ixp4xx_resume,
+	.set_next_event		= ixp4xx_set_next_event,
+};
+
+static void __init ixp4xx_clockevent_init(void)
+{
+	clockevent_ixp4xx.cpumask = cpumask_of(0);
+	clockevents_config_and_register(&clockevent_ixp4xx, IXP4XX_TIMER_FREQ,
+					0xf, 0xfffffffe);
+}
+
+void ixp4xx_restart(enum reboot_mode mode, const char *cmd)
+{
+	if (mode == REBOOT_SOFT) {
+		/* Jump into ROM at address 0 */
+		soft_restart(0);
+	} else {
+		/* Use on-chip reset capability */
+
+		/* set the "key" register to enable access to
+		 * "timer" and "enable" registers
+		 */
+		*IXP4XX_OSWK = IXP4XX_WDT_KEY;
+
+		/* write 0 to the timer register for an immediate reset */
+		*IXP4XX_OSWT = 0;
+
+		*IXP4XX_OSWE = IXP4XX_WDT_RESET_ENABLE | IXP4XX_WDT_COUNT_ENABLE;
+	}
+}
+
+#ifdef CONFIG_PCI
+static int ixp4xx_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size)
+{
+	return (dma_addr + size) > SZ_64M;
+}
+
+static int ixp4xx_platform_notify_remove(struct device *dev)
+{
+	if (dev_is_pci(dev))
+		dmabounce_unregister_dev(dev);
+
+	return 0;
+}
+#endif
+
+/*
+ * Setup DMA mask to 64MB on PCI devices and 4 GB on all other things.
+ */
+static int ixp4xx_platform_notify(struct device *dev)
+{
+	dev->dma_mask = &dev->coherent_dma_mask;
+
+#ifdef CONFIG_PCI
+	if (dev_is_pci(dev)) {
+		dev->coherent_dma_mask = DMA_BIT_MASK(28); /* 64 MB */
+		dmabounce_register_dev(dev, 2048, 4096, ixp4xx_needs_bounce);
+		return 0;
+	}
+#endif
+
+	dev->coherent_dma_mask = DMA_BIT_MASK(32);
+	return 0;
+}
+
+int dma_set_coherent_mask(struct device *dev, u64 mask)
+{
+	if (dev_is_pci(dev))
+		mask &= DMA_BIT_MASK(28); /* 64 MB */
+
+	if ((mask & DMA_BIT_MASK(28)) == DMA_BIT_MASK(28)) {
+		dev->coherent_dma_mask = mask;
+		return 0;
+	}
+
+	return -EIO;		/* device wanted sub-64MB mask */
+}
+EXPORT_SYMBOL(dma_set_coherent_mask);
+
+#ifdef CONFIG_IXP4XX_INDIRECT_PCI
+/*
+ * In the case of using indirect PCI, we simply return the actual PCI
+ * address and our read/write implementation use that to drive the
+ * access registers. If something outside of PCI is ioremap'd, we
+ * fallback to the default.
+ */
+
+static void __iomem *ixp4xx_ioremap_caller(phys_addr_t addr, size_t size,
+					   unsigned int mtype, void *caller)
+{
+	if (!is_pci_memory(addr))
+		return __arm_ioremap_caller(addr, size, mtype, caller);
+
+	return (void __iomem *)addr;
+}
+
+static void ixp4xx_iounmap(volatile void __iomem *addr)
+{
+	if (!is_pci_memory((__force u32)addr))
+		__iounmap(addr);
+}
+#endif
+
+void __init ixp4xx_init_early(void)
+{
+	platform_notify = ixp4xx_platform_notify;
+#ifdef CONFIG_PCI
+	platform_notify_remove = ixp4xx_platform_notify_remove;
+#endif
+#ifdef CONFIG_IXP4XX_INDIRECT_PCI
+	arch_ioremap_caller = ixp4xx_ioremap_caller;
+	arch_iounmap = ixp4xx_iounmap;
+#endif
+}
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/coyote-pci.c b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/coyote-pci.c
new file mode 100644
index 0000000..5d14ce2
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/coyote-pci.c
@@ -0,0 +1,64 @@
+/*
+ * arch/arm/mach-ixp4xx/coyote-pci.c
+ *
+ * PCI setup routines for ADI Engineering Coyote platform
+ *
+ * Copyright (C) 2002 Jungo Software Technologies.
+ * Copyright (C) 2003 MontaVista Softwrae, Inc.
+ *
+ * Maintainer: Deepak Saxena <dsaxena@mvista.com>
+ *
+ * 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/pci.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach/pci.h>
+
+#define SLOT0_DEVID	14
+#define SLOT1_DEVID	15
+
+/* PCI controller GPIO to IRQ pin mappings */
+#define SLOT0_INTA	6
+#define SLOT1_INTA	11
+
+void __init coyote_pci_preinit(void)
+{
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(SLOT0_INTA), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(SLOT1_INTA), IRQ_TYPE_LEVEL_LOW);
+	ixp4xx_pci_preinit();
+}
+
+static int __init coyote_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	if (slot == SLOT0_DEVID)
+		return IXP4XX_GPIO_IRQ(SLOT0_INTA);
+	else if (slot == SLOT1_DEVID)
+		return IXP4XX_GPIO_IRQ(SLOT1_INTA);
+	else return -1;
+}
+
+struct hw_pci coyote_pci __initdata = {
+	.nr_controllers = 1,
+	.ops		= &ixp4xx_ops,
+	.preinit =        coyote_pci_preinit,
+	.setup =          ixp4xx_setup,
+	.map_irq =        coyote_map_irq,
+};
+
+int __init coyote_pci_init(void)
+{
+	if (machine_is_adi_coyote())
+		pci_common_init(&coyote_pci);
+	return 0;
+}
+
+subsys_initcall(coyote_pci_init);
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/coyote-setup.c b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/coyote-setup.c
new file mode 100644
index 0000000..7e40fe7
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/coyote-setup.c
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * arch/arm/mach-ixp4xx/coyote-setup.c
+ *
+ * Board setup for ADI Engineering and IXDGP425 boards
+ *
+ * Copyright (C) 2003-2005 MontaVista Software, Inc.
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_8250.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <mach/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+#define COYOTE_IDE_BASE_PHYS	IXP4XX_EXP_BUS_BASE(3)
+#define COYOTE_IDE_BASE_VIRT	0xFFFE1000
+#define COYOTE_IDE_REGION_SIZE	0x1000
+
+#define COYOTE_IDE_DATA_PORT	0xFFFE10E0
+#define COYOTE_IDE_CTRL_PORT	0xFFFE10FC
+#define COYOTE_IDE_ERROR_PORT	0xFFFE10E2
+#define IRQ_COYOTE_IDE		IRQ_IXP4XX_GPIO5
+
+static struct flash_platform_data coyote_flash_data = {
+	.map_name	= "cfi_probe",
+	.width		= 2,
+};
+
+static struct resource coyote_flash_resource = {
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device coyote_flash = {
+	.name		= "IXP4XX-Flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &coyote_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &coyote_flash_resource,
+};
+
+static struct resource coyote_uart_resource = {
+	.start	= IXP4XX_UART2_BASE_PHYS,
+	.end	= IXP4XX_UART2_BASE_PHYS + 0x0fff,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct plat_serial8250_port coyote_uart_data[] = {
+	{
+		.mapbase	= IXP4XX_UART2_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART2,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	},
+	{ },
+};
+
+static struct platform_device coyote_uart = {
+	.name		= "serial8250",
+	.id		= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= coyote_uart_data,
+	},
+	.num_resources	= 1,
+	.resource	= &coyote_uart_resource,
+};
+
+static struct platform_device *coyote_devices[] __initdata = {
+	&coyote_flash,
+	&coyote_uart
+};
+
+static void __init coyote_init(void)
+{
+	ixp4xx_sys_init();
+
+	coyote_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+	coyote_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1;
+
+	*IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE;
+	*IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0;
+
+	if (machine_is_ixdpg425()) {
+		coyote_uart_data[0].membase =
+			(char*)(IXP4XX_UART1_BASE_VIRT + REG_OFFSET);
+		coyote_uart_data[0].mapbase = IXP4XX_UART1_BASE_PHYS;
+		coyote_uart_data[0].irq = IRQ_IXP4XX_UART1;
+	}
+
+	platform_add_devices(coyote_devices, ARRAY_SIZE(coyote_devices));
+}
+
+#ifdef CONFIG_ARCH_ADI_COYOTE
+MACHINE_START(ADI_COYOTE, "ADI Engineering Coyote")
+	/* Maintainer: MontaVista Software, Inc. */
+	.map_io		= ixp4xx_map_io,
+	.init_early	= ixp4xx_init_early,
+	.init_irq	= ixp4xx_init_irq,
+	.init_time	= ixp4xx_timer_init,
+	.atag_offset	= 0x100,
+	.init_machine	= coyote_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
+	.restart	= ixp4xx_restart,
+MACHINE_END
+#endif
+
+/*
+ * IXDPG425 is identical to Coyote except for which serial port
+ * is connected.
+ */
+#ifdef CONFIG_MACH_IXDPG425
+MACHINE_START(IXDPG425, "Intel IXDPG425")
+	/* Maintainer: MontaVista Software, Inc. */
+	.map_io		= ixp4xx_map_io,
+	.init_early	= ixp4xx_init_early,
+	.init_irq	= ixp4xx_init_irq,
+	.init_time	= ixp4xx_timer_init,
+	.atag_offset	= 0x100,
+	.init_machine	= coyote_init,
+	.restart	= ixp4xx_restart,
+MACHINE_END
+#endif
+
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/dsmg600-pci.c b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/dsmg600-pci.c
new file mode 100644
index 0000000..8dca769
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/dsmg600-pci.c
@@ -0,0 +1,79 @@
+/*
+ * DSM-G600 board-level PCI initialization
+ *
+ * Copyright (C) 2006 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * based on ixdp425-pci.c:
+ *	Copyright (C) 2002 Intel Corporation.
+ *	Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ * Maintainer: http://www.nslu2-linux.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/init.h>
+#include <linux/irq.h>
+#include <asm/mach/pci.h>
+#include <asm/mach-types.h>
+
+#define MAX_DEV		4
+#define IRQ_LINES	3
+
+/* PCI controller GPIO to IRQ pin mappings */
+#define INTA		11
+#define INTB		10
+#define INTC		9
+#define INTD		8
+#define INTE		7
+#define INTF		6
+
+void __init dsmg600_pci_preinit(void)
+{
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTE), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTF), IRQ_TYPE_LEVEL_LOW);
+	ixp4xx_pci_preinit();
+}
+
+static int __init dsmg600_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	static int pci_irq_table[MAX_DEV][IRQ_LINES] = {
+		{ IXP4XX_GPIO_IRQ(INTE), -1, -1 },
+		{ IXP4XX_GPIO_IRQ(INTA), -1, -1 },
+		{ IXP4XX_GPIO_IRQ(INTB), IXP4XX_GPIO_IRQ(INTC),
+		  IXP4XX_GPIO_IRQ(INTD) },
+		{ IXP4XX_GPIO_IRQ(INTF), -1, -1 },
+	};
+
+	if (slot >= 1 && slot <= MAX_DEV && pin >= 1 && pin <= IRQ_LINES)
+		return pci_irq_table[slot - 1][pin - 1];
+
+	return -1;
+}
+
+struct hw_pci __initdata dsmg600_pci = {
+	.nr_controllers = 1,
+	.ops		= &ixp4xx_ops,
+	.preinit	= dsmg600_pci_preinit,
+	.setup		= ixp4xx_setup,
+	.map_irq	= dsmg600_map_irq,
+};
+
+int __init dsmg600_pci_init(void)
+{
+	if (machine_is_dsmg600())
+		pci_common_init(&dsmg600_pci);
+
+	return 0;
+}
+
+subsys_initcall(dsmg600_pci_init);
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/dsmg600-setup.c b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/dsmg600-setup.c
new file mode 100644
index 0000000..db488ec
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/dsmg600-setup.c
@@ -0,0 +1,299 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DSM-G600 board-setup
+ *
+ * Copyright (C) 2008 Rod Whitby <rod@whitby.id.au>
+ * Copyright (C) 2006 Tower Technologies
+ *
+ * based on ixdp425-setup.c:
+ *      Copyright (C) 2003-2004 MontaVista Software, Inc.
+ * based on nslu2-power.c:
+ *	Copyright (C) 2005 Tower Technologies
+ * based on nslu2-io.c:
+ *	Copyright (C) 2004 Karen Spearel
+ *
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ * Author: Michael Westerhof <mwester@dls.net>
+ * Author: Rod Whitby <rod@whitby.id.au>
+ * Maintainers: http://www.nslu2-linux.org/
+ */
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/jiffies.h>
+#include <linux/timer.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/leds.h>
+#include <linux/reboot.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
+
+#include <mach/hardware.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/time.h>
+
+#define DSMG600_SDA_PIN		5
+#define DSMG600_SCL_PIN		4
+
+/* DSM-G600 Timer Setting */
+#define DSMG600_FREQ		66000000
+
+/* Buttons */
+#define DSMG600_PB_GPIO		15	/* power button */
+#define DSMG600_RB_GPIO		3	/* reset button */
+
+/* Power control */
+#define DSMG600_PO_GPIO		2	/* power off */
+
+/* LEDs */
+#define DSMG600_LED_PWR_GPIO	0
+#define DSMG600_LED_WLAN_GPIO	14
+
+static struct flash_platform_data dsmg600_flash_data = {
+	.map_name		= "cfi_probe",
+	.width			= 2,
+};
+
+static struct resource dsmg600_flash_resource = {
+	.flags			= IORESOURCE_MEM,
+};
+
+static struct platform_device dsmg600_flash = {
+	.name			= "IXP4XX-Flash",
+	.id			= 0,
+	.dev.platform_data	= &dsmg600_flash_data,
+	.num_resources		= 1,
+	.resource		= &dsmg600_flash_resource,
+};
+
+static struct i2c_gpio_platform_data dsmg600_i2c_gpio_data = {
+	.sda_pin		= DSMG600_SDA_PIN,
+	.scl_pin		= DSMG600_SCL_PIN,
+};
+
+static struct platform_device dsmg600_i2c_gpio = {
+	.name			= "i2c-gpio",
+	.id			= 0,
+	.dev	 = {
+		.platform_data	= &dsmg600_i2c_gpio_data,
+	},
+};
+
+static struct i2c_board_info __initdata dsmg600_i2c_board_info [] = {
+	{
+		I2C_BOARD_INFO("pcf8563", 0x51),
+	},
+};
+
+static struct gpio_led dsmg600_led_pins[] = {
+	{
+		.name		= "dsmg600:green:power",
+		.gpio		= DSMG600_LED_PWR_GPIO,
+	},
+	{
+		.name		= "dsmg600:green:wlan",
+		.gpio		= DSMG600_LED_WLAN_GPIO,
+		.active_low	= true,
+	},
+};
+
+static struct gpio_led_platform_data dsmg600_led_data = {
+	.num_leds		= ARRAY_SIZE(dsmg600_led_pins),
+	.leds			= dsmg600_led_pins,
+};
+
+static struct platform_device dsmg600_leds = {
+	.name			= "leds-gpio",
+	.id			= -1,
+	.dev.platform_data	= &dsmg600_led_data,
+};
+
+static struct resource dsmg600_uart_resources[] = {
+	{
+		.start		= IXP4XX_UART1_BASE_PHYS,
+		.end		= IXP4XX_UART1_BASE_PHYS + 0x0fff,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= IXP4XX_UART2_BASE_PHYS,
+		.end		= IXP4XX_UART2_BASE_PHYS + 0x0fff,
+		.flags		= IORESOURCE_MEM,
+	}
+};
+
+static struct plat_serial8250_port dsmg600_uart_data[] = {
+	{
+		.mapbase	= IXP4XX_UART1_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART1,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	},
+	{
+		.mapbase	= IXP4XX_UART2_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART2,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	},
+	{ }
+};
+
+static struct platform_device dsmg600_uart = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev.platform_data	= dsmg600_uart_data,
+	.num_resources		= ARRAY_SIZE(dsmg600_uart_resources),
+	.resource		= dsmg600_uart_resources,
+};
+
+static struct platform_device *dsmg600_devices[] __initdata = {
+	&dsmg600_i2c_gpio,
+	&dsmg600_flash,
+	&dsmg600_leds,
+};
+
+static void dsmg600_power_off(void)
+{
+	/* enable the pwr cntl and drive it high */
+	gpio_direction_output(DSMG600_PO_GPIO, 1);
+}
+
+/* This is used to make sure the power-button pusher is serious.  The button
+ * must be held until the value of this counter reaches zero.
+ */
+static int power_button_countdown;
+
+/* Must hold the button down for at least this many counts to be processed */
+#define PBUTTON_HOLDDOWN_COUNT 4 /* 2 secs */
+
+static void dsmg600_power_handler(unsigned long data);
+static DEFINE_TIMER(dsmg600_power_timer, dsmg600_power_handler, 0, 0);
+
+static void dsmg600_power_handler(unsigned long data)
+{
+	/* This routine is called twice per second to check the
+	 * state of the power button.
+	 */
+
+	if (gpio_get_value(DSMG600_PB_GPIO)) {
+
+		/* IO Pin is 1 (button pushed) */
+		if (power_button_countdown > 0)
+			power_button_countdown--;
+
+	} else {
+
+		/* Done on button release, to allow for auto-power-on mods. */
+		if (power_button_countdown == 0) {
+			/* Signal init to do the ctrlaltdel action,
+			 * this will bypass init if it hasn't started
+			 * and do a kernel_restart.
+			 */
+			ctrl_alt_del();
+
+			/* Change the state of the power LED to "blink" */
+			gpio_set_value(DSMG600_LED_PWR_GPIO, 0);
+		} else {
+			power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
+		}
+	}
+
+	mod_timer(&dsmg600_power_timer, jiffies + msecs_to_jiffies(500));
+}
+
+static irqreturn_t dsmg600_reset_handler(int irq, void *dev_id)
+{
+	/* This is the paper-clip reset, it shuts the machine down directly. */
+	machine_power_off();
+
+	return IRQ_HANDLED;
+}
+
+static void __init dsmg600_timer_init(void)
+{
+    /* The xtal on this machine is non-standard. */
+    ixp4xx_timer_freq = DSMG600_FREQ;
+
+    /* Call standard timer_init function. */
+    ixp4xx_timer_init();
+}
+
+static int __init dsmg600_gpio_init(void)
+{
+	if (!machine_is_dsmg600())
+		return 0;
+
+	gpio_request(DSMG600_RB_GPIO, "reset button");
+	if (request_irq(gpio_to_irq(DSMG600_RB_GPIO), &dsmg600_reset_handler,
+		IRQF_TRIGGER_LOW, "DSM-G600 reset button", NULL) < 0) {
+
+		printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
+			gpio_to_irq(DSMG600_RB_GPIO));
+	}
+
+	/*
+	 * The power button on the D-Link DSM-G600 is on GPIO 15, but
+	 * it cannot handle interrupts on that GPIO line.  So we'll
+	 * have to poll it with a kernel timer.
+	 */
+
+	/* Make sure that the power button GPIO is set up as an input */
+	gpio_request(DSMG600_PB_GPIO, "power button");
+	gpio_direction_input(DSMG600_PB_GPIO);
+	/* Request poweroff GPIO line */
+	gpio_request(DSMG600_PO_GPIO, "power off button");
+
+	/* Set the initial value for the power button IRQ handler */
+	power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
+
+	mod_timer(&dsmg600_power_timer, jiffies + msecs_to_jiffies(500));
+	return 0;
+}
+device_initcall(dsmg600_gpio_init);
+
+static void __init dsmg600_init(void)
+{
+	ixp4xx_sys_init();
+
+	/* Make sure that GPIO14 and GPIO15 are not used as clocks */
+	*IXP4XX_GPIO_GPCLKR = 0;
+
+	dsmg600_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+	dsmg600_flash_resource.end =
+		IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
+
+	i2c_register_board_info(0, dsmg600_i2c_board_info,
+				ARRAY_SIZE(dsmg600_i2c_board_info));
+
+	/* The UART is required on the DSM-G600 (Redboot cannot use the
+	 * NIC) -- do it here so that it does *not* get removed if
+	 * platform_add_devices fails!
+         */
+        (void)platform_device_register(&dsmg600_uart);
+
+	platform_add_devices(dsmg600_devices, ARRAY_SIZE(dsmg600_devices));
+
+	pm_power_off = dsmg600_power_off;
+}
+
+MACHINE_START(DSMG600, "D-Link DSM-G600 RevA")
+	/* Maintainer: www.nslu2-linux.org */
+	.atag_offset	= 0x100,
+	.map_io		= ixp4xx_map_io,
+	.init_early	= ixp4xx_init_early,
+	.init_irq	= ixp4xx_init_irq,
+	.init_time	= dsmg600_timer_init,
+	.init_machine	= dsmg600_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
+	.restart	= ixp4xx_restart,
+MACHINE_END
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/fsg-pci.c b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/fsg-pci.c
new file mode 100644
index 0000000..fd4a862
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/fsg-pci.c
@@ -0,0 +1,75 @@
+/*
+ * arch/arch/mach-ixp4xx/fsg-pci.c
+ *
+ * FSG board-level PCI initialization
+ *
+ * Author: Rod Whitby <rod@whitby.id.au>
+ * Maintainer: http://www.nslu2-linux.org/
+ *
+ * based on ixdp425-pci.c:
+ *	Copyright (C) 2002 Intel Corporation.
+ *	Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ * 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/init.h>
+#include <linux/irq.h>
+#include <asm/mach/pci.h>
+#include <asm/mach-types.h>
+
+#define MAX_DEV		3
+#define IRQ_LINES	3
+
+/* PCI controller GPIO to IRQ pin mappings */
+#define INTA	6
+#define INTB	7
+#define INTC	5
+
+void __init fsg_pci_preinit(void)
+{
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
+	ixp4xx_pci_preinit();
+}
+
+static int __init fsg_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	static int pci_irq_table[IRQ_LINES] = {
+		IXP4XX_GPIO_IRQ(INTC),
+		IXP4XX_GPIO_IRQ(INTB),
+		IXP4XX_GPIO_IRQ(INTA),
+	};
+
+	int irq = -1;
+	slot -= 11;
+
+	if (slot >= 1 && slot <= MAX_DEV && pin >= 1 && pin <= IRQ_LINES)
+		irq = pci_irq_table[slot - 1];
+	printk(KERN_INFO "%s: Mapped slot %d pin %d to IRQ %d\n",
+	       __func__, slot, pin, irq);
+
+	return irq;
+}
+
+struct hw_pci fsg_pci __initdata = {
+	.nr_controllers = 1,
+	.ops		= &ixp4xx_ops,
+	.preinit =	  fsg_pci_preinit,
+	.setup =	  ixp4xx_setup,
+	.map_irq =	  fsg_map_irq,
+};
+
+int __init fsg_pci_init(void)
+{
+	if (machine_is_fsg())
+		pci_common_init(&fsg_pci);
+	return 0;
+}
+
+subsys_initcall(fsg_pci_init);
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/fsg-setup.c b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/fsg-setup.c
new file mode 100644
index 0000000..6e32cbc
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/fsg-setup.c
@@ -0,0 +1,282 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * arch/arm/mach-ixp4xx/fsg-setup.c
+ *
+ * FSG board-setup
+ *
+ * Copyright (C) 2008 Rod Whitby <rod@whitby.id.au>
+ *
+ * based on ixdp425-setup.c:
+ *	Copyright (C) 2003-2004 MontaVista Software, Inc.
+ * based on nslu2-power.c
+ *	Copyright (C) 2005 Tower Technologies
+ *
+ * Author: Rod Whitby <rod@whitby.id.au>
+ * Maintainers: http://www.nslu2-linux.org/
+ *
+ */
+#include <linux/gpio.h>
+#include <linux/if_ether.h>
+#include <linux/irq.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/leds.h>
+#include <linux/reboot.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
+#include <linux/io.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+#define FSG_SDA_PIN		12
+#define FSG_SCL_PIN		13
+
+#define FSG_SB_GPIO		4	/* sync button */
+#define FSG_RB_GPIO		9	/* reset button */
+#define FSG_UB_GPIO		10	/* usb button */
+
+static struct flash_platform_data fsg_flash_data = {
+	.map_name		= "cfi_probe",
+	.width			= 2,
+};
+
+static struct resource fsg_flash_resource = {
+	.flags			= IORESOURCE_MEM,
+};
+
+static struct platform_device fsg_flash = {
+	.name			= "IXP4XX-Flash",
+	.id			= 0,
+	.dev = {
+		.platform_data	= &fsg_flash_data,
+	},
+	.num_resources		= 1,
+	.resource		= &fsg_flash_resource,
+};
+
+static struct i2c_gpio_platform_data fsg_i2c_gpio_data = {
+	.sda_pin		= FSG_SDA_PIN,
+	.scl_pin		= FSG_SCL_PIN,
+};
+
+static struct platform_device fsg_i2c_gpio = {
+	.name			= "i2c-gpio",
+	.id			= 0,
+	.dev = {
+		.platform_data	= &fsg_i2c_gpio_data,
+	},
+};
+
+static struct i2c_board_info __initdata fsg_i2c_board_info [] = {
+	{
+		I2C_BOARD_INFO("isl1208", 0x6f),
+	},
+};
+
+static struct resource fsg_uart_resources[] = {
+	{
+		.start		= IXP4XX_UART1_BASE_PHYS,
+		.end		= IXP4XX_UART1_BASE_PHYS + 0x0fff,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= IXP4XX_UART2_BASE_PHYS,
+		.end		= IXP4XX_UART2_BASE_PHYS + 0x0fff,
+		.flags		= IORESOURCE_MEM,
+	}
+};
+
+static struct plat_serial8250_port fsg_uart_data[] = {
+	{
+		.mapbase	= IXP4XX_UART1_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART1,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	},
+	{
+		.mapbase	= IXP4XX_UART2_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART2,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	},
+	{ }
+};
+
+static struct platform_device fsg_uart = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev = {
+		.platform_data	= fsg_uart_data,
+	},
+	.num_resources		= ARRAY_SIZE(fsg_uart_resources),
+	.resource		= fsg_uart_resources,
+};
+
+static struct platform_device fsg_leds = {
+	.name		= "fsg-led",
+	.id		= -1,
+};
+
+/* Built-in 10/100 Ethernet MAC interfaces */
+static struct eth_plat_info fsg_plat_eth[] = {
+	{
+		.phy		= 5,
+		.rxq		= 3,
+		.txreadyq	= 20,
+	}, {
+		.phy		= 4,
+		.rxq		= 4,
+		.txreadyq	= 21,
+	}
+};
+
+static struct platform_device fsg_eth[] = {
+	{
+		.name			= "ixp4xx_eth",
+		.id			= IXP4XX_ETH_NPEB,
+		.dev = {
+			.platform_data	= fsg_plat_eth,
+		},
+	}, {
+		.name			= "ixp4xx_eth",
+		.id			= IXP4XX_ETH_NPEC,
+		.dev = {
+			.platform_data	= fsg_plat_eth + 1,
+		},
+	}
+};
+
+static struct platform_device *fsg_devices[] __initdata = {
+	&fsg_i2c_gpio,
+	&fsg_flash,
+	&fsg_leds,
+	&fsg_eth[0],
+	&fsg_eth[1],
+};
+
+static irqreturn_t fsg_power_handler(int irq, void *dev_id)
+{
+	/* Signal init to do the ctrlaltdel action, this will bypass init if
+	 * it hasn't started and do a kernel_restart.
+	 */
+	ctrl_alt_del();
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t fsg_reset_handler(int irq, void *dev_id)
+{
+	/* This is the paper-clip reset which does an emergency reboot. */
+	printk(KERN_INFO "Restarting system.\n");
+	machine_restart(NULL);
+
+	/* This should never be reached. */
+	return IRQ_HANDLED;
+}
+
+static void __init fsg_init(void)
+{
+	uint8_t __iomem *f;
+
+	ixp4xx_sys_init();
+
+	fsg_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+	fsg_flash_resource.end =
+		IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
+
+	*IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE;
+	*IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0;
+
+	/* Configure CS2 for operation, 8bit and writable */
+	*IXP4XX_EXP_CS2 = 0xbfff0002;
+
+	i2c_register_board_info(0, fsg_i2c_board_info,
+				ARRAY_SIZE(fsg_i2c_board_info));
+
+	/* This is only useful on a modified machine, but it is valuable
+	 * to have it first in order to see debug messages, and so that
+	 * it does *not* get removed if platform_add_devices fails!
+	 */
+	(void)platform_device_register(&fsg_uart);
+
+	platform_add_devices(fsg_devices, ARRAY_SIZE(fsg_devices));
+
+	if (request_irq(gpio_to_irq(FSG_RB_GPIO), &fsg_reset_handler,
+			IRQF_TRIGGER_LOW, "FSG reset button", NULL) < 0) {
+
+		printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
+			gpio_to_irq(FSG_RB_GPIO));
+	}
+
+	if (request_irq(gpio_to_irq(FSG_SB_GPIO), &fsg_power_handler,
+			IRQF_TRIGGER_LOW, "FSG power button", NULL) < 0) {
+
+		printk(KERN_DEBUG "Power Button IRQ %d not available\n",
+			gpio_to_irq(FSG_SB_GPIO));
+	}
+
+	/*
+	 * Map in a portion of the flash and read the MAC addresses.
+	 * Since it is stored in BE in the flash itself, we need to
+	 * byteswap it if we're in LE mode.
+	 */
+	f = ioremap(IXP4XX_EXP_BUS_BASE(0), 0x400000);
+	if (f) {
+#ifdef __ARMEB__
+		int i;
+		for (i = 0; i < 6; i++) {
+			fsg_plat_eth[0].hwaddr[i] = readb(f + 0x3C0422 + i);
+			fsg_plat_eth[1].hwaddr[i] = readb(f + 0x3C043B + i);
+		}
+#else
+
+		/*
+		  Endian-swapped reads from unaligned addresses are
+		  required to extract the two MACs from the big-endian
+		  Redboot config area in flash.
+		*/
+
+		fsg_plat_eth[0].hwaddr[0] = readb(f + 0x3C0421);
+		fsg_plat_eth[0].hwaddr[1] = readb(f + 0x3C0420);
+		fsg_plat_eth[0].hwaddr[2] = readb(f + 0x3C0427);
+		fsg_plat_eth[0].hwaddr[3] = readb(f + 0x3C0426);
+		fsg_plat_eth[0].hwaddr[4] = readb(f + 0x3C0425);
+		fsg_plat_eth[0].hwaddr[5] = readb(f + 0x3C0424);
+
+		fsg_plat_eth[1].hwaddr[0] = readb(f + 0x3C0439);
+		fsg_plat_eth[1].hwaddr[1] = readb(f + 0x3C043F);
+		fsg_plat_eth[1].hwaddr[2] = readb(f + 0x3C043E);
+		fsg_plat_eth[1].hwaddr[3] = readb(f + 0x3C043D);
+		fsg_plat_eth[1].hwaddr[4] = readb(f + 0x3C043C);
+		fsg_plat_eth[1].hwaddr[5] = readb(f + 0x3C0443);
+#endif
+		iounmap(f);
+	}
+	printk(KERN_INFO "FSG: Using MAC address %pM for port 0\n",
+	       fsg_plat_eth[0].hwaddr);
+	printk(KERN_INFO "FSG: Using MAC address %pM for port 1\n",
+	       fsg_plat_eth[1].hwaddr);
+
+}
+
+MACHINE_START(FSG, "Freecom FSG-3")
+	/* Maintainer: www.nslu2-linux.org */
+	.map_io		= ixp4xx_map_io,
+	.init_early	= ixp4xx_init_early,
+	.init_irq	= ixp4xx_init_irq,
+	.init_time	= ixp4xx_timer_init,
+	.atag_offset	= 0x100,
+	.init_machine	= fsg_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
+	.restart	= ixp4xx_restart,
+MACHINE_END
+
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/gateway7001-pci.c b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/gateway7001-pci.c
new file mode 100644
index 0000000..d9d6cc0
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/gateway7001-pci.c
@@ -0,0 +1,63 @@
+/*
+ * arch/arch/mach-ixp4xx/gateway7001-pci.c
+ *
+ * PCI setup routines for Gateway 7001
+ *
+ * Copyright (C) 2007 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * based on coyote-pci.c:
+ *	Copyright (C) 2002 Jungo Software Technologies.
+ *	Copyright (C) 2003 MontaVista Softwrae, Inc.
+ *
+ * Maintainer: 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/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+
+#include <asm/mach/pci.h>
+
+void __init gateway7001_pci_preinit(void)
+{
+	irq_set_irq_type(IRQ_IXP4XX_GPIO10, IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IRQ_IXP4XX_GPIO11, IRQ_TYPE_LEVEL_LOW);
+
+	ixp4xx_pci_preinit();
+}
+
+static int __init gateway7001_map_irq(const struct pci_dev *dev, u8 slot,
+	u8 pin)
+{
+	if (slot == 1)
+		return IRQ_IXP4XX_GPIO11;
+	else if (slot == 2)
+		return IRQ_IXP4XX_GPIO10;
+	else return -1;
+}
+
+struct hw_pci gateway7001_pci __initdata = {
+	.nr_controllers = 1,
+	.ops		= &ixp4xx_ops,
+	.preinit =        gateway7001_pci_preinit,
+	.setup =          ixp4xx_setup,
+	.map_irq =        gateway7001_map_irq,
+};
+
+int __init gateway7001_pci_init(void)
+{
+	if (machine_is_gateway7001())
+		pci_common_init(&gateway7001_pci);
+	return 0;
+}
+
+subsys_initcall(gateway7001_pci_init);
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/gateway7001-setup.c b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/gateway7001-setup.c
new file mode 100644
index 0000000..1be6faf
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/gateway7001-setup.c
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * arch/arm/mach-ixp4xx/gateway7001-setup.c
+ *
+ * Board setup for the Gateway 7001 board
+ *
+ * Copyright (C) 2007 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * based on coyote-setup.c:
+ *      Copyright (C) 2003-2005 MontaVista Software, Inc.
+ *
+ * Author: Imre Kaloz <Kaloz@openwrt.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_8250.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <mach/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+static struct flash_platform_data gateway7001_flash_data = {
+	.map_name	= "cfi_probe",
+	.width		= 2,
+};
+
+static struct resource gateway7001_flash_resource = {
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device gateway7001_flash = {
+	.name		= "IXP4XX-Flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &gateway7001_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &gateway7001_flash_resource,
+};
+
+static struct resource gateway7001_uart_resource = {
+	.start	= IXP4XX_UART2_BASE_PHYS,
+	.end	= IXP4XX_UART2_BASE_PHYS + 0x0fff,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct plat_serial8250_port gateway7001_uart_data[] = {
+	{
+		.mapbase	= IXP4XX_UART2_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART2,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	},
+	{ },
+};
+
+static struct platform_device gateway7001_uart = {
+	.name		= "serial8250",
+	.id		= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= gateway7001_uart_data,
+	},
+	.num_resources	= 1,
+	.resource	= &gateway7001_uart_resource,
+};
+
+static struct platform_device *gateway7001_devices[] __initdata = {
+	&gateway7001_flash,
+	&gateway7001_uart
+};
+
+static void __init gateway7001_init(void)
+{
+	ixp4xx_sys_init();
+
+	gateway7001_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+	gateway7001_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1;
+
+	*IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE;
+	*IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0;
+
+	platform_add_devices(gateway7001_devices, ARRAY_SIZE(gateway7001_devices));
+}
+
+#ifdef CONFIG_MACH_GATEWAY7001
+MACHINE_START(GATEWAY7001, "Gateway 7001 AP")
+	/* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
+	.map_io		= ixp4xx_map_io,
+	.init_early	= ixp4xx_init_early,
+	.init_irq	= ixp4xx_init_irq,
+	.init_time	= ixp4xx_timer_init,
+	.atag_offset	= 0x100,
+	.init_machine	= gateway7001_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
+	.restart	= ixp4xx_restart,
+MACHINE_END
+#endif
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/goramo_mlr.c b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/goramo_mlr.c
new file mode 100644
index 0000000..145ec5c
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/goramo_mlr.c
@@ -0,0 +1,518 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Goramo MultiLink router platform code
+ * Copyright (C) 2006-2009 Krzysztof Halasa <khc@pm.waw.pl>
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/hdlc.h>
+#include <linux/i2c-gpio.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/serial_8250.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/pci.h>
+#include <asm/system_info.h>
+
+#define SLOT_ETHA		0x0B	/* IDSEL = AD21 */
+#define SLOT_ETHB		0x0C	/* IDSEL = AD20 */
+#define SLOT_MPCI		0x0D	/* IDSEL = AD19 */
+#define SLOT_NEC		0x0E	/* IDSEL = AD18 */
+
+/* GPIO lines */
+#define GPIO_SCL		0
+#define GPIO_SDA		1
+#define GPIO_STR		2
+#define GPIO_IRQ_NEC		3
+#define GPIO_IRQ_ETHA		4
+#define GPIO_IRQ_ETHB		5
+#define GPIO_HSS0_DCD_N		6
+#define GPIO_HSS1_DCD_N		7
+#define GPIO_UART0_DCD		8
+#define GPIO_UART1_DCD		9
+#define GPIO_HSS0_CTS_N		10
+#define GPIO_HSS1_CTS_N		11
+#define GPIO_IRQ_MPCI		12
+#define GPIO_HSS1_RTS_N		13
+#define GPIO_HSS0_RTS_N		14
+/* GPIO15 is not connected */
+
+/* Control outputs from 74HC4094 */
+#define CONTROL_HSS0_CLK_INT	0
+#define CONTROL_HSS1_CLK_INT	1
+#define CONTROL_HSS0_DTR_N	2
+#define CONTROL_HSS1_DTR_N	3
+#define CONTROL_EXT		4
+#define CONTROL_AUTO_RESET	5
+#define CONTROL_PCI_RESET_N	6
+#define CONTROL_EEPROM_WC_N	7
+
+/* offsets from start of flash ROM = 0x50000000 */
+#define CFG_ETH0_ADDRESS	0x40 /* 6 bytes */
+#define CFG_ETH1_ADDRESS	0x46 /* 6 bytes */
+#define CFG_REV			0x4C /* u32 */
+#define CFG_SDRAM_SIZE		0x50 /* u32 */
+#define CFG_SDRAM_CONF		0x54 /* u32 */
+#define CFG_SDRAM_MODE		0x58 /* u32 */
+#define CFG_SDRAM_REFRESH	0x5C /* u32 */
+
+#define CFG_HW_BITS		0x60 /* u32 */
+#define  CFG_HW_USB_PORTS	0x00000007 /* 0 = no NEC chip, 1-5 = ports # */
+#define  CFG_HW_HAS_PCI_SLOT	0x00000008
+#define  CFG_HW_HAS_ETH0	0x00000010
+#define  CFG_HW_HAS_ETH1	0x00000020
+#define  CFG_HW_HAS_HSS0	0x00000040
+#define  CFG_HW_HAS_HSS1	0x00000080
+#define  CFG_HW_HAS_UART0	0x00000100
+#define  CFG_HW_HAS_UART1	0x00000200
+#define  CFG_HW_HAS_EEPROM	0x00000400
+
+#define FLASH_CMD_READ_ARRAY	0xFF
+#define FLASH_CMD_READ_ID	0x90
+#define FLASH_SER_OFF		0x102 /* 0x81 in 16-bit mode */
+
+static u32 hw_bits = 0xFFFFFFFD;    /* assume all hardware present */;
+static u8 control_value;
+
+static void set_scl(u8 value)
+{
+	gpio_set_value(GPIO_SCL, !!value);
+	udelay(3);
+}
+
+static void set_sda(u8 value)
+{
+	gpio_set_value(GPIO_SDA, !!value);
+	udelay(3);
+}
+
+static void set_str(u8 value)
+{
+	gpio_set_value(GPIO_STR, !!value);
+	udelay(3);
+}
+
+static inline void set_control(int line, int value)
+{
+	if (value)
+		control_value |=  (1 << line);
+	else
+		control_value &= ~(1 << line);
+}
+
+
+static void output_control(void)
+{
+	int i;
+
+	gpio_direction_output(GPIO_SCL, 1);
+	gpio_direction_output(GPIO_SDA, 1);
+
+	for (i = 0; i < 8; i++) {
+		set_scl(0);
+		set_sda(control_value & (0x80 >> i)); /* MSB first */
+		set_scl(1);	/* active edge */
+	}
+
+	set_str(1);
+	set_str(0);
+
+	set_scl(0);
+	set_sda(1);		/* Be ready for START */
+	set_scl(1);
+}
+
+
+static void (*set_carrier_cb_tab[2])(void *pdev, int carrier);
+
+static int hss_set_clock(int port, unsigned int clock_type)
+{
+	int ctrl_int = port ? CONTROL_HSS1_CLK_INT : CONTROL_HSS0_CLK_INT;
+
+	switch (clock_type) {
+	case CLOCK_DEFAULT:
+	case CLOCK_EXT:
+		set_control(ctrl_int, 0);
+		output_control();
+		return CLOCK_EXT;
+
+	case CLOCK_INT:
+		set_control(ctrl_int, 1);
+		output_control();
+		return CLOCK_INT;
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static irqreturn_t hss_dcd_irq(int irq, void *pdev)
+{
+	int port = (irq == IXP4XX_GPIO_IRQ(GPIO_HSS1_DCD_N));
+	int i = gpio_get_value(port ? GPIO_HSS1_DCD_N : GPIO_HSS0_DCD_N);
+	set_carrier_cb_tab[port](pdev, !i);
+	return IRQ_HANDLED;
+}
+
+
+static int hss_open(int port, void *pdev,
+		    void (*set_carrier_cb)(void *pdev, int carrier))
+{
+	int i, irq;
+
+	if (!port)
+		irq = IXP4XX_GPIO_IRQ(GPIO_HSS0_DCD_N);
+	else
+		irq = IXP4XX_GPIO_IRQ(GPIO_HSS1_DCD_N);
+
+	i = gpio_get_value(port ? GPIO_HSS1_DCD_N : GPIO_HSS0_DCD_N);
+	set_carrier_cb(pdev, !i);
+
+	set_carrier_cb_tab[!!port] = set_carrier_cb;
+
+	if ((i = request_irq(irq, hss_dcd_irq, 0, "IXP4xx HSS", pdev)) != 0) {
+		printk(KERN_ERR "ixp4xx_hss: failed to request IRQ%i (%i)\n",
+		       irq, i);
+		return i;
+	}
+
+	set_control(port ? CONTROL_HSS1_DTR_N : CONTROL_HSS0_DTR_N, 0);
+	output_control();
+	gpio_set_value(port ? GPIO_HSS1_RTS_N : GPIO_HSS0_RTS_N, 0);
+	return 0;
+}
+
+static void hss_close(int port, void *pdev)
+{
+	free_irq(port ? IXP4XX_GPIO_IRQ(GPIO_HSS1_DCD_N) :
+		 IXP4XX_GPIO_IRQ(GPIO_HSS0_DCD_N), pdev);
+	set_carrier_cb_tab[!!port] = NULL; /* catch bugs */
+
+	set_control(port ? CONTROL_HSS1_DTR_N : CONTROL_HSS0_DTR_N, 1);
+	output_control();
+	gpio_set_value(port ? GPIO_HSS1_RTS_N : GPIO_HSS0_RTS_N, 1);
+}
+
+
+/* Flash memory */
+static struct flash_platform_data flash_data = {
+	.map_name	= "cfi_probe",
+	.width		= 2,
+};
+
+static struct resource flash_resource = {
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device device_flash = {
+	.name		= "IXP4XX-Flash",
+	.id		= 0,
+	.dev		= { .platform_data = &flash_data },
+	.num_resources	= 1,
+	.resource	= &flash_resource,
+};
+
+
+/* I^2C interface */
+static struct i2c_gpio_platform_data i2c_data = {
+	.sda_pin	= GPIO_SDA,
+	.scl_pin	= GPIO_SCL,
+};
+
+static struct platform_device device_i2c = {
+	.name		= "i2c-gpio",
+	.id		= 0,
+	.dev		= { .platform_data = &i2c_data },
+};
+
+
+/* IXP425 2 UART ports */
+static struct resource uart_resources[] = {
+	{
+		.start		= IXP4XX_UART1_BASE_PHYS,
+		.end		= IXP4XX_UART1_BASE_PHYS + 0x0fff,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= IXP4XX_UART2_BASE_PHYS,
+		.end		= IXP4XX_UART2_BASE_PHYS + 0x0fff,
+		.flags		= IORESOURCE_MEM,
+	}
+};
+
+static struct plat_serial8250_port uart_data[] = {
+	{
+		.mapbase	= IXP4XX_UART1_BASE_PHYS,
+		.membase	= (char __iomem *)IXP4XX_UART1_BASE_VIRT +
+			REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART1,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	},
+	{
+		.mapbase	= IXP4XX_UART2_BASE_PHYS,
+		.membase	= (char __iomem *)IXP4XX_UART2_BASE_VIRT +
+			REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART2,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	},
+	{ },
+};
+
+static struct platform_device device_uarts = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev.platform_data	= uart_data,
+	.num_resources		= 2,
+	.resource		= uart_resources,
+};
+
+
+/* Built-in 10/100 Ethernet MAC interfaces */
+static struct eth_plat_info eth_plat[] = {
+	{
+		.phy		= 0,
+		.rxq		= 3,
+		.txreadyq	= 32,
+	}, {
+		.phy		= 1,
+		.rxq		= 4,
+		.txreadyq	= 33,
+	}
+};
+
+static struct platform_device device_eth_tab[] = {
+	{
+		.name			= "ixp4xx_eth",
+		.id			= IXP4XX_ETH_NPEB,
+		.dev.platform_data	= eth_plat,
+	}, {
+		.name			= "ixp4xx_eth",
+		.id			= IXP4XX_ETH_NPEC,
+		.dev.platform_data	= eth_plat + 1,
+	}
+};
+
+
+/* IXP425 2 synchronous serial ports */
+static struct hss_plat_info hss_plat[] = {
+	{
+		.set_clock	= hss_set_clock,
+		.open		= hss_open,
+		.close		= hss_close,
+		.txreadyq	= 34,
+	}, {
+		.set_clock	= hss_set_clock,
+		.open		= hss_open,
+		.close		= hss_close,
+		.txreadyq	= 35,
+	}
+};
+
+static struct platform_device device_hss_tab[] = {
+	{
+		.name			= "ixp4xx_hss",
+		.id			= 0,
+		.dev.platform_data	= hss_plat,
+	}, {
+		.name			= "ixp4xx_hss",
+		.id			= 1,
+		.dev.platform_data	= hss_plat + 1,
+	}
+};
+
+
+static struct platform_device *device_tab[7] __initdata = {
+	&device_flash,		/* index 0 */
+};
+
+static inline u8 __init flash_readb(u8 __iomem *flash, u32 addr)
+{
+#ifdef __ARMEB__
+	return __raw_readb(flash + addr);
+#else
+	return __raw_readb(flash + (addr ^ 3));
+#endif
+}
+
+static inline u16 __init flash_readw(u8 __iomem *flash, u32 addr)
+{
+#ifdef __ARMEB__
+	return __raw_readw(flash + addr);
+#else
+	return __raw_readw(flash + (addr ^ 2));
+#endif
+}
+
+static void __init gmlr_init(void)
+{
+	u8 __iomem *flash;
+	int i, devices = 1; /* flash */
+
+	ixp4xx_sys_init();
+
+	if ((flash = ioremap(IXP4XX_EXP_BUS_BASE_PHYS, 0x80)) == NULL)
+		printk(KERN_ERR "goramo-mlr: unable to access system"
+		       " configuration data\n");
+	else {
+		system_rev = __raw_readl(flash + CFG_REV);
+		hw_bits = __raw_readl(flash + CFG_HW_BITS);
+
+		for (i = 0; i < ETH_ALEN; i++) {
+			eth_plat[0].hwaddr[i] =
+				flash_readb(flash, CFG_ETH0_ADDRESS + i);
+			eth_plat[1].hwaddr[i] =
+				flash_readb(flash, CFG_ETH1_ADDRESS + i);
+		}
+
+		__raw_writew(FLASH_CMD_READ_ID, flash);
+		system_serial_high = flash_readw(flash, FLASH_SER_OFF);
+		system_serial_high <<= 16;
+		system_serial_high |= flash_readw(flash, FLASH_SER_OFF + 2);
+		system_serial_low = flash_readw(flash, FLASH_SER_OFF + 4);
+		system_serial_low <<= 16;
+		system_serial_low |= flash_readw(flash, FLASH_SER_OFF + 6);
+		__raw_writew(FLASH_CMD_READ_ARRAY, flash);
+
+		iounmap(flash);
+	}
+
+	switch (hw_bits & (CFG_HW_HAS_UART0 | CFG_HW_HAS_UART1)) {
+	case CFG_HW_HAS_UART0:
+		memset(&uart_data[1], 0, sizeof(uart_data[1]));
+		device_uarts.num_resources = 1;
+		break;
+
+	case CFG_HW_HAS_UART1:
+		device_uarts.dev.platform_data = &uart_data[1];
+		device_uarts.resource = &uart_resources[1];
+		device_uarts.num_resources = 1;
+		break;
+	}
+	if (hw_bits & (CFG_HW_HAS_UART0 | CFG_HW_HAS_UART1))
+		device_tab[devices++] = &device_uarts; /* max index 1 */
+
+	if (hw_bits & CFG_HW_HAS_ETH0)
+		device_tab[devices++] = &device_eth_tab[0]; /* max index 2 */
+	if (hw_bits & CFG_HW_HAS_ETH1)
+		device_tab[devices++] = &device_eth_tab[1]; /* max index 3 */
+
+	if (hw_bits & CFG_HW_HAS_HSS0)
+		device_tab[devices++] = &device_hss_tab[0]; /* max index 4 */
+	if (hw_bits & CFG_HW_HAS_HSS1)
+		device_tab[devices++] = &device_hss_tab[1]; /* max index 5 */
+
+	if (hw_bits & CFG_HW_HAS_EEPROM)
+		device_tab[devices++] = &device_i2c; /* max index 6 */
+
+	gpio_request(GPIO_SCL, "SCL/clock");
+	gpio_request(GPIO_SDA, "SDA/data");
+	gpio_request(GPIO_STR, "strobe");
+	gpio_request(GPIO_HSS0_RTS_N, "HSS0 RTS");
+	gpio_request(GPIO_HSS1_RTS_N, "HSS1 RTS");
+	gpio_request(GPIO_HSS0_DCD_N, "HSS0 DCD");
+	gpio_request(GPIO_HSS1_DCD_N, "HSS1 DCD");
+
+	gpio_direction_output(GPIO_SCL, 1);
+	gpio_direction_output(GPIO_SDA, 1);
+	gpio_direction_output(GPIO_STR, 0);
+	gpio_direction_output(GPIO_HSS0_RTS_N, 1);
+	gpio_direction_output(GPIO_HSS1_RTS_N, 1);
+	gpio_direction_input(GPIO_HSS0_DCD_N);
+	gpio_direction_input(GPIO_HSS1_DCD_N);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(GPIO_HSS0_DCD_N), IRQ_TYPE_EDGE_BOTH);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(GPIO_HSS1_DCD_N), IRQ_TYPE_EDGE_BOTH);
+
+	set_control(CONTROL_HSS0_DTR_N, 1);
+	set_control(CONTROL_HSS1_DTR_N, 1);
+	set_control(CONTROL_EEPROM_WC_N, 1);
+	set_control(CONTROL_PCI_RESET_N, 1);
+	output_control();
+
+	msleep(1);	      /* Wait for PCI devices to initialize */
+
+	flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+	flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
+
+	platform_add_devices(device_tab, devices);
+}
+
+
+#ifdef CONFIG_PCI
+static void __init gmlr_pci_preinit(void)
+{
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(GPIO_IRQ_ETHA), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(GPIO_IRQ_ETHB), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(GPIO_IRQ_NEC), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(GPIO_IRQ_MPCI), IRQ_TYPE_LEVEL_LOW);
+	ixp4xx_pci_preinit();
+}
+
+static void __init gmlr_pci_postinit(void)
+{
+	if ((hw_bits & CFG_HW_USB_PORTS) >= 2 &&
+	    (hw_bits & CFG_HW_USB_PORTS) < 5) {
+		/* need to adjust number of USB ports on NEC chip */
+		u32 value, addr = BIT(32 - SLOT_NEC) | 0xE0;
+		if (!ixp4xx_pci_read(addr, NP_CMD_CONFIGREAD, &value)) {
+			value &= ~7;
+			value |= (hw_bits & CFG_HW_USB_PORTS);
+			ixp4xx_pci_write(addr, NP_CMD_CONFIGWRITE, value);
+		}
+	}
+}
+
+static int __init gmlr_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	switch(slot) {
+	case SLOT_ETHA:	return IXP4XX_GPIO_IRQ(GPIO_IRQ_ETHA);
+	case SLOT_ETHB:	return IXP4XX_GPIO_IRQ(GPIO_IRQ_ETHB);
+	case SLOT_NEC:	return IXP4XX_GPIO_IRQ(GPIO_IRQ_NEC);
+	default:	return IXP4XX_GPIO_IRQ(GPIO_IRQ_MPCI);
+	}
+}
+
+static struct hw_pci gmlr_hw_pci __initdata = {
+	.nr_controllers = 1,
+	.ops		= &ixp4xx_ops,
+	.preinit	= gmlr_pci_preinit,
+	.postinit	= gmlr_pci_postinit,
+	.setup		= ixp4xx_setup,
+	.map_irq	= gmlr_map_irq,
+};
+
+static int __init gmlr_pci_init(void)
+{
+	if (machine_is_goramo_mlr() &&
+	    (hw_bits & (CFG_HW_USB_PORTS | CFG_HW_HAS_PCI_SLOT)))
+		pci_common_init(&gmlr_hw_pci);
+	return 0;
+}
+
+subsys_initcall(gmlr_pci_init);
+#endif /* CONFIG_PCI */
+
+
+MACHINE_START(GORAMO_MLR, "MultiLink")
+	/* Maintainer: Krzysztof Halasa */
+	.map_io		= ixp4xx_map_io,
+	.init_early	= ixp4xx_init_early,
+	.init_irq	= ixp4xx_init_irq,
+	.init_time	= ixp4xx_timer_init,
+	.atag_offset	= 0x100,
+	.init_machine	= gmlr_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
+	.restart	= ixp4xx_restart,
+MACHINE_END
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/gtwx5715-pci.c b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/gtwx5715-pci.c
new file mode 100644
index 0000000..551d114
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/gtwx5715-pci.c
@@ -0,0 +1,84 @@
+/*
+ * arch/arm/mach-ixp4xx/gtwx5715-pci.c
+ *
+ * Gemtek GTWX5715 (Linksys WRV54G) board setup
+ *
+ * Copyright (C) 2004 George T. Joseph
+ * Derived from Coyote
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <asm/mach/pci.h>
+
+#define SLOT0_DEVID	0
+#define SLOT1_DEVID	1
+#define INTA		10 /* slot 1 has INTA and INTB crossed */
+#define INTB		11
+
+/*
+ * Slot 0 isn't actually populated with a card connector but
+ * we initialize it anyway in case a future version has the
+ * slot populated or someone with good soldering skills has
+ * some free time.
+ */
+void __init gtwx5715_pci_preinit(void)
+{
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
+	ixp4xx_pci_preinit();
+}
+
+
+static int __init gtwx5715_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	int rc = -1;
+
+	if ((slot == SLOT0_DEVID && pin == 1) ||
+	    (slot == SLOT1_DEVID && pin == 2))
+		rc = IXP4XX_GPIO_IRQ(INTA);
+	else if ((slot == SLOT0_DEVID && pin == 2) ||
+		 (slot == SLOT1_DEVID && pin == 1))
+		rc = IXP4XX_GPIO_IRQ(INTB);
+
+	printk(KERN_INFO "%s: Mapped slot %d pin %d to IRQ %d\n",
+	       __func__, slot, pin, rc);
+	return rc;
+}
+
+struct hw_pci gtwx5715_pci __initdata = {
+	.nr_controllers = 1,
+	.ops		= &ixp4xx_ops,
+	.preinit =        gtwx5715_pci_preinit,
+	.setup =          ixp4xx_setup,
+	.map_irq =        gtwx5715_map_irq,
+};
+
+int __init gtwx5715_pci_init(void)
+{
+	if (machine_is_gtwx5715())
+		pci_common_init(&gtwx5715_pci);
+
+	return 0;
+}
+
+subsys_initcall(gtwx5715_pci_init);
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/gtwx5715-setup.c b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/gtwx5715-setup.c
new file mode 100644
index 0000000..16a1299
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/gtwx5715-setup.c
@@ -0,0 +1,179 @@
+/*
+ * arch/arm/mach-ixp4xx/gtwx5715-setup.c
+ *
+ * Gemtek GTWX5715 (Linksys WRV54G) board setup
+ *
+ * Copyright (C) 2004 George T. Joseph
+ * Derived from Coyote
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_8250.h>
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <mach/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+/* GPIO 5,6,7 and 12 are hard wired to the Kendin KS8995M Switch
+   and operate as an SPI type interface.  The details of the interface
+   are available on Kendin/Micrel's web site. */
+
+#define GTWX5715_KSSPI_SELECT	5
+#define GTWX5715_KSSPI_TXD	6
+#define GTWX5715_KSSPI_CLOCK	7
+#define GTWX5715_KSSPI_RXD	12
+
+/* The "reset" button is wired to GPIO 3.
+   The GPIO is brought "low" when the button is pushed. */
+
+#define GTWX5715_BUTTON_GPIO	3
+
+/* Board Label      Front Label
+   LED1             Power
+   LED2             Wireless-G
+   LED3             not populated but could be
+   LED4             Internet
+   LED5 - LED8      Controlled by KS8995M Switch
+   LED9             DMZ */
+
+#define GTWX5715_LED1_GPIO	2
+#define GTWX5715_LED2_GPIO	9
+#define GTWX5715_LED3_GPIO	8
+#define GTWX5715_LED4_GPIO	1
+#define GTWX5715_LED9_GPIO	4
+
+/*
+ * Xscale UART registers are 32 bits wide with only the least
+ * significant 8 bits having any meaning.  From a configuration
+ * perspective, this means 2 things...
+ *
+ *   Setting .regshift = 2 so that the standard 16550 registers
+ *   line up on every 4th byte.
+ *
+ *   Shifting the register start virtual address +3 bytes when
+ *   compiled big-endian.  Since register writes are done on a
+ *   single byte basis, if the shift isn't done the driver will
+ *   write the value into the most significant byte of the register,
+ *   which is ignored, instead of the least significant.
+ */
+
+#ifdef	__ARMEB__
+#define	REG_OFFSET	3
+#else
+#define	REG_OFFSET	0
+#endif
+
+/*
+ * Only the second or "console" uart is connected on the gtwx5715.
+ */
+
+static struct resource gtwx5715_uart_resources[] = {
+	{
+		.start	= IXP4XX_UART2_BASE_PHYS,
+		.end	= IXP4XX_UART2_BASE_PHYS + 0x0fff,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= IRQ_IXP4XX_UART2,
+		.end	= IRQ_IXP4XX_UART2,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{ },
+};
+
+
+static struct plat_serial8250_port gtwx5715_uart_platform_data[] = {
+	{
+	.mapbase	= IXP4XX_UART2_BASE_PHYS,
+	.membase	= (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+	.irq		= IRQ_IXP4XX_UART2,
+	.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+	.iotype		= UPIO_MEM,
+	.regshift	= 2,
+	.uartclk	= IXP4XX_UART_XTAL,
+	},
+	{ },
+};
+
+static struct platform_device gtwx5715_uart_device = {
+	.name		= "serial8250",
+	.id		= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= gtwx5715_uart_platform_data,
+	},
+	.num_resources	= 2,
+	.resource	= gtwx5715_uart_resources,
+};
+
+static struct flash_platform_data gtwx5715_flash_data = {
+	.map_name	= "cfi_probe",
+	.width		= 2,
+};
+
+static struct resource gtwx5715_flash_resource = {
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device gtwx5715_flash = {
+	.name		= "IXP4XX-Flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &gtwx5715_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &gtwx5715_flash_resource,
+};
+
+static struct platform_device *gtwx5715_devices[] __initdata = {
+	&gtwx5715_uart_device,
+	&gtwx5715_flash,
+};
+
+static void __init gtwx5715_init(void)
+{
+	ixp4xx_sys_init();
+
+	gtwx5715_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+	gtwx5715_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_8M - 1;
+
+	platform_add_devices(gtwx5715_devices, ARRAY_SIZE(gtwx5715_devices));
+}
+
+
+MACHINE_START(GTWX5715, "Gemtek GTWX5715 (Linksys WRV54G)")
+	/* Maintainer: George Joseph */
+	.map_io		= ixp4xx_map_io,
+	.init_early	= ixp4xx_init_early,
+	.init_irq	= ixp4xx_init_irq,
+	.init_time	= ixp4xx_timer_init,
+	.atag_offset	= 0x100,
+	.init_machine	= gtwx5715_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
+	.restart	= ixp4xx_restart,
+MACHINE_END
+
+
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/cpu.h b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/cpu.h
new file mode 100644
index 0000000..ebc0ba3
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/cpu.h
@@ -0,0 +1,58 @@
+/*
+ * arch/arm/mach-ixp4xx/include/mach/cpu.h
+ *
+ * IXP4XX cpu type detection
+ *
+ * Copyright (C) 2007 MontaVista Software, Inc.
+ *
+ * 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_ARCH_CPU_H__
+#define __ASM_ARCH_CPU_H__
+
+#include <linux/io.h>
+#include <asm/cputype.h>
+
+/* Processor id value in CP15 Register 0 */
+#define IXP42X_PROCESSOR_ID_VALUE	0x690541c0 /* including unused 0x690541Ex */
+#define IXP42X_PROCESSOR_ID_MASK	0xffffffc0
+
+#define IXP43X_PROCESSOR_ID_VALUE	0x69054040
+#define IXP43X_PROCESSOR_ID_MASK	0xfffffff0
+
+#define IXP46X_PROCESSOR_ID_VALUE	0x69054200 /* including IXP455 */
+#define IXP46X_PROCESSOR_ID_MASK	0xfffffff0
+
+#define cpu_is_ixp42x_rev_a0() ((read_cpuid_id() & (IXP42X_PROCESSOR_ID_MASK | 0xF)) == \
+				IXP42X_PROCESSOR_ID_VALUE)
+#define cpu_is_ixp42x()	((read_cpuid_id() & IXP42X_PROCESSOR_ID_MASK) == \
+			 IXP42X_PROCESSOR_ID_VALUE)
+#define cpu_is_ixp43x()	((read_cpuid_id() & IXP43X_PROCESSOR_ID_MASK) == \
+			 IXP43X_PROCESSOR_ID_VALUE)
+#define cpu_is_ixp46x()	((read_cpuid_id() & IXP46X_PROCESSOR_ID_MASK) == \
+			 IXP46X_PROCESSOR_ID_VALUE)
+
+static inline u32 ixp4xx_read_feature_bits(void)
+{
+	u32 val = ~__raw_readl(IXP4XX_EXP_CFG2);
+
+	if (cpu_is_ixp42x_rev_a0())
+		return IXP42X_FEATURE_MASK & ~(IXP4XX_FEATURE_RCOMP |
+					       IXP4XX_FEATURE_AES);
+	if (cpu_is_ixp42x())
+		return val & IXP42X_FEATURE_MASK;
+	if (cpu_is_ixp43x())
+		return val & IXP43X_FEATURE_MASK;
+	return val & IXP46X_FEATURE_MASK;
+}
+
+static inline void ixp4xx_write_feature_bits(u32 value)
+{
+	__raw_writel(~value, IXP4XX_EXP_CFG2);
+}
+
+#endif  /* _ASM_ARCH_CPU_H */
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/entry-macro.S b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/entry-macro.S
new file mode 100644
index 0000000..79adf83
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/entry-macro.S
@@ -0,0 +1,41 @@
+/*
+ * arch/arm/mach-ixp4xx/include/mach/entry-macro.S
+ *
+ * Low-level IRQ helper macros for IXP4xx-based platforms
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <mach/hardware.h>
+
+		.macro  get_irqnr_preamble, base, tmp
+		.endm
+
+		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+		ldr	\irqstat, =(IXP4XX_INTC_BASE_VIRT+IXP4XX_ICIP_OFFSET)
+		ldr	\irqstat, [\irqstat]		@ get interrupts
+		cmp	\irqstat, #0
+		beq	1001f				@ upper IRQ?
+		clz     \irqnr, \irqstat
+		mov     \base, #31
+		sub     \irqnr, \base, \irqnr
+		b	1002f				@ lower IRQ being
+							@ handled
+
+1001:
+		/*
+		 * IXP465/IXP435 has an upper IRQ status register
+		 */
+#if defined(CONFIG_CPU_IXP46X) || defined(CONFIG_CPU_IXP43X)
+		ldr	\irqstat, =(IXP4XX_INTC_BASE_VIRT+IXP4XX_ICIP2_OFFSET)
+		ldr	\irqstat, [\irqstat]		@ get upper interrupts
+		mov	\irqnr, #63
+		clz	\irqstat, \irqstat
+ 		cmp	\irqstat, #32
+		subne	\irqnr, \irqnr, \irqstat
+#endif
+1002:
+		.endm
+
+
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/hardware.h b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/hardware.h
new file mode 100644
index 0000000..034bb2a
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/hardware.h
@@ -0,0 +1,36 @@
+/*
+ * arch/arm/mach-ixp4xx/include/mach/hardware.h 
+ *
+ * Copyright (C) 2002 Intel Corporation.
+ * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ * 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.
+ *
+ */
+
+/*
+ * Hardware definitions for IXP4xx based systems
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H__
+#define __ASM_ARCH_HARDWARE_H__
+
+#ifdef CONFIG_IXP4XX_INDIRECT_PCI
+#define PCIBIOS_MAX_MEM		0x4FFFFFFF
+#else
+#define PCIBIOS_MAX_MEM		0x4BFFFFFF
+#endif
+
+/* Register locations and bits */
+#include "ixp4xx-regs.h"
+
+#ifndef __ASSEMBLER__
+#include <mach/cpu.h>
+#endif
+
+/* Platform helper functions and definitions */
+#include "platform.h"
+
+#endif  /* _ASM_ARCH_HARDWARE_H */
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/io.h b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/io.h
new file mode 100644
index 0000000..844e8ac
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/io.h
@@ -0,0 +1,548 @@
+/*
+ * arch/arm/mach-ixp4xx/include/mach/io.h
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright (C) 2002-2005  MontaVista Software, Inc.
+ *
+ * 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_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#include <linux/bitops.h>
+
+#include <mach/hardware.h>
+
+extern int (*ixp4xx_pci_read)(u32 addr, u32 cmd, u32* data);
+extern int ixp4xx_pci_write(u32 addr, u32 cmd, u32 data);
+
+
+/*
+ * IXP4xx provides two methods of accessing PCI memory space:
+ *
+ * 1) A direct mapped window from 0x48000000 to 0x4BFFFFFF (64MB).
+ *    To access PCI via this space, we simply ioremap() the BAR
+ *    into the kernel and we can use the standard read[bwl]/write[bwl]
+ *    macros. This is the preffered method due to speed but it
+ *    limits the system to just 64MB of PCI memory. This can be
+ *    problematic if using video cards and other memory-heavy targets.
+ *
+ * 2) If > 64MB of memory space is required, the IXP4xx can use indirect
+ *    registers to access the whole 4 GB of PCI memory space (as we do below
+ *    for I/O transactions). This allows currently for up to 1 GB (0x10000000
+ *    to 0x4FFFFFFF) of memory on the bus. The disadvantage of this is that
+ *    every PCI access requires three local register accesses plus a spinlock,
+ *    but in some cases the performance hit is acceptable. In addition, you
+ *    cannot mmap() PCI devices in this case.
+ */
+#ifdef	CONFIG_IXP4XX_INDIRECT_PCI
+
+/*
+ * In the case of using indirect PCI, we simply return the actual PCI
+ * address and our read/write implementation use that to drive the 
+ * access registers. If something outside of PCI is ioremap'd, we
+ * fallback to the default.
+ */
+
+extern unsigned long pcibios_min_mem;
+static inline int is_pci_memory(u32 addr)
+{
+	return (addr >= pcibios_min_mem) && (addr <= 0x4FFFFFFF);
+}
+
+#define writeb(v, p)			__indirect_writeb(v, p)
+#define writew(v, p)			__indirect_writew(v, p)
+#define writel(v, p)			__indirect_writel(v, p)
+
+#define writeb_relaxed(v, p)		__indirect_writeb(v, p)
+#define writew_relaxed(v, p)		__indirect_writew(v, p)
+#define writel_relaxed(v, p)		__indirect_writel(v, p)
+
+#define writesb(p, v, l)		__indirect_writesb(p, v, l)
+#define writesw(p, v, l)		__indirect_writesw(p, v, l)
+#define writesl(p, v, l)		__indirect_writesl(p, v, l)
+
+#define readb(p)			__indirect_readb(p)
+#define readw(p)			__indirect_readw(p)
+#define readl(p)			__indirect_readl(p)
+
+#define readb_relaxed(p)		__indirect_readb(p)
+#define readw_relaxed(p)		__indirect_readw(p)
+#define readl_relaxed(p)		__indirect_readl(p)
+
+#define readsb(p, v, l)			__indirect_readsb(p, v, l)
+#define readsw(p, v, l)			__indirect_readsw(p, v, l)
+#define readsl(p, v, l)			__indirect_readsl(p, v, l)
+
+static inline void __indirect_writeb(u8 value, volatile void __iomem *p)
+{
+	u32 addr = (u32)p;
+	u32 n, byte_enables, data;
+
+	if (!is_pci_memory(addr)) {
+		__raw_writeb(value, p);
+		return;
+	}
+
+	n = addr % 4;
+	byte_enables = (0xf & ~BIT(n)) << IXP4XX_PCI_NP_CBE_BESL;
+	data = value << (8*n);
+	ixp4xx_pci_write(addr, byte_enables | NP_CMD_MEMWRITE, data);
+}
+
+static inline void __indirect_writesb(volatile void __iomem *bus_addr,
+				      const void *p, int count)
+{
+	const u8 *vaddr = p;
+
+	while (count--)
+		writeb(*vaddr++, bus_addr);
+}
+
+static inline void __indirect_writew(u16 value, volatile void __iomem *p)
+{
+	u32 addr = (u32)p;
+	u32 n, byte_enables, data;
+
+	if (!is_pci_memory(addr)) {
+		__raw_writew(value, p);
+		return;
+	}
+
+	n = addr % 4;
+	byte_enables = (0xf & ~(BIT(n) | BIT(n+1))) << IXP4XX_PCI_NP_CBE_BESL;
+	data = value << (8*n);
+	ixp4xx_pci_write(addr, byte_enables | NP_CMD_MEMWRITE, data);
+}
+
+static inline void __indirect_writesw(volatile void __iomem *bus_addr,
+				      const void *p, int count)
+{
+	const u16 *vaddr = p;
+
+	while (count--)
+		writew(*vaddr++, bus_addr);
+}
+
+static inline void __indirect_writel(u32 value, volatile void __iomem *p)
+{
+	u32 addr = (__force u32)p;
+
+	if (!is_pci_memory(addr)) {
+		__raw_writel(value, p);
+		return;
+	}
+
+	ixp4xx_pci_write(addr, NP_CMD_MEMWRITE, value);
+}
+
+static inline void __indirect_writesl(volatile void __iomem *bus_addr,
+				      const void *p, int count)
+{
+	const u32 *vaddr = p;
+	while (count--)
+		writel(*vaddr++, bus_addr);
+}
+
+static inline u8 __indirect_readb(const volatile void __iomem *p)
+{
+	u32 addr = (u32)p;
+	u32 n, byte_enables, data;
+
+	if (!is_pci_memory(addr))
+		return __raw_readb(p);
+
+	n = addr % 4;
+	byte_enables = (0xf & ~BIT(n)) << IXP4XX_PCI_NP_CBE_BESL;
+	if (ixp4xx_pci_read(addr, byte_enables | NP_CMD_MEMREAD, &data))
+		return 0xff;
+
+	return data >> (8*n);
+}
+
+static inline void __indirect_readsb(const volatile void __iomem *bus_addr,
+				     void *p, u32 count)
+{
+	u8 *vaddr = p;
+
+	while (count--)
+		*vaddr++ = readb(bus_addr);
+}
+
+static inline u16 __indirect_readw(const volatile void __iomem *p)
+{
+	u32 addr = (u32)p;
+	u32 n, byte_enables, data;
+
+	if (!is_pci_memory(addr))
+		return __raw_readw(p);
+
+	n = addr % 4;
+	byte_enables = (0xf & ~(BIT(n) | BIT(n+1))) << IXP4XX_PCI_NP_CBE_BESL;
+	if (ixp4xx_pci_read(addr, byte_enables | NP_CMD_MEMREAD, &data))
+		return 0xffff;
+
+	return data>>(8*n);
+}
+
+static inline void __indirect_readsw(const volatile void __iomem *bus_addr,
+				     void *p, u32 count)
+{
+	u16 *vaddr = p;
+
+	while (count--)
+		*vaddr++ = readw(bus_addr);
+}
+
+static inline u32 __indirect_readl(const volatile void __iomem *p)
+{
+	u32 addr = (__force u32)p;
+	u32 data;
+
+	if (!is_pci_memory(addr))
+		return __raw_readl(p);
+
+	if (ixp4xx_pci_read(addr, NP_CMD_MEMREAD, &data))
+		return 0xffffffff;
+
+	return data;
+}
+
+static inline void __indirect_readsl(const volatile void __iomem *bus_addr,
+				     void *p, u32 count)
+{
+	u32 *vaddr = p;
+
+	while (count--)
+		*vaddr++ = readl(bus_addr);
+}
+
+
+/*
+ * We can use the built-in functions b/c they end up calling writeb/readb
+ */
+#define memset_io(c,v,l)		_memset_io((c),(v),(l))
+#define memcpy_fromio(a,c,l)		_memcpy_fromio((a),(c),(l))
+#define memcpy_toio(c,a,l)		_memcpy_toio((c),(a),(l))
+
+#endif /* CONFIG_IXP4XX_INDIRECT_PCI */
+
+#ifndef CONFIG_PCI
+
+#define	__io(v)		__typesafe_io(v)
+
+#else
+
+/*
+ * IXP4xx does not have a transparent cpu -> PCI I/O translation
+ * window.  Instead, it has a set of registers that must be tweaked
+ * with the proper byte lanes, command types, and address for the
+ * transaction.  This means that we need to override the default
+ * I/O functions.
+ */
+
+#define outb outb
+static inline void outb(u8 value, u32 addr)
+{
+	u32 n, byte_enables, data;
+	n = addr % 4;
+	byte_enables = (0xf & ~BIT(n)) << IXP4XX_PCI_NP_CBE_BESL;
+	data = value << (8*n);
+	ixp4xx_pci_write(addr, byte_enables | NP_CMD_IOWRITE, data);
+}
+
+#define outsb outsb
+static inline void outsb(u32 io_addr, const void *p, u32 count)
+{
+	const u8 *vaddr = p;
+
+	while (count--)
+		outb(*vaddr++, io_addr);
+}
+
+#define outw outw
+static inline void outw(u16 value, u32 addr)
+{
+	u32 n, byte_enables, data;
+	n = addr % 4;
+	byte_enables = (0xf & ~(BIT(n) | BIT(n+1))) << IXP4XX_PCI_NP_CBE_BESL;
+	data = value << (8*n);
+	ixp4xx_pci_write(addr, byte_enables | NP_CMD_IOWRITE, data);
+}
+
+#define outsw outsw
+static inline void outsw(u32 io_addr, const void *p, u32 count)
+{
+	const u16 *vaddr = p;
+	while (count--)
+		outw(cpu_to_le16(*vaddr++), io_addr);
+}
+
+#define outl outl
+static inline void outl(u32 value, u32 addr)
+{
+	ixp4xx_pci_write(addr, NP_CMD_IOWRITE, value);
+}
+
+#define outsl outsl
+static inline void outsl(u32 io_addr, const void *p, u32 count)
+{
+	const u32 *vaddr = p;
+	while (count--)
+		outl(cpu_to_le32(*vaddr++), io_addr);
+}
+
+#define inb inb
+static inline u8 inb(u32 addr)
+{
+	u32 n, byte_enables, data;
+	n = addr % 4;
+	byte_enables = (0xf & ~BIT(n)) << IXP4XX_PCI_NP_CBE_BESL;
+	if (ixp4xx_pci_read(addr, byte_enables | NP_CMD_IOREAD, &data))
+		return 0xff;
+
+	return data >> (8*n);
+}
+
+#define insb insb
+static inline void insb(u32 io_addr, void *p, u32 count)
+{
+	u8 *vaddr = p;
+	while (count--)
+		*vaddr++ = inb(io_addr);
+}
+
+#define inw inw
+static inline u16 inw(u32 addr)
+{
+	u32 n, byte_enables, data;
+	n = addr % 4;
+	byte_enables = (0xf & ~(BIT(n) | BIT(n+1))) << IXP4XX_PCI_NP_CBE_BESL;
+	if (ixp4xx_pci_read(addr, byte_enables | NP_CMD_IOREAD, &data))
+		return 0xffff;
+
+	return data>>(8*n);
+}
+
+#define insw insw
+static inline void insw(u32 io_addr, void *p, u32 count)
+{
+	u16 *vaddr = p;
+	while (count--)
+		*vaddr++ = le16_to_cpu(inw(io_addr));
+}
+
+#define inl inl
+static inline u32 inl(u32 addr)
+{
+	u32 data;
+	if (ixp4xx_pci_read(addr, NP_CMD_IOREAD, &data))
+		return 0xffffffff;
+
+	return data;
+}
+
+#define insl insl
+static inline void insl(u32 io_addr, void *p, u32 count)
+{
+	u32 *vaddr = p;
+	while (count--)
+		*vaddr++ = le32_to_cpu(inl(io_addr));
+}
+
+#define PIO_OFFSET      0x10000UL
+#define PIO_MASK        0x0ffffUL
+
+#define	__is_io_address(p)	(((unsigned long)p >= PIO_OFFSET) && \
+					((unsigned long)p <= (PIO_MASK + PIO_OFFSET)))
+
+#define	ioread8(p)			ioread8(p)
+static inline u8 ioread8(const void __iomem *addr)
+{
+	unsigned long port = (unsigned long __force)addr;
+	if (__is_io_address(port))
+		return (unsigned int)inb(port & PIO_MASK);
+	else
+#ifndef CONFIG_IXP4XX_INDIRECT_PCI
+		return (unsigned int)__raw_readb(addr);
+#else
+		return (unsigned int)__indirect_readb(addr);
+#endif
+}
+
+#define	ioread8_rep(p, v, c)		ioread8_rep(p, v, c)
+static inline void ioread8_rep(const void __iomem *addr, void *vaddr, u32 count)
+{
+	unsigned long port = (unsigned long __force)addr;
+	if (__is_io_address(port))
+		insb(port & PIO_MASK, vaddr, count);
+	else
+#ifndef	CONFIG_IXP4XX_INDIRECT_PCI
+		__raw_readsb(addr, vaddr, count);
+#else
+		__indirect_readsb(addr, vaddr, count);
+#endif
+}
+
+#define	ioread16(p)			ioread16(p)
+static inline u16 ioread16(const void __iomem *addr)
+{
+	unsigned long port = (unsigned long __force)addr;
+	if (__is_io_address(port))
+		return	(unsigned int)inw(port & PIO_MASK);
+	else
+#ifndef CONFIG_IXP4XX_INDIRECT_PCI
+		return le16_to_cpu((__force __le16)__raw_readw(addr));
+#else
+		return (unsigned int)__indirect_readw(addr);
+#endif
+}
+
+#define	ioread16_rep(p, v, c)		ioread16_rep(p, v, c)
+static inline void ioread16_rep(const void __iomem *addr, void *vaddr,
+				u32 count)
+{
+	unsigned long port = (unsigned long __force)addr;
+	if (__is_io_address(port))
+		insw(port & PIO_MASK, vaddr, count);
+	else
+#ifndef	CONFIG_IXP4XX_INDIRECT_PCI
+		__raw_readsw(addr, vaddr, count);
+#else
+		__indirect_readsw(addr, vaddr, count);
+#endif
+}
+
+#define	ioread32(p)			ioread32(p)
+static inline u32 ioread32(const void __iomem *addr)
+{
+	unsigned long port = (unsigned long __force)addr;
+	if (__is_io_address(port))
+		return	(unsigned int)inl(port & PIO_MASK);
+	else {
+#ifndef CONFIG_IXP4XX_INDIRECT_PCI
+		return le32_to_cpu((__force __le32)__raw_readl(addr));
+#else
+		return (unsigned int)__indirect_readl(addr);
+#endif
+	}
+}
+
+#define	ioread32_rep(p, v, c)		ioread32_rep(p, v, c)
+static inline void ioread32_rep(const void __iomem *addr, void *vaddr,
+				u32 count)
+{
+	unsigned long port = (unsigned long __force)addr;
+	if (__is_io_address(port))
+		insl(port & PIO_MASK, vaddr, count);
+	else
+#ifndef	CONFIG_IXP4XX_INDIRECT_PCI
+		__raw_readsl(addr, vaddr, count);
+#else
+		__indirect_readsl(addr, vaddr, count);
+#endif
+}
+
+#define	iowrite8(v, p)			iowrite8(v, p)
+static inline void iowrite8(u8 value, void __iomem *addr)
+{
+	unsigned long port = (unsigned long __force)addr;
+	if (__is_io_address(port))
+		outb(value, port & PIO_MASK);
+	else
+#ifndef CONFIG_IXP4XX_INDIRECT_PCI
+		__raw_writeb(value, addr);
+#else
+		__indirect_writeb(value, addr);
+#endif
+}
+
+#define	iowrite8_rep(p, v, c)		iowrite8_rep(p, v, c)
+static inline void iowrite8_rep(void __iomem *addr, const void *vaddr,
+				u32 count)
+{
+	unsigned long port = (unsigned long __force)addr;
+	if (__is_io_address(port))
+		outsb(port & PIO_MASK, vaddr, count);
+	else
+#ifndef CONFIG_IXP4XX_INDIRECT_PCI
+		__raw_writesb(addr, vaddr, count);
+#else
+		__indirect_writesb(addr, vaddr, count);
+#endif
+}
+
+#define	iowrite16(v, p)			iowrite16(v, p)
+static inline void iowrite16(u16 value, void __iomem *addr)
+{
+	unsigned long port = (unsigned long __force)addr;
+	if (__is_io_address(port))
+		outw(value, port & PIO_MASK);
+	else
+#ifndef CONFIG_IXP4XX_INDIRECT_PCI
+		__raw_writew(cpu_to_le16(value), addr);
+#else
+		__indirect_writew(value, addr);
+#endif
+}
+
+#define	iowrite16_rep(p, v, c)		iowrite16_rep(p, v, c)
+static inline void iowrite16_rep(void __iomem *addr, const void *vaddr,
+				 u32 count)
+{
+	unsigned long port = (unsigned long __force)addr;
+	if (__is_io_address(port))
+		outsw(port & PIO_MASK, vaddr, count);
+	else
+#ifndef CONFIG_IXP4XX_INDIRECT_PCI
+		__raw_writesw(addr, vaddr, count);
+#else
+		__indirect_writesw(addr, vaddr, count);
+#endif
+}
+
+#define	iowrite32(v, p)			iowrite32(v, p)
+static inline void iowrite32(u32 value, void __iomem *addr)
+{
+	unsigned long port = (unsigned long __force)addr;
+	if (__is_io_address(port))
+		outl(value, port & PIO_MASK);
+	else
+#ifndef CONFIG_IXP4XX_INDIRECT_PCI
+		__raw_writel((u32 __force)cpu_to_le32(value), addr);
+#else
+		__indirect_writel(value, addr);
+#endif
+}
+
+#define	iowrite32_rep(p, v, c)		iowrite32_rep(p, v, c)
+static inline void iowrite32_rep(void __iomem *addr, const void *vaddr,
+				 u32 count)
+{
+	unsigned long port = (unsigned long __force)addr;
+	if (__is_io_address(port))
+		outsl(port & PIO_MASK, vaddr, count);
+	else
+#ifndef CONFIG_IXP4XX_INDIRECT_PCI
+		__raw_writesl(addr, vaddr, count);
+#else
+		__indirect_writesl(addr, vaddr, count);
+#endif
+}
+
+#define ioport_map(port, nr) ioport_map(port, nr)
+static inline void __iomem *ioport_map(unsigned long port, unsigned int nr)
+{
+	return ((void __iomem*)((port) + PIO_OFFSET));
+}
+#define	ioport_unmap(addr) ioport_unmap(addr)
+static inline void ioport_unmap(void __iomem *addr)
+{
+}
+#endif /* CONFIG_PCI */
+
+#endif /* __ASM_ARM_ARCH_IO_H */
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/irqs.h b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/irqs.h
new file mode 100644
index 0000000..7e6d4cc
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/irqs.h
@@ -0,0 +1,75 @@
+/*
+ * arch/arm/mach-ixp4xx/include/mach/irqs.h 
+ *
+ * IRQ definitions for IXP4XX based systems
+ *
+ * Copyright (C) 2002 Intel Corporation.
+ * Copyright (C) 2003 MontaVista Software, Inc.
+ *
+ * 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 _ARCH_IXP4XX_IRQS_H_
+#define _ARCH_IXP4XX_IRQS_H_
+
+#define IRQ_IXP4XX_NPEA		0
+#define IRQ_IXP4XX_NPEB		1
+#define IRQ_IXP4XX_NPEC		2
+#define IRQ_IXP4XX_QM1		3
+#define IRQ_IXP4XX_QM2		4
+#define IRQ_IXP4XX_TIMER1	5
+#define IRQ_IXP4XX_GPIO0	6
+#define IRQ_IXP4XX_GPIO1	7
+#define IRQ_IXP4XX_PCI_INT	8
+#define IRQ_IXP4XX_PCI_DMA1	9
+#define IRQ_IXP4XX_PCI_DMA2	10
+#define IRQ_IXP4XX_TIMER2	11
+#define IRQ_IXP4XX_USB		12
+#define IRQ_IXP4XX_UART2	13
+#define IRQ_IXP4XX_TIMESTAMP	14
+#define IRQ_IXP4XX_UART1	15
+#define IRQ_IXP4XX_WDOG		16
+#define IRQ_IXP4XX_AHB_PMU	17
+#define IRQ_IXP4XX_XSCALE_PMU	18
+#define IRQ_IXP4XX_GPIO2	19
+#define IRQ_IXP4XX_GPIO3	20
+#define IRQ_IXP4XX_GPIO4	21
+#define IRQ_IXP4XX_GPIO5	22
+#define IRQ_IXP4XX_GPIO6	23
+#define IRQ_IXP4XX_GPIO7	24
+#define IRQ_IXP4XX_GPIO8	25
+#define IRQ_IXP4XX_GPIO9	26
+#define IRQ_IXP4XX_GPIO10	27
+#define IRQ_IXP4XX_GPIO11	28
+#define IRQ_IXP4XX_GPIO12	29
+#define IRQ_IXP4XX_SW_INT1	30
+#define IRQ_IXP4XX_SW_INT2	31
+#define IRQ_IXP4XX_USB_HOST	32
+#define IRQ_IXP4XX_I2C		33
+#define IRQ_IXP4XX_SSP		34
+#define IRQ_IXP4XX_TSYNC	35
+#define IRQ_IXP4XX_EAU_DONE	36
+#define IRQ_IXP4XX_SHA_DONE	37
+#define IRQ_IXP4XX_SWCP_PE	58
+#define IRQ_IXP4XX_QM_PE	60
+#define IRQ_IXP4XX_MCU_ECC	61
+#define IRQ_IXP4XX_EXP_PE	62
+
+#define _IXP4XX_GPIO_IRQ(n)	(IRQ_IXP4XX_GPIO ## n)
+#define IXP4XX_GPIO_IRQ(n)	_IXP4XX_GPIO_IRQ(n)
+
+/*
+ * Only first 32 sources are valid if running on IXP42x systems
+ */
+#if defined(CONFIG_CPU_IXP46X) || defined(CONFIG_CPU_IXP43X)
+#define NR_IRQS			64
+#else
+#define NR_IRQS			32
+#endif
+
+#define	XSCALE_PMU_IRQ		(IRQ_IXP4XX_XSCALE_PMU)
+
+#endif
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/ixp46x_ts.h b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/ixp46x_ts.h
new file mode 100644
index 0000000..cf03614
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/ixp46x_ts.h
@@ -0,0 +1,81 @@
+/*
+ * PTP 1588 clock using the IXP46X
+ *
+ * Copyright (C) 2010 OMICRON electronics GmbH
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _IXP46X_TS_H_
+#define _IXP46X_TS_H_
+
+#define DEFAULT_ADDEND 0xF0000029
+#define TICKS_NS_SHIFT 4
+
+struct ixp46x_channel_ctl {
+	u32 ch_control;  /* 0x40 Time Synchronization Channel Control */
+	u32 ch_event;    /* 0x44 Time Synchronization Channel Event */
+	u32 tx_snap_lo;  /* 0x48 Transmit Snapshot Low Register */
+	u32 tx_snap_hi;  /* 0x4C Transmit Snapshot High Register */
+	u32 rx_snap_lo;  /* 0x50 Receive Snapshot Low Register */
+	u32 rx_snap_hi;  /* 0x54 Receive Snapshot High Register */
+	u32 src_uuid_lo; /* 0x58 Source UUID0 Low Register */
+	u32 src_uuid_hi; /* 0x5C Sequence Identifier/Source UUID0 High */
+};
+
+struct ixp46x_ts_regs {
+	u32 control;     /* 0x00 Time Sync Control Register */
+	u32 event;       /* 0x04 Time Sync Event Register */
+	u32 addend;      /* 0x08 Time Sync Addend Register */
+	u32 accum;       /* 0x0C Time Sync Accumulator Register */
+	u32 test;        /* 0x10 Time Sync Test Register */
+	u32 unused;      /* 0x14 */
+	u32 rsystime_lo; /* 0x18 RawSystemTime_Low Register */
+	u32 rsystime_hi; /* 0x1C RawSystemTime_High Register */
+	u32 systime_lo;  /* 0x20 SystemTime_Low Register */
+	u32 systime_hi;  /* 0x24 SystemTime_High Register */
+	u32 trgt_lo;     /* 0x28 TargetTime_Low Register */
+	u32 trgt_hi;     /* 0x2C TargetTime_High Register */
+	u32 asms_lo;     /* 0x30 Auxiliary Slave Mode Snapshot Low  */
+	u32 asms_hi;     /* 0x34 Auxiliary Slave Mode Snapshot High */
+	u32 amms_lo;     /* 0x38 Auxiliary Master Mode Snapshot Low */
+	u32 amms_hi;     /* 0x3C Auxiliary Master Mode Snapshot High */
+
+	struct ixp46x_channel_ctl channel[3];
+};
+
+/* 0x00 Time Sync Control Register Bits */
+#define TSCR_AMM (1<<3)
+#define TSCR_ASM (1<<2)
+#define TSCR_TTM (1<<1)
+#define TSCR_RST (1<<0)
+
+/* 0x04 Time Sync Event Register Bits */
+#define TSER_SNM (1<<3)
+#define TSER_SNS (1<<2)
+#define TTIPEND  (1<<1)
+
+/* 0x40 Time Synchronization Channel Control Register Bits */
+#define MASTER_MODE   (1<<0)
+#define TIMESTAMP_ALL (1<<1)
+
+/* 0x44 Time Synchronization Channel Event Register Bits */
+#define TX_SNAPSHOT_LOCKED (1<<0)
+#define RX_SNAPSHOT_LOCKED (1<<1)
+
+/* The ptp_ixp46x module will set this variable */
+extern int ixp46x_phc_index;
+
+#endif
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h
new file mode 100644
index 0000000..b7ddd27
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h
@@ -0,0 +1,454 @@
+/*
+ * arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h
+ *
+ * Register definitions for IXP4xx chipset. This file contains 
+ * register location and bit definitions only. Platform specific 
+ * definitions and helper function declarations are in platform.h 
+ * and machine-name.h.
+ *
+ * Copyright (C) 2002 Intel Corporation.
+ * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ * 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_ARM_IXP4XX_H_
+#define _ASM_ARM_IXP4XX_H_
+
+/*
+ * IXP4xx Linux Memory Map:
+ *
+ * Phy		Size		Virt		Description
+ * =========================================================================
+ *
+ * 0x00000000	0x10000000(max)	PAGE_OFFSET	System RAM
+ *
+ * 0x48000000	0x04000000	ioremap'd	PCI Memory Space
+ *
+ * 0x50000000	0x10000000	ioremap'd	EXP BUS
+ *
+ * 0xC8000000	0x00013000	0xFEF00000	On-Chip Peripherals
+ *
+ * 0xC0000000	0x00001000	0xFEF13000	PCI CFG
+ *
+ * 0xC4000000	0x00001000	0xFEF14000	EXP CFG
+ *
+ * 0x60000000	0x00004000	0xFEF15000	QMgr
+ */
+
+/*
+ * Queue Manager
+ */
+#define IXP4XX_QMGR_BASE_PHYS		0x60000000
+#define IXP4XX_QMGR_BASE_VIRT		IOMEM(0xFEF15000)
+#define IXP4XX_QMGR_REGION_SIZE		0x00004000
+
+/*
+ * Peripheral space, including debug UART. Must be section-aligned so that
+ * it can be used with the low-level debug code.
+ */
+#define IXP4XX_PERIPHERAL_BASE_PHYS	0xC8000000
+#define IXP4XX_PERIPHERAL_BASE_VIRT	IOMEM(0xFEF00000)
+#define IXP4XX_PERIPHERAL_REGION_SIZE	0x00013000
+
+/*
+ * PCI Config registers
+ */
+#define IXP4XX_PCI_CFG_BASE_PHYS	0xC0000000
+#define IXP4XX_PCI_CFG_BASE_VIRT	IOMEM(0xFEF13000)
+#define IXP4XX_PCI_CFG_REGION_SIZE	0x00001000
+
+/*
+ * Expansion BUS Configuration registers
+ */
+#define IXP4XX_EXP_CFG_BASE_PHYS	0xC4000000
+#define IXP4XX_EXP_CFG_BASE_VIRT	0xFEF14000
+#define IXP4XX_EXP_CFG_REGION_SIZE	0x00001000
+
+#define IXP4XX_EXP_CS0_OFFSET	0x00
+#define IXP4XX_EXP_CS1_OFFSET   0x04
+#define IXP4XX_EXP_CS2_OFFSET   0x08
+#define IXP4XX_EXP_CS3_OFFSET   0x0C
+#define IXP4XX_EXP_CS4_OFFSET   0x10
+#define IXP4XX_EXP_CS5_OFFSET   0x14
+#define IXP4XX_EXP_CS6_OFFSET   0x18
+#define IXP4XX_EXP_CS7_OFFSET   0x1C
+#define IXP4XX_EXP_CFG0_OFFSET	0x20
+#define IXP4XX_EXP_CFG1_OFFSET	0x24
+#define IXP4XX_EXP_CFG2_OFFSET	0x28
+#define IXP4XX_EXP_CFG3_OFFSET	0x2C
+
+/*
+ * Expansion Bus Controller registers.
+ */
+#define IXP4XX_EXP_REG(x) ((volatile u32 __iomem *)(IXP4XX_EXP_CFG_BASE_VIRT+(x)))
+
+#define IXP4XX_EXP_CS0      IXP4XX_EXP_REG(IXP4XX_EXP_CS0_OFFSET)
+#define IXP4XX_EXP_CS1      IXP4XX_EXP_REG(IXP4XX_EXP_CS1_OFFSET)
+#define IXP4XX_EXP_CS2      IXP4XX_EXP_REG(IXP4XX_EXP_CS2_OFFSET) 
+#define IXP4XX_EXP_CS3      IXP4XX_EXP_REG(IXP4XX_EXP_CS3_OFFSET)
+#define IXP4XX_EXP_CS4      IXP4XX_EXP_REG(IXP4XX_EXP_CS4_OFFSET)
+#define IXP4XX_EXP_CS5      IXP4XX_EXP_REG(IXP4XX_EXP_CS5_OFFSET)
+#define IXP4XX_EXP_CS6      IXP4XX_EXP_REG(IXP4XX_EXP_CS6_OFFSET)     
+#define IXP4XX_EXP_CS7      IXP4XX_EXP_REG(IXP4XX_EXP_CS7_OFFSET)
+
+#define IXP4XX_EXP_CFG0     IXP4XX_EXP_REG(IXP4XX_EXP_CFG0_OFFSET) 
+#define IXP4XX_EXP_CFG1     IXP4XX_EXP_REG(IXP4XX_EXP_CFG1_OFFSET) 
+#define IXP4XX_EXP_CFG2     IXP4XX_EXP_REG(IXP4XX_EXP_CFG2_OFFSET) 
+#define IXP4XX_EXP_CFG3     IXP4XX_EXP_REG(IXP4XX_EXP_CFG3_OFFSET)
+
+
+/*
+ * Peripheral Space Register Region Base Addresses
+ */
+#define IXP4XX_UART1_BASE_PHYS		(IXP4XX_PERIPHERAL_BASE_PHYS + 0x0000)
+#define IXP4XX_UART2_BASE_PHYS		(IXP4XX_PERIPHERAL_BASE_PHYS + 0x1000)
+#define IXP4XX_PMU_BASE_PHYS		(IXP4XX_PERIPHERAL_BASE_PHYS + 0x2000)
+#define IXP4XX_INTC_BASE_PHYS		(IXP4XX_PERIPHERAL_BASE_PHYS + 0x3000)
+#define IXP4XX_GPIO_BASE_PHYS		(IXP4XX_PERIPHERAL_BASE_PHYS + 0x4000)
+#define IXP4XX_TIMER_BASE_PHYS		(IXP4XX_PERIPHERAL_BASE_PHYS + 0x5000)
+#define IXP4XX_NPEA_BASE_PHYS   	(IXP4XX_PERIPHERAL_BASE_PHYS + 0x6000)
+#define IXP4XX_NPEB_BASE_PHYS   	(IXP4XX_PERIPHERAL_BASE_PHYS + 0x7000)
+#define IXP4XX_NPEC_BASE_PHYS   	(IXP4XX_PERIPHERAL_BASE_PHYS + 0x8000)
+#define IXP4XX_EthB_BASE_PHYS		(IXP4XX_PERIPHERAL_BASE_PHYS + 0x9000)
+#define IXP4XX_EthC_BASE_PHYS		(IXP4XX_PERIPHERAL_BASE_PHYS + 0xA000)
+#define IXP4XX_USB_BASE_PHYS		(IXP4XX_PERIPHERAL_BASE_PHYS + 0xB000)
+/* ixp46X only */
+#define IXP4XX_EthA_BASE_PHYS		(IXP4XX_PERIPHERAL_BASE_PHYS + 0xC000)
+#define IXP4XX_EthB1_BASE_PHYS		(IXP4XX_PERIPHERAL_BASE_PHYS + 0xD000)
+#define IXP4XX_EthB2_BASE_PHYS		(IXP4XX_PERIPHERAL_BASE_PHYS + 0xE000)
+#define IXP4XX_EthB3_BASE_PHYS		(IXP4XX_PERIPHERAL_BASE_PHYS + 0xF000)
+#define IXP4XX_TIMESYNC_BASE_PHYS	(IXP4XX_PERIPHERAL_BASE_PHYS + 0x10000)
+#define IXP4XX_I2C_BASE_PHYS		(IXP4XX_PERIPHERAL_BASE_PHYS + 0x11000)
+#define IXP4XX_SSP_BASE_PHYS		(IXP4XX_PERIPHERAL_BASE_PHYS + 0x12000)
+
+
+#define IXP4XX_UART1_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0x0000)
+#define IXP4XX_UART2_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0x1000)
+#define IXP4XX_PMU_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0x2000)
+#define IXP4XX_INTC_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0x3000)
+#define IXP4XX_GPIO_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0x4000)
+#define IXP4XX_TIMER_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0x5000)
+#define IXP4XX_NPEA_BASE_VIRT   	(IXP4XX_PERIPHERAL_BASE_VIRT + 0x6000)
+#define IXP4XX_NPEB_BASE_VIRT   	(IXP4XX_PERIPHERAL_BASE_VIRT + 0x7000)
+#define IXP4XX_NPEC_BASE_VIRT   	(IXP4XX_PERIPHERAL_BASE_VIRT + 0x8000)
+#define IXP4XX_EthB_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0x9000)
+#define IXP4XX_EthC_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0xA000)
+#define IXP4XX_USB_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0xB000)
+/* ixp46X only */
+#define IXP4XX_EthA_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0xC000)
+#define IXP4XX_EthB1_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0xD000)
+#define IXP4XX_EthB2_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0xE000)
+#define IXP4XX_EthB3_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0xF000)
+#define IXP4XX_TIMESYNC_BASE_VIRT	(IXP4XX_PERIPHERAL_BASE_VIRT + 0x10000)
+#define IXP4XX_I2C_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0x11000)
+#define IXP4XX_SSP_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0x12000)
+
+/*
+ * Constants to make it easy to access  Interrupt Controller registers
+ */
+#define IXP4XX_ICPR_OFFSET	0x00 /* Interrupt Status */
+#define IXP4XX_ICMR_OFFSET	0x04 /* Interrupt Enable */
+#define IXP4XX_ICLR_OFFSET	0x08 /* Interrupt IRQ/FIQ Select */
+#define IXP4XX_ICIP_OFFSET      0x0C /* IRQ Status */
+#define IXP4XX_ICFP_OFFSET	0x10 /* FIQ Status */
+#define IXP4XX_ICHR_OFFSET	0x14 /* Interrupt Priority */
+#define IXP4XX_ICIH_OFFSET	0x18 /* IRQ Highest Pri Int */
+#define IXP4XX_ICFH_OFFSET	0x1C /* FIQ Highest Pri Int */
+
+/*
+ * IXP465-only
+ */
+#define	IXP4XX_ICPR2_OFFSET	0x20 /* Interrupt Status 2 */
+#define	IXP4XX_ICMR2_OFFSET	0x24 /* Interrupt Enable 2 */
+#define	IXP4XX_ICLR2_OFFSET	0x28 /* Interrupt IRQ/FIQ Select 2 */
+#define IXP4XX_ICIP2_OFFSET     0x2C /* IRQ Status */
+#define IXP4XX_ICFP2_OFFSET	0x30 /* FIQ Status */
+#define IXP4XX_ICEEN_OFFSET	0x34 /* Error High Pri Enable */
+
+
+/*
+ * Interrupt Controller Register Definitions.
+ */
+
+#define IXP4XX_INTC_REG(x) ((volatile u32 *)(IXP4XX_INTC_BASE_VIRT+(x)))
+
+#define IXP4XX_ICPR	IXP4XX_INTC_REG(IXP4XX_ICPR_OFFSET)
+#define IXP4XX_ICMR     IXP4XX_INTC_REG(IXP4XX_ICMR_OFFSET)
+#define IXP4XX_ICLR     IXP4XX_INTC_REG(IXP4XX_ICLR_OFFSET)
+#define IXP4XX_ICIP     IXP4XX_INTC_REG(IXP4XX_ICIP_OFFSET)
+#define IXP4XX_ICFP     IXP4XX_INTC_REG(IXP4XX_ICFP_OFFSET)
+#define IXP4XX_ICHR     IXP4XX_INTC_REG(IXP4XX_ICHR_OFFSET)
+#define IXP4XX_ICIH     IXP4XX_INTC_REG(IXP4XX_ICIH_OFFSET) 
+#define IXP4XX_ICFH     IXP4XX_INTC_REG(IXP4XX_ICFH_OFFSET)
+#define IXP4XX_ICPR2	IXP4XX_INTC_REG(IXP4XX_ICPR2_OFFSET)
+#define IXP4XX_ICMR2    IXP4XX_INTC_REG(IXP4XX_ICMR2_OFFSET)
+#define IXP4XX_ICLR2    IXP4XX_INTC_REG(IXP4XX_ICLR2_OFFSET)
+#define IXP4XX_ICIP2    IXP4XX_INTC_REG(IXP4XX_ICIP2_OFFSET)
+#define IXP4XX_ICFP2    IXP4XX_INTC_REG(IXP4XX_ICFP2_OFFSET)
+#define IXP4XX_ICEEN    IXP4XX_INTC_REG(IXP4XX_ICEEN_OFFSET)
+                                                                                
+/*
+ * Constants to make it easy to access GPIO registers
+ */
+#define IXP4XX_GPIO_GPOUTR_OFFSET       0x00
+#define IXP4XX_GPIO_GPOER_OFFSET        0x04
+#define IXP4XX_GPIO_GPINR_OFFSET        0x08
+#define IXP4XX_GPIO_GPISR_OFFSET        0x0C
+#define IXP4XX_GPIO_GPIT1R_OFFSET	0x10
+#define IXP4XX_GPIO_GPIT2R_OFFSET	0x14
+#define IXP4XX_GPIO_GPCLKR_OFFSET	0x18
+#define IXP4XX_GPIO_GPDBSELR_OFFSET	0x1C
+
+/* 
+ * GPIO Register Definitions.
+ * [Only perform 32bit reads/writes]
+ */
+#define IXP4XX_GPIO_REG(x) ((volatile u32 *)(IXP4XX_GPIO_BASE_VIRT+(x)))
+
+#define IXP4XX_GPIO_GPOUTR	IXP4XX_GPIO_REG(IXP4XX_GPIO_GPOUTR_OFFSET)
+#define IXP4XX_GPIO_GPOER       IXP4XX_GPIO_REG(IXP4XX_GPIO_GPOER_OFFSET)
+#define IXP4XX_GPIO_GPINR       IXP4XX_GPIO_REG(IXP4XX_GPIO_GPINR_OFFSET)
+#define IXP4XX_GPIO_GPISR       IXP4XX_GPIO_REG(IXP4XX_GPIO_GPISR_OFFSET)
+#define IXP4XX_GPIO_GPIT1R      IXP4XX_GPIO_REG(IXP4XX_GPIO_GPIT1R_OFFSET)
+#define IXP4XX_GPIO_GPIT2R      IXP4XX_GPIO_REG(IXP4XX_GPIO_GPIT2R_OFFSET)
+#define IXP4XX_GPIO_GPCLKR      IXP4XX_GPIO_REG(IXP4XX_GPIO_GPCLKR_OFFSET)
+#define IXP4XX_GPIO_GPDBSELR    IXP4XX_GPIO_REG(IXP4XX_GPIO_GPDBSELR_OFFSET)
+
+/*
+ * GPIO register bit definitions
+ */
+
+/* Interrupt styles
+ */
+#define IXP4XX_GPIO_STYLE_ACTIVE_HIGH	0x0
+#define IXP4XX_GPIO_STYLE_ACTIVE_LOW	0x1
+#define IXP4XX_GPIO_STYLE_RISING_EDGE	0x2
+#define IXP4XX_GPIO_STYLE_FALLING_EDGE	0x3
+#define IXP4XX_GPIO_STYLE_TRANSITIONAL	0x4
+
+/* 
+ * Mask used to clear interrupt styles 
+ */
+#define IXP4XX_GPIO_STYLE_CLEAR		0x7
+#define IXP4XX_GPIO_STYLE_SIZE		3
+
+/*
+ * Constants to make it easy to access Timer Control/Status registers
+ */
+#define IXP4XX_OSTS_OFFSET	0x00  /* Continious TimeStamp */
+#define IXP4XX_OST1_OFFSET	0x04  /* Timer 1 Timestamp */
+#define IXP4XX_OSRT1_OFFSET	0x08  /* Timer 1 Reload */
+#define IXP4XX_OST2_OFFSET	0x0C  /* Timer 2 Timestamp */
+#define IXP4XX_OSRT2_OFFSET	0x10  /* Timer 2 Reload */
+#define IXP4XX_OSWT_OFFSET	0x14  /* Watchdog Timer */
+#define IXP4XX_OSWE_OFFSET	0x18  /* Watchdog Enable */
+#define IXP4XX_OSWK_OFFSET	0x1C  /* Watchdog Key */
+#define IXP4XX_OSST_OFFSET	0x20  /* Timer Status */
+
+/*
+ * Operating System Timer Register Definitions.
+ */
+
+#define IXP4XX_TIMER_REG(x) ((volatile u32 *)(IXP4XX_TIMER_BASE_VIRT+(x)))
+
+#define IXP4XX_OSTS	IXP4XX_TIMER_REG(IXP4XX_OSTS_OFFSET)
+#define IXP4XX_OST1	IXP4XX_TIMER_REG(IXP4XX_OST1_OFFSET)
+#define IXP4XX_OSRT1	IXP4XX_TIMER_REG(IXP4XX_OSRT1_OFFSET)
+#define IXP4XX_OST2	IXP4XX_TIMER_REG(IXP4XX_OST2_OFFSET)
+#define IXP4XX_OSRT2	IXP4XX_TIMER_REG(IXP4XX_OSRT2_OFFSET)
+#define IXP4XX_OSWT	IXP4XX_TIMER_REG(IXP4XX_OSWT_OFFSET)
+#define IXP4XX_OSWE	IXP4XX_TIMER_REG(IXP4XX_OSWE_OFFSET)
+#define IXP4XX_OSWK	IXP4XX_TIMER_REG(IXP4XX_OSWK_OFFSET)
+#define IXP4XX_OSST	IXP4XX_TIMER_REG(IXP4XX_OSST_OFFSET)
+
+/*
+ * Timer register values and bit definitions 
+ */
+#define IXP4XX_OST_ENABLE		0x00000001
+#define IXP4XX_OST_ONE_SHOT		0x00000002
+/* Low order bits of reload value ignored */
+#define IXP4XX_OST_RELOAD_MASK		0x00000003
+#define IXP4XX_OST_DISABLED		0x00000000
+#define IXP4XX_OSST_TIMER_1_PEND	0x00000001
+#define IXP4XX_OSST_TIMER_2_PEND	0x00000002
+#define IXP4XX_OSST_TIMER_TS_PEND	0x00000004
+#define IXP4XX_OSST_TIMER_WDOG_PEND	0x00000008
+#define IXP4XX_OSST_TIMER_WARM_RESET	0x00000010
+
+#define	IXP4XX_WDT_KEY			0x0000482E
+
+#define	IXP4XX_WDT_RESET_ENABLE		0x00000001
+#define	IXP4XX_WDT_IRQ_ENABLE		0x00000002
+#define	IXP4XX_WDT_COUNT_ENABLE		0x00000004
+
+
+/*
+ * Constants to make it easy to access PCI Control/Status registers
+ */
+#define PCI_NP_AD_OFFSET            0x00
+#define PCI_NP_CBE_OFFSET           0x04
+#define PCI_NP_WDATA_OFFSET         0x08
+#define PCI_NP_RDATA_OFFSET         0x0c
+#define PCI_CRP_AD_CBE_OFFSET       0x10
+#define PCI_CRP_WDATA_OFFSET        0x14
+#define PCI_CRP_RDATA_OFFSET        0x18
+#define PCI_CSR_OFFSET              0x1c
+#define PCI_ISR_OFFSET              0x20
+#define PCI_INTEN_OFFSET            0x24
+#define PCI_DMACTRL_OFFSET          0x28
+#define PCI_AHBMEMBASE_OFFSET       0x2c
+#define PCI_AHBIOBASE_OFFSET        0x30
+#define PCI_PCIMEMBASE_OFFSET       0x34
+#define PCI_AHBDOORBELL_OFFSET      0x38
+#define PCI_PCIDOORBELL_OFFSET      0x3C
+#define PCI_ATPDMA0_AHBADDR_OFFSET  0x40
+#define PCI_ATPDMA0_PCIADDR_OFFSET  0x44
+#define PCI_ATPDMA0_LENADDR_OFFSET  0x48
+#define PCI_ATPDMA1_AHBADDR_OFFSET  0x4C
+#define PCI_ATPDMA1_PCIADDR_OFFSET  0x50
+#define PCI_ATPDMA1_LENADDR_OFFSET	0x54
+
+/*
+ * PCI Control/Status Registers
+ */
+#define IXP4XX_PCI_CSR(x) ((volatile u32 *)(IXP4XX_PCI_CFG_BASE_VIRT+(x)))
+
+#define PCI_NP_AD               IXP4XX_PCI_CSR(PCI_NP_AD_OFFSET)
+#define PCI_NP_CBE              IXP4XX_PCI_CSR(PCI_NP_CBE_OFFSET)
+#define PCI_NP_WDATA            IXP4XX_PCI_CSR(PCI_NP_WDATA_OFFSET)
+#define PCI_NP_RDATA            IXP4XX_PCI_CSR(PCI_NP_RDATA_OFFSET)
+#define PCI_CRP_AD_CBE          IXP4XX_PCI_CSR(PCI_CRP_AD_CBE_OFFSET)
+#define PCI_CRP_WDATA           IXP4XX_PCI_CSR(PCI_CRP_WDATA_OFFSET)
+#define PCI_CRP_RDATA           IXP4XX_PCI_CSR(PCI_CRP_RDATA_OFFSET)
+#define PCI_CSR                 IXP4XX_PCI_CSR(PCI_CSR_OFFSET) 
+#define PCI_ISR                 IXP4XX_PCI_CSR(PCI_ISR_OFFSET)
+#define PCI_INTEN               IXP4XX_PCI_CSR(PCI_INTEN_OFFSET)
+#define PCI_DMACTRL             IXP4XX_PCI_CSR(PCI_DMACTRL_OFFSET)
+#define PCI_AHBMEMBASE          IXP4XX_PCI_CSR(PCI_AHBMEMBASE_OFFSET)
+#define PCI_AHBIOBASE           IXP4XX_PCI_CSR(PCI_AHBIOBASE_OFFSET)
+#define PCI_PCIMEMBASE          IXP4XX_PCI_CSR(PCI_PCIMEMBASE_OFFSET)
+#define PCI_AHBDOORBELL         IXP4XX_PCI_CSR(PCI_AHBDOORBELL_OFFSET)
+#define PCI_PCIDOORBELL         IXP4XX_PCI_CSR(PCI_PCIDOORBELL_OFFSET)
+#define PCI_ATPDMA0_AHBADDR     IXP4XX_PCI_CSR(PCI_ATPDMA0_AHBADDR_OFFSET)
+#define PCI_ATPDMA0_PCIADDR     IXP4XX_PCI_CSR(PCI_ATPDMA0_PCIADDR_OFFSET)
+#define PCI_ATPDMA0_LENADDR     IXP4XX_PCI_CSR(PCI_ATPDMA0_LENADDR_OFFSET)
+#define PCI_ATPDMA1_AHBADDR     IXP4XX_PCI_CSR(PCI_ATPDMA1_AHBADDR_OFFSET)
+#define PCI_ATPDMA1_PCIADDR     IXP4XX_PCI_CSR(PCI_ATPDMA1_PCIADDR_OFFSET)
+#define PCI_ATPDMA1_LENADDR     IXP4XX_PCI_CSR(PCI_ATPDMA1_LENADDR_OFFSET)
+
+/*
+ * PCI register values and bit definitions 
+ */
+
+/* CSR bit definitions */
+#define PCI_CSR_HOST    	0x00000001
+#define PCI_CSR_ARBEN   	0x00000002
+#define PCI_CSR_ADS     	0x00000004
+#define PCI_CSR_PDS     	0x00000008
+#define PCI_CSR_ABE     	0x00000010
+#define PCI_CSR_DBT     	0x00000020
+#define PCI_CSR_ASE     	0x00000100
+#define PCI_CSR_IC      	0x00008000
+
+/* ISR (Interrupt status) Register bit definitions */
+#define PCI_ISR_PSE     	0x00000001
+#define PCI_ISR_PFE     	0x00000002
+#define PCI_ISR_PPE     	0x00000004
+#define PCI_ISR_AHBE    	0x00000008
+#define PCI_ISR_APDC    	0x00000010
+#define PCI_ISR_PADC    	0x00000020
+#define PCI_ISR_ADB     	0x00000040
+#define PCI_ISR_PDB     	0x00000080
+
+/* INTEN (Interrupt Enable) Register bit definitions */
+#define PCI_INTEN_PSE   	0x00000001
+#define PCI_INTEN_PFE   	0x00000002
+#define PCI_INTEN_PPE   	0x00000004
+#define PCI_INTEN_AHBE  	0x00000008
+#define PCI_INTEN_APDC  	0x00000010
+#define PCI_INTEN_PADC  	0x00000020
+#define PCI_INTEN_ADB   	0x00000040
+#define PCI_INTEN_PDB   	0x00000080
+
+/*
+ * Shift value for byte enable on NP cmd/byte enable register
+ */
+#define IXP4XX_PCI_NP_CBE_BESL		4
+
+/*
+ * PCI commands supported by NP access unit
+ */
+#define NP_CMD_IOREAD			0x2
+#define NP_CMD_IOWRITE			0x3
+#define NP_CMD_CONFIGREAD		0xa
+#define NP_CMD_CONFIGWRITE		0xb
+#define NP_CMD_MEMREAD			0x6
+#define	NP_CMD_MEMWRITE			0x7
+
+/*
+ * Constants for CRP access into local config space
+ */
+#define CRP_AD_CBE_BESL         20
+#define CRP_AD_CBE_WRITE	0x00010000
+
+#define DCMD_LENGTH	0x01fff		/* length mask (max = 8K - 1) */
+
+/* "fuse" bits of IXP_EXP_CFG2 */
+/* All IXP4xx CPUs */
+#define IXP4XX_FEATURE_RCOMP		(1 << 0)
+#define IXP4XX_FEATURE_USB_DEVICE	(1 << 1)
+#define IXP4XX_FEATURE_HASH		(1 << 2)
+#define IXP4XX_FEATURE_AES		(1 << 3)
+#define IXP4XX_FEATURE_DES		(1 << 4)
+#define IXP4XX_FEATURE_HDLC		(1 << 5)
+#define IXP4XX_FEATURE_AAL		(1 << 6)
+#define IXP4XX_FEATURE_HSS		(1 << 7)
+#define IXP4XX_FEATURE_UTOPIA		(1 << 8)
+#define IXP4XX_FEATURE_NPEB_ETH0	(1 << 9)
+#define IXP4XX_FEATURE_NPEC_ETH		(1 << 10)
+#define IXP4XX_FEATURE_RESET_NPEA	(1 << 11)
+#define IXP4XX_FEATURE_RESET_NPEB	(1 << 12)
+#define IXP4XX_FEATURE_RESET_NPEC	(1 << 13)
+#define IXP4XX_FEATURE_PCI		(1 << 14)
+#define IXP4XX_FEATURE_UTOPIA_PHY_LIMIT	(3 << 16)
+#define IXP4XX_FEATURE_XSCALE_MAX_FREQ	(3 << 22)
+#define IXP42X_FEATURE_MASK		(IXP4XX_FEATURE_RCOMP            | \
+					 IXP4XX_FEATURE_USB_DEVICE       | \
+					 IXP4XX_FEATURE_HASH             | \
+					 IXP4XX_FEATURE_AES              | \
+					 IXP4XX_FEATURE_DES              | \
+					 IXP4XX_FEATURE_HDLC             | \
+					 IXP4XX_FEATURE_AAL              | \
+					 IXP4XX_FEATURE_HSS              | \
+					 IXP4XX_FEATURE_UTOPIA           | \
+					 IXP4XX_FEATURE_NPEB_ETH0        | \
+					 IXP4XX_FEATURE_NPEC_ETH         | \
+					 IXP4XX_FEATURE_RESET_NPEA       | \
+					 IXP4XX_FEATURE_RESET_NPEB       | \
+					 IXP4XX_FEATURE_RESET_NPEC       | \
+					 IXP4XX_FEATURE_PCI              | \
+					 IXP4XX_FEATURE_UTOPIA_PHY_LIMIT | \
+					 IXP4XX_FEATURE_XSCALE_MAX_FREQ)
+
+
+/* IXP43x/46x CPUs */
+#define IXP4XX_FEATURE_ECC_TIMESYNC	(1 << 15)
+#define IXP4XX_FEATURE_USB_HOST		(1 << 18)
+#define IXP4XX_FEATURE_NPEA_ETH		(1 << 19)
+#define IXP43X_FEATURE_MASK		(IXP42X_FEATURE_MASK             | \
+					 IXP4XX_FEATURE_ECC_TIMESYNC     | \
+					 IXP4XX_FEATURE_USB_HOST         | \
+					 IXP4XX_FEATURE_NPEA_ETH)
+
+/* IXP46x CPU (including IXP455) only */
+#define IXP4XX_FEATURE_NPEB_ETH_1_TO_3	(1 << 20)
+#define IXP4XX_FEATURE_RSA		(1 << 21)
+#define IXP46X_FEATURE_MASK		(IXP43X_FEATURE_MASK             | \
+					 IXP4XX_FEATURE_NPEB_ETH_1_TO_3  | \
+					 IXP4XX_FEATURE_RSA)
+
+#endif
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/npe.h b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/npe.h
new file mode 100644
index 0000000..3a98084
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/npe.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __IXP4XX_NPE_H
+#define __IXP4XX_NPE_H
+
+#include <linux/kernel.h>
+
+extern const char *npe_names[];
+
+struct npe_regs {
+	u32 exec_addr, exec_data, exec_status_cmd, exec_count;
+	u32 action_points[4];
+	u32 watchpoint_fifo, watch_count;
+	u32 profile_count;
+	u32 messaging_status, messaging_control;
+	u32 mailbox_status, /*messaging_*/ in_out_fifo;
+};
+
+struct npe {
+	struct resource *mem_res;
+	struct npe_regs __iomem *regs;
+	u32 regs_phys;
+	int id;
+	int valid;
+};
+
+
+static inline const char *npe_name(struct npe *npe)
+{
+	return npe_names[npe->id];
+}
+
+int npe_running(struct npe *npe);
+int npe_send_message(struct npe *npe, const void *msg, const char *what);
+int npe_recv_message(struct npe *npe, void *msg, const char *what);
+int npe_send_recv_message(struct npe *npe, void *msg, const char *what);
+int npe_load_firmware(struct npe *npe, const char *name, struct device *dev);
+struct npe *npe_request(unsigned id);
+void npe_release(struct npe *npe);
+
+#endif /* __IXP4XX_NPE_H */
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/platform.h b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/platform.h
new file mode 100644
index 0000000..342acbe
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/platform.h
@@ -0,0 +1,136 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * arch/arm/mach-ixp4xx/include/mach/platform.h
+ *
+ * Constants and functions that are useful to IXP4xx platform-specific code
+ * and device drivers.
+ *
+ * Copyright (C) 2004 MontaVista Software, Inc.
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H__
+#error "Do not include this directly, instead #include <mach/hardware.h>"
+#endif
+
+#ifndef __ASSEMBLY__
+
+#include <linux/reboot.h>
+
+#include <asm/types.h>
+
+#ifndef	__ARMEB__
+#define	REG_OFFSET	0
+#else
+#define	REG_OFFSET	3
+#endif
+
+/*
+ * Expansion bus memory regions
+ */
+#define IXP4XX_EXP_BUS_BASE_PHYS	(0x50000000)
+
+/*
+ * The expansion bus on the IXP4xx can be configured for either 16 or
+ * 32MB windows and the CS offset for each region changes based on the
+ * current configuration. This means that we cannot simply hardcode
+ * each offset. ixp4xx_sys_init() looks at the expansion bus configuration
+ * as setup by the bootloader to determine our window size.
+ */
+extern unsigned long ixp4xx_exp_bus_size;
+
+#define	IXP4XX_EXP_BUS_BASE(region)\
+		(IXP4XX_EXP_BUS_BASE_PHYS + ((region) * ixp4xx_exp_bus_size))
+
+#define IXP4XX_EXP_BUS_END(region)\
+		(IXP4XX_EXP_BUS_BASE(region) + ixp4xx_exp_bus_size - 1)
+
+/* Those macros can be used to adjust timing and configure
+ * other features for each region.
+ */
+
+#define IXP4XX_EXP_BUS_RECOVERY_T(x)	(((x) & 0x0f) << 16)
+#define IXP4XX_EXP_BUS_HOLD_T(x)	(((x) & 0x03) << 20)
+#define IXP4XX_EXP_BUS_STROBE_T(x)	(((x) & 0x0f) << 22)
+#define IXP4XX_EXP_BUS_SETUP_T(x)	(((x) & 0x03) << 26)
+#define IXP4XX_EXP_BUS_ADDR_T(x)	(((x) & 0x03) << 28)
+#define IXP4XX_EXP_BUS_SIZE(x)		(((x) & 0x0f) << 10)
+#define IXP4XX_EXP_BUS_CYCLES(x)	(((x) & 0x03) << 14)
+
+#define IXP4XX_EXP_BUS_CS_EN		(1L << 31)
+#define IXP4XX_EXP_BUS_BYTE_RD16	(1L << 6)
+#define IXP4XX_EXP_BUS_HRDY_POL		(1L << 5)
+#define IXP4XX_EXP_BUS_MUX_EN		(1L << 4)
+#define IXP4XX_EXP_BUS_SPLT_EN		(1L << 3)
+#define IXP4XX_EXP_BUS_WR_EN		(1L << 1)
+#define IXP4XX_EXP_BUS_BYTE_EN		(1L << 0)
+
+#define IXP4XX_EXP_BUS_CYCLES_INTEL	0x00
+#define IXP4XX_EXP_BUS_CYCLES_MOTOROLA	0x01
+#define IXP4XX_EXP_BUS_CYCLES_HPI	0x02
+
+#define IXP4XX_FLASH_WRITABLE	(0x2)
+#define IXP4XX_FLASH_DEFAULT	(0xbcd23c40)
+#define IXP4XX_FLASH_WRITE	(0xbcd23c42)
+
+/*
+ * Clock Speed Definitions.
+ */
+#define IXP4XX_PERIPHERAL_BUS_CLOCK 	(66) /* 66MHzi APB BUS   */ 
+#define IXP4XX_UART_XTAL        	14745600
+
+/*
+ * This structure provide a means for the board setup code
+ * to give information to th pata_ixp4xx driver. It is
+ * passed as platform_data.
+ */
+struct ixp4xx_pata_data {
+	volatile u32	*cs0_cfg;
+	volatile u32	*cs1_cfg;
+	unsigned long	cs0_bits;
+	unsigned long	cs1_bits;
+	void __iomem	*cs0;
+	void __iomem	*cs1;
+};
+
+#define IXP4XX_ETH_NPEA		0x00
+#define IXP4XX_ETH_NPEB		0x10
+#define IXP4XX_ETH_NPEC		0x20
+
+/* Information about built-in Ethernet MAC interfaces */
+struct eth_plat_info {
+	u8 phy;		/* MII PHY ID, 0 - 31 */
+	u8 rxq;		/* configurable, currently 0 - 31 only */
+	u8 txreadyq;
+	u8 hwaddr[6];
+};
+
+/* Information about built-in HSS (synchronous serial) interfaces */
+struct hss_plat_info {
+	int (*set_clock)(int port, unsigned int clock_type);
+	int (*open)(int port, void *pdev,
+		    void (*set_carrier_cb)(void *pdev, int carrier));
+	void (*close)(int port, void *pdev);
+	u8 txreadyq;
+};
+
+/*
+ * Frequency of clock used for primary clocksource
+ */
+extern unsigned long ixp4xx_timer_freq;
+
+/*
+ * Functions used by platform-level setup code
+ */
+extern void ixp4xx_map_io(void);
+extern void ixp4xx_init_early(void);
+extern void ixp4xx_init_irq(void);
+extern void ixp4xx_sys_init(void);
+extern void ixp4xx_timer_init(void);
+extern void ixp4xx_restart(enum reboot_mode, const char *);
+extern void ixp4xx_pci_preinit(void);
+struct pci_sys_data;
+extern int ixp4xx_setup(int nr, struct pci_sys_data *sys);
+extern struct pci_ops ixp4xx_ops;
+
+#endif // __ASSEMBLY__
+
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/qmgr.h b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/qmgr.h
new file mode 100644
index 0000000..4de8da5
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/qmgr.h
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2007 Krzysztof Halasa <khc@pm.waw.pl>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+#ifndef IXP4XX_QMGR_H
+#define IXP4XX_QMGR_H
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+
+#define DEBUG_QMGR	0
+
+#define HALF_QUEUES	32
+#define QUEUES		64
+#define MAX_QUEUE_LENGTH 4	/* in dwords */
+
+#define QUEUE_STAT1_EMPTY		1 /* queue status bits */
+#define QUEUE_STAT1_NEARLY_EMPTY	2
+#define QUEUE_STAT1_NEARLY_FULL		4
+#define QUEUE_STAT1_FULL		8
+#define QUEUE_STAT2_UNDERFLOW		1
+#define QUEUE_STAT2_OVERFLOW		2
+
+#define QUEUE_WATERMARK_0_ENTRIES	0
+#define QUEUE_WATERMARK_1_ENTRY		1
+#define QUEUE_WATERMARK_2_ENTRIES	2
+#define QUEUE_WATERMARK_4_ENTRIES	3
+#define QUEUE_WATERMARK_8_ENTRIES	4
+#define QUEUE_WATERMARK_16_ENTRIES	5
+#define QUEUE_WATERMARK_32_ENTRIES	6
+#define QUEUE_WATERMARK_64_ENTRIES	7
+
+/* queue interrupt request conditions */
+#define QUEUE_IRQ_SRC_EMPTY		0
+#define QUEUE_IRQ_SRC_NEARLY_EMPTY	1
+#define QUEUE_IRQ_SRC_NEARLY_FULL	2
+#define QUEUE_IRQ_SRC_FULL		3
+#define QUEUE_IRQ_SRC_NOT_EMPTY		4
+#define QUEUE_IRQ_SRC_NOT_NEARLY_EMPTY	5
+#define QUEUE_IRQ_SRC_NOT_NEARLY_FULL	6
+#define QUEUE_IRQ_SRC_NOT_FULL		7
+
+struct qmgr_regs {
+	u32 acc[QUEUES][MAX_QUEUE_LENGTH]; /* 0x000 - 0x3FF */
+	u32 stat1[4];		/* 0x400 - 0x40F */
+	u32 stat2[2];		/* 0x410 - 0x417 */
+	u32 statne_h;		/* 0x418 - queue nearly empty */
+	u32 statf_h;		/* 0x41C - queue full */
+	u32 irqsrc[4];		/* 0x420 - 0x42F IRC source */
+	u32 irqen[2];		/* 0x430 - 0x437 IRQ enabled */
+	u32 irqstat[2];		/* 0x438 - 0x43F - IRQ access only */
+	u32 reserved[1776];
+	u32 sram[2048];		/* 0x2000 - 0x3FFF - config and buffer */
+};
+
+void qmgr_set_irq(unsigned int queue, int src,
+		  void (*handler)(void *pdev), void *pdev);
+void qmgr_enable_irq(unsigned int queue);
+void qmgr_disable_irq(unsigned int queue);
+
+/* request_ and release_queue() must be called from non-IRQ context */
+
+#if DEBUG_QMGR
+extern char qmgr_queue_descs[QUEUES][32];
+
+int qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */,
+		       unsigned int nearly_empty_watermark,
+		       unsigned int nearly_full_watermark,
+		       const char *desc_format, const char* name);
+#else
+int __qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */,
+			 unsigned int nearly_empty_watermark,
+			 unsigned int nearly_full_watermark);
+#define qmgr_request_queue(queue, len, nearly_empty_watermark,		\
+			   nearly_full_watermark, desc_format, name)	\
+	__qmgr_request_queue(queue, len, nearly_empty_watermark,	\
+			     nearly_full_watermark)
+#endif
+
+void qmgr_release_queue(unsigned int queue);
+
+
+static inline void qmgr_put_entry(unsigned int queue, u32 val)
+{
+	struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
+#if DEBUG_QMGR
+	BUG_ON(!qmgr_queue_descs[queue]); /* not yet requested */
+
+	printk(KERN_DEBUG "Queue %s(%i) put %X\n",
+	       qmgr_queue_descs[queue], queue, val);
+#endif
+	__raw_writel(val, &qmgr_regs->acc[queue][0]);
+}
+
+static inline u32 qmgr_get_entry(unsigned int queue)
+{
+	u32 val;
+	const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
+	val = __raw_readl(&qmgr_regs->acc[queue][0]);
+#if DEBUG_QMGR
+	BUG_ON(!qmgr_queue_descs[queue]); /* not yet requested */
+
+	printk(KERN_DEBUG "Queue %s(%i) get %X\n",
+	       qmgr_queue_descs[queue], queue, val);
+#endif
+	return val;
+}
+
+static inline int __qmgr_get_stat1(unsigned int queue)
+{
+	const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
+	return (__raw_readl(&qmgr_regs->stat1[queue >> 3])
+		>> ((queue & 7) << 2)) & 0xF;
+}
+
+static inline int __qmgr_get_stat2(unsigned int queue)
+{
+	const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
+	BUG_ON(queue >= HALF_QUEUES);
+	return (__raw_readl(&qmgr_regs->stat2[queue >> 4])
+		>> ((queue & 0xF) << 1)) & 0x3;
+}
+
+/**
+ * qmgr_stat_empty() - checks if a hardware queue is empty
+ * @queue:	queue number
+ *
+ * Returns non-zero value if the queue is empty.
+ */
+static inline int qmgr_stat_empty(unsigned int queue)
+{
+	BUG_ON(queue >= HALF_QUEUES);
+	return __qmgr_get_stat1(queue) & QUEUE_STAT1_EMPTY;
+}
+
+/**
+ * qmgr_stat_below_low_watermark() - checks if a queue is below low watermark
+ * @queue:	queue number
+ *
+ * Returns non-zero value if the queue is below low watermark.
+ */
+static inline int qmgr_stat_below_low_watermark(unsigned int queue)
+{
+	const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
+	if (queue >= HALF_QUEUES)
+		return (__raw_readl(&qmgr_regs->statne_h) >>
+			(queue - HALF_QUEUES)) & 0x01;
+	return __qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_EMPTY;
+}
+
+/**
+ * qmgr_stat_above_high_watermark() - checks if a queue is above high watermark
+ * @queue:	queue number
+ *
+ * Returns non-zero value if the queue is above high watermark
+ */
+static inline int qmgr_stat_above_high_watermark(unsigned int queue)
+{
+	BUG_ON(queue >= HALF_QUEUES);
+	return __qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_FULL;
+}
+
+/**
+ * qmgr_stat_full() - checks if a hardware queue is full
+ * @queue:	queue number
+ *
+ * Returns non-zero value if the queue is full.
+ */
+static inline int qmgr_stat_full(unsigned int queue)
+{
+	const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
+	if (queue >= HALF_QUEUES)
+		return (__raw_readl(&qmgr_regs->statf_h) >>
+			(queue - HALF_QUEUES)) & 0x01;
+	return __qmgr_get_stat1(queue) & QUEUE_STAT1_FULL;
+}
+
+/**
+ * qmgr_stat_underflow() - checks if a hardware queue experienced underflow
+ * @queue:	queue number
+ *
+ * Returns non-zero value if the queue experienced underflow.
+ */
+static inline int qmgr_stat_underflow(unsigned int queue)
+{
+	return __qmgr_get_stat2(queue) & QUEUE_STAT2_UNDERFLOW;
+}
+
+/**
+ * qmgr_stat_overflow() - checks if a hardware queue experienced overflow
+ * @queue:	queue number
+ *
+ * Returns non-zero value if the queue experienced overflow.
+ */
+static inline int qmgr_stat_overflow(unsigned int queue)
+{
+	return __qmgr_get_stat2(queue) & QUEUE_STAT2_OVERFLOW;
+}
+
+#endif
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/udc.h b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/udc.h
new file mode 100644
index 0000000..7bd8b96
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/udc.h
@@ -0,0 +1,8 @@
+/*
+ * arch/arm/mach-ixp4xx/include/mach/udc.h
+ *
+ */
+#include <linux/platform_data/pxa2xx_udc.h>
+
+extern void ixp4xx_set_udc_info(struct pxa2xx_udc_mach_info *info);
+
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/uncompress.h b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/uncompress.h
new file mode 100644
index 0000000..7b25c02
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/include/mach/uncompress.h
@@ -0,0 +1,56 @@
+/*
+ * arch/arm/mach-ixp4xx/include/mach/uncompress.h 
+ *
+ * Copyright (C) 2002 Intel Corporation.
+ * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ * 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 _ARCH_UNCOMPRESS_H_
+#define _ARCH_UNCOMPRESS_H_
+
+#include "ixp4xx-regs.h"
+#include <asm/mach-types.h>
+#include <linux/serial_reg.h>
+
+#define TX_DONE (UART_LSR_TEMT|UART_LSR_THRE)
+
+volatile u32* uart_base;
+
+static inline void putc(int c)
+{
+	/* Check THRE and TEMT bits before we transmit the character.
+	 */
+	while ((uart_base[UART_LSR] & TX_DONE) != TX_DONE)
+		barrier();
+
+	*uart_base = c;
+}
+
+static void flush(void)
+{
+}
+
+static __inline__ void __arch_decomp_setup(unsigned long arch_id)
+{
+	/*
+	 * Some boards are using UART2 as console
+	 */
+	if (machine_is_adi_coyote() || machine_is_gtwx5715() ||
+	    machine_is_gateway7001() || machine_is_wg302v2() ||
+	    machine_is_devixp() || machine_is_miccpt() || machine_is_mic256())
+		uart_base = (volatile u32*) IXP4XX_UART2_BASE_PHYS;
+	else
+		uart_base = (volatile u32*) IXP4XX_UART1_BASE_PHYS;
+}
+
+/*
+ * arch_id is a variable in decompress_kernel()
+ */
+#define arch_decomp_setup()	__arch_decomp_setup(arch_id)
+
+#endif
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/ixdp425-pci.c b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/ixdp425-pci.c
new file mode 100644
index 0000000..318424d
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/ixdp425-pci.c
@@ -0,0 +1,77 @@
+/*
+ * arch/arm/mach-ixp4xx/ixdp425-pci.c
+ *
+ * IXDP425 board-level PCI initialization
+ *
+ * Copyright (C) 2002 Intel Corporation.
+ * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * 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/pci.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <asm/mach/pci.h>
+#include <asm/irq.h>
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+
+#define MAX_DEV		4
+#define IRQ_LINES	4
+
+/* PCI controller GPIO to IRQ pin mappings */
+#define INTA		11
+#define INTB		10
+#define INTC		9
+#define INTD		8
+
+
+void __init ixdp425_pci_preinit(void)
+{
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW);
+	ixp4xx_pci_preinit();
+}
+
+static int __init ixdp425_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	static int pci_irq_table[IRQ_LINES] = {
+		IXP4XX_GPIO_IRQ(INTA),
+		IXP4XX_GPIO_IRQ(INTB),
+		IXP4XX_GPIO_IRQ(INTC),
+		IXP4XX_GPIO_IRQ(INTD)
+	};
+
+	if (slot >= 1 && slot <= MAX_DEV && pin >= 1 && pin <= IRQ_LINES)
+		return pci_irq_table[(slot + pin - 2) % 4];
+
+	return -1;
+}
+
+struct hw_pci ixdp425_pci __initdata = {
+	.nr_controllers = 1,
+	.ops		= &ixp4xx_ops,
+	.preinit	= ixdp425_pci_preinit,
+	.setup		= ixp4xx_setup,
+	.map_irq	= ixdp425_map_irq,
+};
+
+int __init ixdp425_pci_init(void)
+{
+	if (machine_is_ixdp425() || machine_is_ixcdp1100() ||
+			machine_is_ixdp465() || machine_is_kixrp435())
+		pci_common_init(&ixdp425_pci);
+	return 0;
+}
+
+subsys_initcall(ixdp425_pci_init);
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/ixdp425-setup.c b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/ixdp425-setup.c
new file mode 100644
index 0000000..8f5e015
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/ixdp425-setup.c
@@ -0,0 +1,311 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * arch/arm/mach-ixp4xx/ixdp425-setup.c
+ *
+ * IXDP425/IXCDP1100 board-setup
+ *
+ * Copyright (C) 2003-2005 MontaVista Software, Inc.
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_8250.h>
+#include <linux/i2c-gpio.h>
+#include <linux/io.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/rawnand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+#define IXDP425_SDA_PIN		7
+#define IXDP425_SCL_PIN		6
+
+/* NAND Flash pins */
+#define IXDP425_NAND_NCE_PIN	12
+
+#define IXDP425_NAND_CMD_BYTE	0x01
+#define IXDP425_NAND_ADDR_BYTE	0x02
+
+static struct flash_platform_data ixdp425_flash_data = {
+	.map_name	= "cfi_probe",
+	.width		= 2,
+};
+
+static struct resource ixdp425_flash_resource = {
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device ixdp425_flash = {
+	.name		= "IXP4XX-Flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &ixdp425_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &ixdp425_flash_resource,
+};
+
+#if defined(CONFIG_MTD_NAND_PLATFORM) || \
+    defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
+
+static struct mtd_partition ixdp425_partitions[] = {
+	{
+		.name	= "ixp400 NAND FS 0",
+		.offset	= 0,
+		.size 	= SZ_8M
+	}, {
+		.name	= "ixp400 NAND FS 1",
+		.offset	= MTDPART_OFS_APPEND,
+		.size	= MTDPART_SIZ_FULL
+	},
+};
+
+static void
+ixdp425_flash_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+	struct nand_chip *this = mtd_to_nand(mtd);
+	int offset = (int)nand_get_controller_data(this);
+
+	if (ctrl & NAND_CTRL_CHANGE) {
+		if (ctrl & NAND_NCE) {
+			gpio_set_value(IXDP425_NAND_NCE_PIN, 0);
+			udelay(5);
+		} else
+			gpio_set_value(IXDP425_NAND_NCE_PIN, 1);
+
+		offset = (ctrl & NAND_CLE) ? IXDP425_NAND_CMD_BYTE : 0;
+		offset |= (ctrl & NAND_ALE) ? IXDP425_NAND_ADDR_BYTE : 0;
+		nand_set_controller_data(this, (void *)offset);
+	}
+
+	if (cmd != NAND_CMD_NONE)
+		writeb(cmd, this->IO_ADDR_W + offset);
+}
+
+static struct platform_nand_data ixdp425_flash_nand_data = {
+	.chip = {
+		.nr_chips		= 1,
+		.chip_delay		= 30,
+		.partitions	 	= ixdp425_partitions,
+		.nr_partitions	 	= ARRAY_SIZE(ixdp425_partitions),
+	},
+	.ctrl = {
+		.cmd_ctrl 		= ixdp425_flash_nand_cmd_ctrl
+	}
+};
+
+static struct resource ixdp425_flash_nand_resource = {
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device ixdp425_flash_nand = {
+	.name		= "gen_nand",
+	.id		= -1,
+	.dev		= {
+		.platform_data = &ixdp425_flash_nand_data,
+	},
+	.num_resources	= 1,
+	.resource	= &ixdp425_flash_nand_resource,
+};
+#endif	/* CONFIG_MTD_NAND_PLATFORM */
+
+static struct i2c_gpio_platform_data ixdp425_i2c_gpio_data = {
+	.sda_pin	= IXDP425_SDA_PIN,
+	.scl_pin	= IXDP425_SCL_PIN,
+};
+
+static struct platform_device ixdp425_i2c_gpio = {
+	.name		= "i2c-gpio",
+	.id		= 0,
+	.dev	 = {
+		.platform_data	= &ixdp425_i2c_gpio_data,
+	},
+};
+
+static struct resource ixdp425_uart_resources[] = {
+	{
+		.start		= IXP4XX_UART1_BASE_PHYS,
+		.end		= IXP4XX_UART1_BASE_PHYS + 0x0fff,
+		.flags		= IORESOURCE_MEM
+	},
+	{
+		.start		= IXP4XX_UART2_BASE_PHYS,
+		.end		= IXP4XX_UART2_BASE_PHYS + 0x0fff,
+		.flags		= IORESOURCE_MEM
+	}
+};
+
+static struct plat_serial8250_port ixdp425_uart_data[] = {
+	{
+		.mapbase	= IXP4XX_UART1_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART1,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	},
+	{
+		.mapbase	= IXP4XX_UART2_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART2,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	},
+	{ },
+};
+
+static struct platform_device ixdp425_uart = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev.platform_data	= ixdp425_uart_data,
+	.num_resources		= 2,
+	.resource		= ixdp425_uart_resources
+};
+
+/* Built-in 10/100 Ethernet MAC interfaces */
+static struct eth_plat_info ixdp425_plat_eth[] = {
+	{
+		.phy		= 0,
+		.rxq		= 3,
+		.txreadyq	= 20,
+	}, {
+		.phy		= 1,
+		.rxq		= 4,
+		.txreadyq	= 21,
+	}
+};
+
+static struct platform_device ixdp425_eth[] = {
+	{
+		.name			= "ixp4xx_eth",
+		.id			= IXP4XX_ETH_NPEB,
+		.dev.platform_data	= ixdp425_plat_eth,
+	}, {
+		.name			= "ixp4xx_eth",
+		.id			= IXP4XX_ETH_NPEC,
+		.dev.platform_data	= ixdp425_plat_eth + 1,
+	}
+};
+
+static struct platform_device *ixdp425_devices[] __initdata = {
+	&ixdp425_i2c_gpio,
+	&ixdp425_flash,
+#if defined(CONFIG_MTD_NAND_PLATFORM) || \
+    defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
+	&ixdp425_flash_nand,
+#endif
+	&ixdp425_uart,
+	&ixdp425_eth[0],
+	&ixdp425_eth[1],
+};
+
+static void __init ixdp425_init(void)
+{
+	ixp4xx_sys_init();
+
+	ixdp425_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+	ixdp425_flash_resource.end =
+		IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
+
+#if defined(CONFIG_MTD_NAND_PLATFORM) || \
+    defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
+	ixdp425_flash_nand_resource.start = IXP4XX_EXP_BUS_BASE(3),
+	ixdp425_flash_nand_resource.end   = IXP4XX_EXP_BUS_BASE(3) + 0x10 - 1;
+
+	gpio_request(IXDP425_NAND_NCE_PIN, "NAND NCE pin");
+	gpio_direction_output(IXDP425_NAND_NCE_PIN, 0);
+
+	/* Configure expansion bus for NAND Flash */
+	*IXP4XX_EXP_CS3 = IXP4XX_EXP_BUS_CS_EN |
+			  IXP4XX_EXP_BUS_STROBE_T(1) |	/* extend by 1 clock */
+			  IXP4XX_EXP_BUS_CYCLES(0) |	/* Intel cycles */
+			  IXP4XX_EXP_BUS_SIZE(0) |	/* 512bytes addr space*/
+			  IXP4XX_EXP_BUS_WR_EN |
+			  IXP4XX_EXP_BUS_BYTE_EN;	/* 8 bit data bus */
+#endif
+
+	if (cpu_is_ixp43x()) {
+		ixdp425_uart.num_resources = 1;
+		ixdp425_uart_data[1].flags = 0;
+	}
+
+	platform_add_devices(ixdp425_devices, ARRAY_SIZE(ixdp425_devices));
+}
+
+#ifdef CONFIG_ARCH_IXDP425
+MACHINE_START(IXDP425, "Intel IXDP425 Development Platform")
+	/* Maintainer: MontaVista Software, Inc. */
+	.map_io		= ixp4xx_map_io,
+	.init_early	= ixp4xx_init_early,
+	.init_irq	= ixp4xx_init_irq,
+	.init_time	= ixp4xx_timer_init,
+	.atag_offset	= 0x100,
+	.init_machine	= ixdp425_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
+	.restart	= ixp4xx_restart,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_IXDP465
+MACHINE_START(IXDP465, "Intel IXDP465 Development Platform")
+	/* Maintainer: MontaVista Software, Inc. */
+	.map_io		= ixp4xx_map_io,
+	.init_early	= ixp4xx_init_early,
+	.init_irq	= ixp4xx_init_irq,
+	.init_time	= ixp4xx_timer_init,
+	.atag_offset	= 0x100,
+	.init_machine	= ixdp425_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
+MACHINE_END
+#endif
+
+#ifdef CONFIG_ARCH_PRPMC1100
+MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform")
+	/* Maintainer: MontaVista Software, Inc. */
+	.map_io		= ixp4xx_map_io,
+	.init_early	= ixp4xx_init_early,
+	.init_irq	= ixp4xx_init_irq,
+	.init_time	= ixp4xx_timer_init,
+	.atag_offset	= 0x100,
+	.init_machine	= ixdp425_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_KIXRP435
+MACHINE_START(KIXRP435, "Intel KIXRP435 Reference Platform")
+	/* Maintainer: MontaVista Software, Inc. */
+	.map_io		= ixp4xx_map_io,
+	.init_early	= ixp4xx_init_early,
+	.init_irq	= ixp4xx_init_irq,
+	.init_time	= ixp4xx_timer_init,
+	.atag_offset	= 0x100,
+	.init_machine	= ixdp425_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
+MACHINE_END
+#endif
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/ixdpg425-pci.c b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/ixdpg425-pci.c
new file mode 100644
index 0000000..1f8717b
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/ixdpg425-pci.c
@@ -0,0 +1,58 @@
+/*
+ * arch/arm/mach-ixp4xx/ixdpg425-pci.c
+ *
+ * PCI setup routines for Intel IXDPG425 Platform
+ *
+ * Copyright (C) 2004 MontaVista Softwrae, Inc.
+ *
+ * Maintainer: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * 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/pci.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+
+#include <asm/mach/pci.h>
+
+void __init ixdpg425_pci_preinit(void)
+{
+	irq_set_irq_type(IRQ_IXP4XX_GPIO6, IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IRQ_IXP4XX_GPIO7, IRQ_TYPE_LEVEL_LOW);
+
+	ixp4xx_pci_preinit();
+}
+
+static int __init ixdpg425_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	if (slot == 12 || slot == 13)
+		return IRQ_IXP4XX_GPIO7;
+	else if (slot == 14)
+		return IRQ_IXP4XX_GPIO6;
+	else return -1;
+}
+
+struct hw_pci ixdpg425_pci __initdata = {
+	.nr_controllers = 1,
+	.ops		= &ixp4xx_ops,
+	.preinit =        ixdpg425_pci_preinit,
+	.setup =          ixp4xx_setup,
+	.map_irq =        ixdpg425_map_irq,
+};
+
+int __init ixdpg425_pci_init(void)
+{
+	if (machine_is_ixdpg425())
+		pci_common_init(&ixdpg425_pci);
+	return 0;
+}
+
+subsys_initcall(ixdpg425_pci_init);
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/ixp4xx_npe.c b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/ixp4xx_npe.c
new file mode 100644
index 0000000..d4eb09a
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/ixp4xx_npe.c
@@ -0,0 +1,742 @@
+/*
+ * Intel IXP4xx Network Processor Engine driver for Linux
+ *
+ * Copyright (C) 2007 Krzysztof Halasa <khc@pm.waw.pl>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * The code is based on publicly available information:
+ * - Intel IXP4xx Developer's Manual and other e-papers
+ * - Intel IXP400 Access Library Software (BSD license)
+ * - previous works by Christian Hohnstaedt <chohnstaedt@innominate.com>
+ *   Thanks, Christian.
+ */
+
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/firmware.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <mach/npe.h>
+
+#define DEBUG_MSG			0
+#define DEBUG_FW			0
+
+#define NPE_COUNT			3
+#define MAX_RETRIES			1000	/* microseconds */
+#define NPE_42X_DATA_SIZE		0x800	/* in dwords */
+#define NPE_46X_DATA_SIZE		0x1000
+#define NPE_A_42X_INSTR_SIZE		0x1000
+#define NPE_B_AND_C_42X_INSTR_SIZE	0x800
+#define NPE_46X_INSTR_SIZE		0x1000
+#define REGS_SIZE			0x1000
+
+#define NPE_PHYS_REG			32
+
+#define FW_MAGIC			0xFEEDF00D
+#define FW_BLOCK_TYPE_INSTR		0x0
+#define FW_BLOCK_TYPE_DATA		0x1
+#define FW_BLOCK_TYPE_EOF		0xF
+
+/* NPE exec status (read) and command (write) */
+#define CMD_NPE_STEP			0x01
+#define CMD_NPE_START			0x02
+#define CMD_NPE_STOP			0x03
+#define CMD_NPE_CLR_PIPE		0x04
+#define CMD_CLR_PROFILE_CNT		0x0C
+#define CMD_RD_INS_MEM			0x10 /* instruction memory */
+#define CMD_WR_INS_MEM			0x11
+#define CMD_RD_DATA_MEM			0x12 /* data memory */
+#define CMD_WR_DATA_MEM			0x13
+#define CMD_RD_ECS_REG			0x14 /* exec access register */
+#define CMD_WR_ECS_REG			0x15
+
+#define STAT_RUN			0x80000000
+#define STAT_STOP			0x40000000
+#define STAT_CLEAR			0x20000000
+#define STAT_ECS_K			0x00800000 /* pipeline clean */
+
+#define NPE_STEVT			0x1B
+#define NPE_STARTPC			0x1C
+#define NPE_REGMAP			0x1E
+#define NPE_CINDEX			0x1F
+
+#define INSTR_WR_REG_SHORT		0x0000C000
+#define INSTR_WR_REG_BYTE		0x00004000
+#define INSTR_RD_FIFO			0x0F888220
+#define INSTR_RESET_MBOX		0x0FAC8210
+
+#define ECS_BG_CTXT_REG_0		0x00 /* Background Executing Context */
+#define ECS_BG_CTXT_REG_1		0x01 /*		Stack level */
+#define ECS_BG_CTXT_REG_2		0x02
+#define ECS_PRI_1_CTXT_REG_0		0x04 /* Priority 1 Executing Context */
+#define ECS_PRI_1_CTXT_REG_1		0x05 /*		Stack level */
+#define ECS_PRI_1_CTXT_REG_2		0x06
+#define ECS_PRI_2_CTXT_REG_0		0x08 /* Priority 2 Executing Context */
+#define ECS_PRI_2_CTXT_REG_1		0x09 /*		Stack level */
+#define ECS_PRI_2_CTXT_REG_2		0x0A
+#define ECS_DBG_CTXT_REG_0		0x0C /* Debug Executing Context */
+#define ECS_DBG_CTXT_REG_1		0x0D /*		Stack level */
+#define ECS_DBG_CTXT_REG_2		0x0E
+#define ECS_INSTRUCT_REG		0x11 /* NPE Instruction Register */
+
+#define ECS_REG_0_ACTIVE		0x80000000 /* all levels */
+#define ECS_REG_0_NEXTPC_MASK		0x1FFF0000 /* BG/PRI1/PRI2 levels */
+#define ECS_REG_0_LDUR_BITS		8
+#define ECS_REG_0_LDUR_MASK		0x00000700 /* all levels */
+#define ECS_REG_1_CCTXT_BITS		16
+#define ECS_REG_1_CCTXT_MASK		0x000F0000 /* all levels */
+#define ECS_REG_1_SELCTXT_BITS		0
+#define ECS_REG_1_SELCTXT_MASK		0x0000000F /* all levels */
+#define ECS_DBG_REG_2_IF		0x00100000 /* debug level */
+#define ECS_DBG_REG_2_IE		0x00080000 /* debug level */
+
+/* NPE watchpoint_fifo register bit */
+#define WFIFO_VALID			0x80000000
+
+/* NPE messaging_status register bit definitions */
+#define MSGSTAT_OFNE	0x00010000 /* OutFifoNotEmpty */
+#define MSGSTAT_IFNF	0x00020000 /* InFifoNotFull */
+#define MSGSTAT_OFNF	0x00040000 /* OutFifoNotFull */
+#define MSGSTAT_IFNE	0x00080000 /* InFifoNotEmpty */
+#define MSGSTAT_MBINT	0x00100000 /* Mailbox interrupt */
+#define MSGSTAT_IFINT	0x00200000 /* InFifo interrupt */
+#define MSGSTAT_OFINT	0x00400000 /* OutFifo interrupt */
+#define MSGSTAT_WFINT	0x00800000 /* WatchFifo interrupt */
+
+/* NPE messaging_control register bit definitions */
+#define MSGCTL_OUT_FIFO			0x00010000 /* enable output FIFO */
+#define MSGCTL_IN_FIFO			0x00020000 /* enable input FIFO */
+#define MSGCTL_OUT_FIFO_WRITE		0x01000000 /* enable FIFO + WRITE */
+#define MSGCTL_IN_FIFO_WRITE		0x02000000
+
+/* NPE mailbox_status value for reset */
+#define RESET_MBOX_STAT			0x0000F0F0
+
+#define NPE_A_FIRMWARE "NPE-A"
+#define NPE_B_FIRMWARE "NPE-B"
+#define NPE_C_FIRMWARE "NPE-C"
+
+const char *npe_names[] = { NPE_A_FIRMWARE, NPE_B_FIRMWARE, NPE_C_FIRMWARE };
+
+#define print_npe(pri, npe, fmt, ...)					\
+	printk(pri "%s: " fmt, npe_name(npe), ## __VA_ARGS__)
+
+#if DEBUG_MSG
+#define debug_msg(npe, fmt, ...)					\
+	print_npe(KERN_DEBUG, npe, fmt, ## __VA_ARGS__)
+#else
+#define debug_msg(npe, fmt, ...)
+#endif
+
+static struct {
+	u32 reg, val;
+} ecs_reset[] = {
+	{ ECS_BG_CTXT_REG_0,	0xA0000000 },
+	{ ECS_BG_CTXT_REG_1,	0x01000000 },
+	{ ECS_BG_CTXT_REG_2,	0x00008000 },
+	{ ECS_PRI_1_CTXT_REG_0,	0x20000080 },
+	{ ECS_PRI_1_CTXT_REG_1,	0x01000000 },
+	{ ECS_PRI_1_CTXT_REG_2,	0x00008000 },
+	{ ECS_PRI_2_CTXT_REG_0,	0x20000080 },
+	{ ECS_PRI_2_CTXT_REG_1,	0x01000000 },
+	{ ECS_PRI_2_CTXT_REG_2,	0x00008000 },
+	{ ECS_DBG_CTXT_REG_0,	0x20000000 },
+	{ ECS_DBG_CTXT_REG_1,	0x00000000 },
+	{ ECS_DBG_CTXT_REG_2,	0x001E0000 },
+	{ ECS_INSTRUCT_REG,	0x1003C00F },
+};
+
+static struct npe npe_tab[NPE_COUNT] = {
+	{
+		.id	= 0,
+		.regs	= (struct npe_regs __iomem *)IXP4XX_NPEA_BASE_VIRT,
+		.regs_phys = IXP4XX_NPEA_BASE_PHYS,
+	}, {
+		.id	= 1,
+		.regs	= (struct npe_regs __iomem *)IXP4XX_NPEB_BASE_VIRT,
+		.regs_phys = IXP4XX_NPEB_BASE_PHYS,
+	}, {
+		.id	= 2,
+		.regs	= (struct npe_regs __iomem *)IXP4XX_NPEC_BASE_VIRT,
+		.regs_phys = IXP4XX_NPEC_BASE_PHYS,
+	}
+};
+
+int npe_running(struct npe *npe)
+{
+	return (__raw_readl(&npe->regs->exec_status_cmd) & STAT_RUN) != 0;
+}
+
+static void npe_cmd_write(struct npe *npe, u32 addr, int cmd, u32 data)
+{
+	__raw_writel(data, &npe->regs->exec_data);
+	__raw_writel(addr, &npe->regs->exec_addr);
+	__raw_writel(cmd, &npe->regs->exec_status_cmd);
+}
+
+static u32 npe_cmd_read(struct npe *npe, u32 addr, int cmd)
+{
+	__raw_writel(addr, &npe->regs->exec_addr);
+	__raw_writel(cmd, &npe->regs->exec_status_cmd);
+	/* Iintroduce extra read cycles after issuing read command to NPE
+	   so that we read the register after the NPE has updated it.
+	   This is to overcome race condition between XScale and NPE */
+	__raw_readl(&npe->regs->exec_data);
+	__raw_readl(&npe->regs->exec_data);
+	return __raw_readl(&npe->regs->exec_data);
+}
+
+static void npe_clear_active(struct npe *npe, u32 reg)
+{
+	u32 val = npe_cmd_read(npe, reg, CMD_RD_ECS_REG);
+	npe_cmd_write(npe, reg, CMD_WR_ECS_REG, val & ~ECS_REG_0_ACTIVE);
+}
+
+static void npe_start(struct npe *npe)
+{
+	/* ensure only Background Context Stack Level is active */
+	npe_clear_active(npe, ECS_PRI_1_CTXT_REG_0);
+	npe_clear_active(npe, ECS_PRI_2_CTXT_REG_0);
+	npe_clear_active(npe, ECS_DBG_CTXT_REG_0);
+
+	__raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd);
+	__raw_writel(CMD_NPE_START, &npe->regs->exec_status_cmd);
+}
+
+static void npe_stop(struct npe *npe)
+{
+	__raw_writel(CMD_NPE_STOP, &npe->regs->exec_status_cmd);
+	__raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd); /*FIXME?*/
+}
+
+static int __must_check npe_debug_instr(struct npe *npe, u32 instr, u32 ctx,
+					u32 ldur)
+{
+	u32 wc;
+	int i;
+
+	/* set the Active bit, and the LDUR, in the debug level */
+	npe_cmd_write(npe, ECS_DBG_CTXT_REG_0, CMD_WR_ECS_REG,
+		      ECS_REG_0_ACTIVE | (ldur << ECS_REG_0_LDUR_BITS));
+
+	/* set CCTXT at ECS DEBUG L3 to specify in which context to execute
+	   the instruction, and set SELCTXT at ECS DEBUG Level to specify
+	   which context store to access.
+	   Debug ECS Level Reg 1 has form 0x000n000n, where n = context number
+	*/
+	npe_cmd_write(npe, ECS_DBG_CTXT_REG_1, CMD_WR_ECS_REG,
+		      (ctx << ECS_REG_1_CCTXT_BITS) |
+		      (ctx << ECS_REG_1_SELCTXT_BITS));
+
+	/* clear the pipeline */
+	__raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd);
+
+	/* load NPE instruction into the instruction register */
+	npe_cmd_write(npe, ECS_INSTRUCT_REG, CMD_WR_ECS_REG, instr);
+
+	/* we need this value later to wait for completion of NPE execution
+	   step */
+	wc = __raw_readl(&npe->regs->watch_count);
+
+	/* issue a Step One command via the Execution Control register */
+	__raw_writel(CMD_NPE_STEP, &npe->regs->exec_status_cmd);
+
+	/* Watch Count register increments when NPE completes an instruction */
+	for (i = 0; i < MAX_RETRIES; i++) {
+		if (wc != __raw_readl(&npe->regs->watch_count))
+			return 0;
+		udelay(1);
+	}
+
+	print_npe(KERN_ERR, npe, "reset: npe_debug_instr(): timeout\n");
+	return -ETIMEDOUT;
+}
+
+static int __must_check npe_logical_reg_write8(struct npe *npe, u32 addr,
+					       u8 val, u32 ctx)
+{
+	/* here we build the NPE assembler instruction: mov8 d0, #0 */
+	u32 instr = INSTR_WR_REG_BYTE |	/* OpCode */
+		addr << 9 |		/* base Operand */
+		(val & 0x1F) << 4 |	/* lower 5 bits to immediate data */
+		(val & ~0x1F) << (18 - 5);/* higher 3 bits to CoProc instr. */
+	return npe_debug_instr(npe, instr, ctx, 1); /* execute it */
+}
+
+static int __must_check npe_logical_reg_write16(struct npe *npe, u32 addr,
+						u16 val, u32 ctx)
+{
+	/* here we build the NPE assembler instruction: mov16 d0, #0 */
+	u32 instr = INSTR_WR_REG_SHORT | /* OpCode */
+		addr << 9 |		/* base Operand */
+		(val & 0x1F) << 4 |	/* lower 5 bits to immediate data */
+		(val & ~0x1F) << (18 - 5);/* higher 11 bits to CoProc instr. */
+	return npe_debug_instr(npe, instr, ctx, 1); /* execute it */
+}
+
+static int __must_check npe_logical_reg_write32(struct npe *npe, u32 addr,
+						u32 val, u32 ctx)
+{
+	/* write in 16 bit steps first the high and then the low value */
+	if (npe_logical_reg_write16(npe, addr, val >> 16, ctx))
+		return -ETIMEDOUT;
+	return npe_logical_reg_write16(npe, addr + 2, val & 0xFFFF, ctx);
+}
+
+static int npe_reset(struct npe *npe)
+{
+	u32 val, ctl, exec_count, ctx_reg2;
+	int i;
+
+	ctl = (__raw_readl(&npe->regs->messaging_control) | 0x3F000000) &
+		0x3F3FFFFF;
+
+	/* disable parity interrupt */
+	__raw_writel(ctl & 0x3F00FFFF, &npe->regs->messaging_control);
+
+	/* pre exec - debug instruction */
+	/* turn off the halt bit by clearing Execution Count register. */
+	exec_count = __raw_readl(&npe->regs->exec_count);
+	__raw_writel(0, &npe->regs->exec_count);
+	/* ensure that IF and IE are on (temporarily), so that we don't end up
+	   stepping forever */
+	ctx_reg2 = npe_cmd_read(npe, ECS_DBG_CTXT_REG_2, CMD_RD_ECS_REG);
+	npe_cmd_write(npe, ECS_DBG_CTXT_REG_2, CMD_WR_ECS_REG, ctx_reg2 |
+		      ECS_DBG_REG_2_IF | ECS_DBG_REG_2_IE);
+
+	/* clear the FIFOs */
+	while (__raw_readl(&npe->regs->watchpoint_fifo) & WFIFO_VALID)
+		;
+	while (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_OFNE)
+		/* read from the outFIFO until empty */
+		print_npe(KERN_DEBUG, npe, "npe_reset: read FIFO = 0x%X\n",
+			  __raw_readl(&npe->regs->in_out_fifo));
+
+	while (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNE)
+		/* step execution of the NPE intruction to read inFIFO using
+		   the Debug Executing Context stack */
+		if (npe_debug_instr(npe, INSTR_RD_FIFO, 0, 0))
+			return -ETIMEDOUT;
+
+	/* reset the mailbox reg from the XScale side */
+	__raw_writel(RESET_MBOX_STAT, &npe->regs->mailbox_status);
+	/* from NPE side */
+	if (npe_debug_instr(npe, INSTR_RESET_MBOX, 0, 0))
+		return -ETIMEDOUT;
+
+	/* Reset the physical registers in the NPE register file */
+	for (val = 0; val < NPE_PHYS_REG; val++) {
+		if (npe_logical_reg_write16(npe, NPE_REGMAP, val >> 1, 0))
+			return -ETIMEDOUT;
+		/* address is either 0 or 4 */
+		if (npe_logical_reg_write32(npe, (val & 1) * 4, 0, 0))
+			return -ETIMEDOUT;
+	}
+
+	/* Reset the context store = each context's Context Store registers */
+
+	/* Context 0 has no STARTPC. Instead, this value is used to set NextPC
+	   for Background ECS, to set where NPE starts executing code */
+	val = npe_cmd_read(npe, ECS_BG_CTXT_REG_0, CMD_RD_ECS_REG);
+	val &= ~ECS_REG_0_NEXTPC_MASK;
+	val |= (0 /* NextPC */ << 16) & ECS_REG_0_NEXTPC_MASK;
+	npe_cmd_write(npe, ECS_BG_CTXT_REG_0, CMD_WR_ECS_REG, val);
+
+	for (i = 0; i < 16; i++) {
+		if (i) {	/* Context 0 has no STEVT nor STARTPC */
+			/* STEVT = off, 0x80 */
+			if (npe_logical_reg_write8(npe, NPE_STEVT, 0x80, i))
+				return -ETIMEDOUT;
+			if (npe_logical_reg_write16(npe, NPE_STARTPC, 0, i))
+				return -ETIMEDOUT;
+		}
+		/* REGMAP = d0->p0, d8->p2, d16->p4 */
+		if (npe_logical_reg_write16(npe, NPE_REGMAP, 0x820, i))
+			return -ETIMEDOUT;
+		if (npe_logical_reg_write8(npe, NPE_CINDEX, 0, i))
+			return -ETIMEDOUT;
+	}
+
+	/* post exec */
+	/* clear active bit in debug level */
+	npe_cmd_write(npe, ECS_DBG_CTXT_REG_0, CMD_WR_ECS_REG, 0);
+	/* clear the pipeline */
+	__raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd);
+	/* restore previous values */
+	__raw_writel(exec_count, &npe->regs->exec_count);
+	npe_cmd_write(npe, ECS_DBG_CTXT_REG_2, CMD_WR_ECS_REG, ctx_reg2);
+
+	/* write reset values to Execution Context Stack registers */
+	for (val = 0; val < ARRAY_SIZE(ecs_reset); val++)
+		npe_cmd_write(npe, ecs_reset[val].reg, CMD_WR_ECS_REG,
+			      ecs_reset[val].val);
+
+	/* clear the profile counter */
+	__raw_writel(CMD_CLR_PROFILE_CNT, &npe->regs->exec_status_cmd);
+
+	__raw_writel(0, &npe->regs->exec_count);
+	__raw_writel(0, &npe->regs->action_points[0]);
+	__raw_writel(0, &npe->regs->action_points[1]);
+	__raw_writel(0, &npe->regs->action_points[2]);
+	__raw_writel(0, &npe->regs->action_points[3]);
+	__raw_writel(0, &npe->regs->watch_count);
+
+	val = ixp4xx_read_feature_bits();
+	/* reset the NPE */
+	ixp4xx_write_feature_bits(val &
+				  ~(IXP4XX_FEATURE_RESET_NPEA << npe->id));
+	/* deassert reset */
+	ixp4xx_write_feature_bits(val |
+				  (IXP4XX_FEATURE_RESET_NPEA << npe->id));
+	for (i = 0; i < MAX_RETRIES; i++) {
+		if (ixp4xx_read_feature_bits() &
+		    (IXP4XX_FEATURE_RESET_NPEA << npe->id))
+			break;	/* NPE is back alive */
+		udelay(1);
+	}
+	if (i == MAX_RETRIES)
+		return -ETIMEDOUT;
+
+	npe_stop(npe);
+
+	/* restore NPE configuration bus Control Register - parity settings */
+	__raw_writel(ctl, &npe->regs->messaging_control);
+	return 0;
+}
+
+
+int npe_send_message(struct npe *npe, const void *msg, const char *what)
+{
+	const u32 *send = msg;
+	int cycles = 0;
+
+	debug_msg(npe, "Trying to send message %s [%08X:%08X]\n",
+		  what, send[0], send[1]);
+
+	if (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNE) {
+		debug_msg(npe, "NPE input FIFO not empty\n");
+		return -EIO;
+	}
+
+	__raw_writel(send[0], &npe->regs->in_out_fifo);
+
+	if (!(__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNF)) {
+		debug_msg(npe, "NPE input FIFO full\n");
+		return -EIO;
+	}
+
+	__raw_writel(send[1], &npe->regs->in_out_fifo);
+
+	while ((cycles < MAX_RETRIES) &&
+	       (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNE)) {
+		udelay(1);
+		cycles++;
+	}
+
+	if (cycles == MAX_RETRIES) {
+		debug_msg(npe, "Timeout sending message\n");
+		return -ETIMEDOUT;
+	}
+
+#if DEBUG_MSG > 1
+	debug_msg(npe, "Sending a message took %i cycles\n", cycles);
+#endif
+	return 0;
+}
+
+int npe_recv_message(struct npe *npe, void *msg, const char *what)
+{
+	u32 *recv = msg;
+	int cycles = 0, cnt = 0;
+
+	debug_msg(npe, "Trying to receive message %s\n", what);
+
+	while (cycles < MAX_RETRIES) {
+		if (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_OFNE) {
+			recv[cnt++] = __raw_readl(&npe->regs->in_out_fifo);
+			if (cnt == 2)
+				break;
+		} else {
+			udelay(1);
+			cycles++;
+		}
+	}
+
+	switch(cnt) {
+	case 1:
+		debug_msg(npe, "Received [%08X]\n", recv[0]);
+		break;
+	case 2:
+		debug_msg(npe, "Received [%08X:%08X]\n", recv[0], recv[1]);
+		break;
+	}
+
+	if (cycles == MAX_RETRIES) {
+		debug_msg(npe, "Timeout waiting for message\n");
+		return -ETIMEDOUT;
+	}
+
+#if DEBUG_MSG > 1
+	debug_msg(npe, "Receiving a message took %i cycles\n", cycles);
+#endif
+	return 0;
+}
+
+int npe_send_recv_message(struct npe *npe, void *msg, const char *what)
+{
+	int result;
+	u32 *send = msg, recv[2];
+
+	if ((result = npe_send_message(npe, msg, what)) != 0)
+		return result;
+	if ((result = npe_recv_message(npe, recv, what)) != 0)
+		return result;
+
+	if ((recv[0] != send[0]) || (recv[1] != send[1])) {
+		debug_msg(npe, "Message %s: unexpected message received\n",
+			  what);
+		return -EIO;
+	}
+	return 0;
+}
+
+
+int npe_load_firmware(struct npe *npe, const char *name, struct device *dev)
+{
+	const struct firmware *fw_entry;
+
+	struct dl_block {
+		u32 type;
+		u32 offset;
+	} *blk;
+
+	struct dl_image {
+		u32 magic;
+		u32 id;
+		u32 size;
+		union {
+			u32 data[0];
+			struct dl_block blocks[0];
+		};
+	} *image;
+
+	struct dl_codeblock {
+		u32 npe_addr;
+		u32 size;
+		u32 data[0];
+	} *cb;
+
+	int i, j, err, data_size, instr_size, blocks, table_end;
+	u32 cmd;
+
+	if ((err = request_firmware(&fw_entry, name, dev)) != 0)
+		return err;
+
+	err = -EINVAL;
+	if (fw_entry->size < sizeof(struct dl_image)) {
+		print_npe(KERN_ERR, npe, "incomplete firmware file\n");
+		goto err;
+	}
+	image = (struct dl_image*)fw_entry->data;
+
+#if DEBUG_FW
+	print_npe(KERN_DEBUG, npe, "firmware: %08X %08X %08X (0x%X bytes)\n",
+		  image->magic, image->id, image->size, image->size * 4);
+#endif
+
+	if (image->magic == swab32(FW_MAGIC)) { /* swapped file */
+		image->id = swab32(image->id);
+		image->size = swab32(image->size);
+	} else if (image->magic != FW_MAGIC) {
+		print_npe(KERN_ERR, npe, "bad firmware file magic: 0x%X\n",
+			  image->magic);
+		goto err;
+	}
+	if ((image->size * 4 + sizeof(struct dl_image)) != fw_entry->size) {
+		print_npe(KERN_ERR, npe,
+			  "inconsistent size of firmware file\n");
+		goto err;
+	}
+	if (((image->id >> 24) & 0xF /* NPE ID */) != npe->id) {
+		print_npe(KERN_ERR, npe, "firmware file NPE ID mismatch\n");
+		goto err;
+	}
+	if (image->magic == swab32(FW_MAGIC))
+		for (i = 0; i < image->size; i++)
+			image->data[i] = swab32(image->data[i]);
+
+	if (cpu_is_ixp42x() && ((image->id >> 28) & 0xF /* device ID */)) {
+		print_npe(KERN_INFO, npe, "IXP43x/IXP46x firmware ignored on "
+			  "IXP42x\n");
+		goto err;
+	}
+
+	if (npe_running(npe)) {
+		print_npe(KERN_INFO, npe, "unable to load firmware, NPE is "
+			  "already running\n");
+		err = -EBUSY;
+		goto err;
+	}
+#if 0
+	npe_stop(npe);
+	npe_reset(npe);
+#endif
+
+	print_npe(KERN_INFO, npe, "firmware functionality 0x%X, "
+		  "revision 0x%X:%X\n", (image->id >> 16) & 0xFF,
+		  (image->id >> 8) & 0xFF, image->id & 0xFF);
+
+	if (cpu_is_ixp42x()) {
+		if (!npe->id)
+			instr_size = NPE_A_42X_INSTR_SIZE;
+		else
+			instr_size = NPE_B_AND_C_42X_INSTR_SIZE;
+		data_size = NPE_42X_DATA_SIZE;
+	} else {
+		instr_size = NPE_46X_INSTR_SIZE;
+		data_size = NPE_46X_DATA_SIZE;
+	}
+
+	for (blocks = 0; blocks * sizeof(struct dl_block) / 4 < image->size;
+	     blocks++)
+		if (image->blocks[blocks].type == FW_BLOCK_TYPE_EOF)
+			break;
+	if (blocks * sizeof(struct dl_block) / 4 >= image->size) {
+		print_npe(KERN_INFO, npe, "firmware EOF block marker not "
+			  "found\n");
+		goto err;
+	}
+
+#if DEBUG_FW
+	print_npe(KERN_DEBUG, npe, "%i firmware blocks found\n", blocks);
+#endif
+
+	table_end = blocks * sizeof(struct dl_block) / 4 + 1 /* EOF marker */;
+	for (i = 0, blk = image->blocks; i < blocks; i++, blk++) {
+		if (blk->offset > image->size - sizeof(struct dl_codeblock) / 4
+		    || blk->offset < table_end) {
+			print_npe(KERN_INFO, npe, "invalid offset 0x%X of "
+				  "firmware block #%i\n", blk->offset, i);
+			goto err;
+		}
+
+		cb = (struct dl_codeblock*)&image->data[blk->offset];
+		if (blk->type == FW_BLOCK_TYPE_INSTR) {
+			if (cb->npe_addr + cb->size > instr_size)
+				goto too_big;
+			cmd = CMD_WR_INS_MEM;
+		} else if (blk->type == FW_BLOCK_TYPE_DATA) {
+			if (cb->npe_addr + cb->size > data_size)
+				goto too_big;
+			cmd = CMD_WR_DATA_MEM;
+		} else {
+			print_npe(KERN_INFO, npe, "invalid firmware block #%i "
+				  "type 0x%X\n", i, blk->type);
+			goto err;
+		}
+		if (blk->offset + sizeof(*cb) / 4 + cb->size > image->size) {
+			print_npe(KERN_INFO, npe, "firmware block #%i doesn't "
+				  "fit in firmware image: type %c, start 0x%X,"
+				  " length 0x%X\n", i,
+				  blk->type == FW_BLOCK_TYPE_INSTR ? 'I' : 'D',
+				  cb->npe_addr, cb->size);
+			goto err;
+		}
+
+		for (j = 0; j < cb->size; j++)
+			npe_cmd_write(npe, cb->npe_addr + j, cmd, cb->data[j]);
+	}
+
+	npe_start(npe);
+	if (!npe_running(npe))
+		print_npe(KERN_ERR, npe, "unable to start\n");
+	release_firmware(fw_entry);
+	return 0;
+
+too_big:
+	print_npe(KERN_INFO, npe, "firmware block #%i doesn't fit in NPE "
+		  "memory: type %c, start 0x%X, length 0x%X\n", i,
+		  blk->type == FW_BLOCK_TYPE_INSTR ? 'I' : 'D',
+		  cb->npe_addr, cb->size);
+err:
+	release_firmware(fw_entry);
+	return err;
+}
+
+
+struct npe *npe_request(unsigned id)
+{
+	if (id < NPE_COUNT)
+		if (npe_tab[id].valid)
+			if (try_module_get(THIS_MODULE))
+				return &npe_tab[id];
+	return NULL;
+}
+
+void npe_release(struct npe *npe)
+{
+	module_put(THIS_MODULE);
+}
+
+
+static int __init npe_init_module(void)
+{
+
+	int i, found = 0;
+
+	for (i = 0; i < NPE_COUNT; i++) {
+		struct npe *npe = &npe_tab[i];
+		if (!(ixp4xx_read_feature_bits() &
+		      (IXP4XX_FEATURE_RESET_NPEA << i)))
+			continue; /* NPE already disabled or not present */
+		if (!(npe->mem_res = request_mem_region(npe->regs_phys,
+							REGS_SIZE,
+							npe_name(npe)))) {
+			print_npe(KERN_ERR, npe,
+				  "failed to request memory region\n");
+			continue;
+		}
+
+		if (npe_reset(npe))
+			continue;
+		npe->valid = 1;
+		found++;
+	}
+
+	if (!found)
+		return -ENODEV;
+	return 0;
+}
+
+static void __exit npe_cleanup_module(void)
+{
+	int i;
+
+	for (i = 0; i < NPE_COUNT; i++)
+		if (npe_tab[i].mem_res) {
+			npe_reset(&npe_tab[i]);
+			release_resource(npe_tab[i].mem_res);
+		}
+}
+
+module_init(npe_init_module);
+module_exit(npe_cleanup_module);
+
+MODULE_AUTHOR("Krzysztof Halasa");
+MODULE_LICENSE("GPL v2");
+MODULE_FIRMWARE(NPE_A_FIRMWARE);
+MODULE_FIRMWARE(NPE_B_FIRMWARE);
+MODULE_FIRMWARE(NPE_C_FIRMWARE);
+
+EXPORT_SYMBOL(npe_names);
+EXPORT_SYMBOL(npe_running);
+EXPORT_SYMBOL(npe_request);
+EXPORT_SYMBOL(npe_release);
+EXPORT_SYMBOL(npe_load_firmware);
+EXPORT_SYMBOL(npe_send_message);
+EXPORT_SYMBOL(npe_recv_message);
+EXPORT_SYMBOL(npe_send_recv_message);
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
new file mode 100644
index 0000000..9d1b6b7
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
@@ -0,0 +1,372 @@
+/*
+ * Intel IXP4xx Queue Manager driver for Linux
+ *
+ * Copyright (C) 2007 Krzysztof Halasa <khc@pm.waw.pl>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <mach/qmgr.h>
+
+static struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
+static struct resource *mem_res;
+static spinlock_t qmgr_lock;
+static u32 used_sram_bitmap[4]; /* 128 16-dword pages */
+static void (*irq_handlers[QUEUES])(void *pdev);
+static void *irq_pdevs[QUEUES];
+
+#if DEBUG_QMGR
+char qmgr_queue_descs[QUEUES][32];
+#endif
+
+void qmgr_set_irq(unsigned int queue, int src,
+		  void (*handler)(void *pdev), void *pdev)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&qmgr_lock, flags);
+	if (queue < HALF_QUEUES) {
+		u32 __iomem *reg;
+		int bit;
+		BUG_ON(src > QUEUE_IRQ_SRC_NOT_FULL);
+		reg = &qmgr_regs->irqsrc[queue >> 3]; /* 8 queues per u32 */
+		bit = (queue % 8) * 4; /* 3 bits + 1 reserved bit per queue */
+		__raw_writel((__raw_readl(reg) & ~(7 << bit)) | (src << bit),
+			     reg);
+	} else
+		/* IRQ source for queues 32-63 is fixed */
+		BUG_ON(src != QUEUE_IRQ_SRC_NOT_NEARLY_EMPTY);
+
+	irq_handlers[queue] = handler;
+	irq_pdevs[queue] = pdev;
+	spin_unlock_irqrestore(&qmgr_lock, flags);
+}
+
+
+static irqreturn_t qmgr_irq1_a0(int irq, void *pdev)
+{
+	int i, ret = 0;
+	u32 en_bitmap, src, stat;
+
+	/* ACK - it may clear any bits so don't rely on it */
+	__raw_writel(0xFFFFFFFF, &qmgr_regs->irqstat[0]);
+
+	en_bitmap = qmgr_regs->irqen[0];
+	while (en_bitmap) {
+		i = __fls(en_bitmap); /* number of the last "low" queue */
+		en_bitmap &= ~BIT(i);
+		src = qmgr_regs->irqsrc[i >> 3];
+		stat = qmgr_regs->stat1[i >> 3];
+		if (src & 4) /* the IRQ condition is inverted */
+			stat = ~stat;
+		if (stat & BIT(src & 3)) {
+			irq_handlers[i](irq_pdevs[i]);
+			ret = IRQ_HANDLED;
+		}
+	}
+	return ret;
+}
+
+
+static irqreturn_t qmgr_irq2_a0(int irq, void *pdev)
+{
+	int i, ret = 0;
+	u32 req_bitmap;
+
+	/* ACK - it may clear any bits so don't rely on it */
+	__raw_writel(0xFFFFFFFF, &qmgr_regs->irqstat[1]);
+
+	req_bitmap = qmgr_regs->irqen[1] & qmgr_regs->statne_h;
+	while (req_bitmap) {
+		i = __fls(req_bitmap); /* number of the last "high" queue */
+		req_bitmap &= ~BIT(i);
+		irq_handlers[HALF_QUEUES + i](irq_pdevs[HALF_QUEUES + i]);
+		ret = IRQ_HANDLED;
+	}
+	return ret;
+}
+
+
+static irqreturn_t qmgr_irq(int irq, void *pdev)
+{
+	int i, half = (irq == IRQ_IXP4XX_QM1 ? 0 : 1);
+	u32 req_bitmap = __raw_readl(&qmgr_regs->irqstat[half]);
+
+	if (!req_bitmap)
+		return 0;
+	__raw_writel(req_bitmap, &qmgr_regs->irqstat[half]); /* ACK */
+
+	while (req_bitmap) {
+		i = __fls(req_bitmap); /* number of the last queue */
+		req_bitmap &= ~BIT(i);
+		i += half * HALF_QUEUES;
+		irq_handlers[i](irq_pdevs[i]);
+	}
+	return IRQ_HANDLED;
+}
+
+
+void qmgr_enable_irq(unsigned int queue)
+{
+	unsigned long flags;
+	int half = queue / 32;
+	u32 mask = 1 << (queue & (HALF_QUEUES - 1));
+
+	spin_lock_irqsave(&qmgr_lock, flags);
+	__raw_writel(__raw_readl(&qmgr_regs->irqen[half]) | mask,
+		     &qmgr_regs->irqen[half]);
+	spin_unlock_irqrestore(&qmgr_lock, flags);
+}
+
+void qmgr_disable_irq(unsigned int queue)
+{
+	unsigned long flags;
+	int half = queue / 32;
+	u32 mask = 1 << (queue & (HALF_QUEUES - 1));
+
+	spin_lock_irqsave(&qmgr_lock, flags);
+	__raw_writel(__raw_readl(&qmgr_regs->irqen[half]) & ~mask,
+		     &qmgr_regs->irqen[half]);
+	__raw_writel(mask, &qmgr_regs->irqstat[half]); /* clear */
+	spin_unlock_irqrestore(&qmgr_lock, flags);
+}
+
+static inline void shift_mask(u32 *mask)
+{
+	mask[3] = mask[3] << 1 | mask[2] >> 31;
+	mask[2] = mask[2] << 1 | mask[1] >> 31;
+	mask[1] = mask[1] << 1 | mask[0] >> 31;
+	mask[0] <<= 1;
+}
+
+#if DEBUG_QMGR
+int qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */,
+		       unsigned int nearly_empty_watermark,
+		       unsigned int nearly_full_watermark,
+		       const char *desc_format, const char* name)
+#else
+int __qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */,
+			 unsigned int nearly_empty_watermark,
+			 unsigned int nearly_full_watermark)
+#endif
+{
+	u32 cfg, addr = 0, mask[4]; /* in 16-dwords */
+	int err;
+
+	BUG_ON(queue >= QUEUES);
+
+	if ((nearly_empty_watermark | nearly_full_watermark) & ~7)
+		return -EINVAL;
+
+	switch (len) {
+	case  16:
+		cfg = 0 << 24;
+		mask[0] = 0x1;
+		break;
+	case  32:
+		cfg = 1 << 24;
+		mask[0] = 0x3;
+		break;
+	case  64:
+		cfg = 2 << 24;
+		mask[0] = 0xF;
+		break;
+	case 128:
+		cfg = 3 << 24;
+		mask[0] = 0xFF;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	cfg |= nearly_empty_watermark << 26;
+	cfg |= nearly_full_watermark << 29;
+	len /= 16;		/* in 16-dwords: 1, 2, 4 or 8 */
+	mask[1] = mask[2] = mask[3] = 0;
+
+	if (!try_module_get(THIS_MODULE))
+		return -ENODEV;
+
+	spin_lock_irq(&qmgr_lock);
+	if (__raw_readl(&qmgr_regs->sram[queue])) {
+		err = -EBUSY;
+		goto err;
+	}
+
+	while (1) {
+		if (!(used_sram_bitmap[0] & mask[0]) &&
+		    !(used_sram_bitmap[1] & mask[1]) &&
+		    !(used_sram_bitmap[2] & mask[2]) &&
+		    !(used_sram_bitmap[3] & mask[3]))
+			break; /* found free space */
+
+		addr++;
+		shift_mask(mask);
+		if (addr + len > ARRAY_SIZE(qmgr_regs->sram)) {
+			printk(KERN_ERR "qmgr: no free SRAM space for"
+			       " queue %i\n", queue);
+			err = -ENOMEM;
+			goto err;
+		}
+	}
+
+	used_sram_bitmap[0] |= mask[0];
+	used_sram_bitmap[1] |= mask[1];
+	used_sram_bitmap[2] |= mask[2];
+	used_sram_bitmap[3] |= mask[3];
+	__raw_writel(cfg | (addr << 14), &qmgr_regs->sram[queue]);
+#if DEBUG_QMGR
+	snprintf(qmgr_queue_descs[queue], sizeof(qmgr_queue_descs[0]),
+		 desc_format, name);
+	printk(KERN_DEBUG "qmgr: requested queue %s(%i) addr = 0x%02X\n",
+	       qmgr_queue_descs[queue], queue, addr);
+#endif
+	spin_unlock_irq(&qmgr_lock);
+	return 0;
+
+err:
+	spin_unlock_irq(&qmgr_lock);
+	module_put(THIS_MODULE);
+	return err;
+}
+
+void qmgr_release_queue(unsigned int queue)
+{
+	u32 cfg, addr, mask[4];
+
+	BUG_ON(queue >= QUEUES); /* not in valid range */
+
+	spin_lock_irq(&qmgr_lock);
+	cfg = __raw_readl(&qmgr_regs->sram[queue]);
+	addr = (cfg >> 14) & 0xFF;
+
+	BUG_ON(!addr);		/* not requested */
+
+	switch ((cfg >> 24) & 3) {
+	case 0: mask[0] = 0x1; break;
+	case 1: mask[0] = 0x3; break;
+	case 2: mask[0] = 0xF; break;
+	case 3: mask[0] = 0xFF; break;
+	}
+
+	mask[1] = mask[2] = mask[3] = 0;
+
+	while (addr--)
+		shift_mask(mask);
+
+#if DEBUG_QMGR
+	printk(KERN_DEBUG "qmgr: releasing queue %s(%i)\n",
+	       qmgr_queue_descs[queue], queue);
+	qmgr_queue_descs[queue][0] = '\x0';
+#endif
+
+	while ((addr = qmgr_get_entry(queue)))
+		printk(KERN_ERR "qmgr: released queue %i not empty: 0x%08X\n",
+		       queue, addr);
+
+	__raw_writel(0, &qmgr_regs->sram[queue]);
+
+	used_sram_bitmap[0] &= ~mask[0];
+	used_sram_bitmap[1] &= ~mask[1];
+	used_sram_bitmap[2] &= ~mask[2];
+	used_sram_bitmap[3] &= ~mask[3];
+	irq_handlers[queue] = NULL; /* catch IRQ bugs */
+	spin_unlock_irq(&qmgr_lock);
+
+	module_put(THIS_MODULE);
+}
+
+static int qmgr_init(void)
+{
+	int i, err;
+	irq_handler_t handler1, handler2;
+
+	mem_res = request_mem_region(IXP4XX_QMGR_BASE_PHYS,
+				     IXP4XX_QMGR_REGION_SIZE,
+				     "IXP4xx Queue Manager");
+	if (mem_res == NULL)
+		return -EBUSY;
+
+	/* reset qmgr registers */
+	for (i = 0; i < 4; i++) {
+		__raw_writel(0x33333333, &qmgr_regs->stat1[i]);
+		__raw_writel(0, &qmgr_regs->irqsrc[i]);
+	}
+	for (i = 0; i < 2; i++) {
+		__raw_writel(0, &qmgr_regs->stat2[i]);
+		__raw_writel(0xFFFFFFFF, &qmgr_regs->irqstat[i]); /* clear */
+		__raw_writel(0, &qmgr_regs->irqen[i]);
+	}
+
+	__raw_writel(0xFFFFFFFF, &qmgr_regs->statne_h);
+	__raw_writel(0, &qmgr_regs->statf_h);
+
+	for (i = 0; i < QUEUES; i++)
+		__raw_writel(0, &qmgr_regs->sram[i]);
+
+	if (cpu_is_ixp42x_rev_a0()) {
+		handler1 = qmgr_irq1_a0;
+		handler2 = qmgr_irq2_a0;
+	} else
+		handler1 = handler2 = qmgr_irq;
+
+	err = request_irq(IRQ_IXP4XX_QM1, handler1, 0, "IXP4xx Queue Manager",
+			  NULL);
+	if (err) {
+		printk(KERN_ERR "qmgr: failed to request IRQ%i (%i)\n",
+		       IRQ_IXP4XX_QM1, err);
+		goto error_irq;
+	}
+
+	err = request_irq(IRQ_IXP4XX_QM2, handler2, 0, "IXP4xx Queue Manager",
+			  NULL);
+	if (err) {
+		printk(KERN_ERR "qmgr: failed to request IRQ%i (%i)\n",
+		       IRQ_IXP4XX_QM2, err);
+		goto error_irq2;
+	}
+
+	used_sram_bitmap[0] = 0xF; /* 4 first pages reserved for config */
+	spin_lock_init(&qmgr_lock);
+
+	printk(KERN_INFO "IXP4xx Queue Manager initialized.\n");
+	return 0;
+
+error_irq2:
+	free_irq(IRQ_IXP4XX_QM1, NULL);
+error_irq:
+	release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
+	return err;
+}
+
+static void qmgr_remove(void)
+{
+	free_irq(IRQ_IXP4XX_QM1, NULL);
+	free_irq(IRQ_IXP4XX_QM2, NULL);
+	synchronize_irq(IRQ_IXP4XX_QM1);
+	synchronize_irq(IRQ_IXP4XX_QM2);
+	release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
+}
+
+module_init(qmgr_init);
+module_exit(qmgr_remove);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Krzysztof Halasa");
+
+EXPORT_SYMBOL(qmgr_set_irq);
+EXPORT_SYMBOL(qmgr_enable_irq);
+EXPORT_SYMBOL(qmgr_disable_irq);
+#if DEBUG_QMGR
+EXPORT_SYMBOL(qmgr_queue_descs);
+EXPORT_SYMBOL(qmgr_request_queue);
+#else
+EXPORT_SYMBOL(__qmgr_request_queue);
+#endif
+EXPORT_SYMBOL(qmgr_release_queue);
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/miccpt-pci.c b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/miccpt-pci.c
new file mode 100644
index 0000000..d114ccd
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/miccpt-pci.c
@@ -0,0 +1,77 @@
+/*
+ * arch/arm/mach-ixp4xx/miccpt-pci.c
+ *
+ * MICCPT board-level PCI initialization
+ *
+ * Copyright (C) 2002 Intel Corporation.
+ * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ * Copyright (C) 2006 OMICRON electronics GmbH
+ *
+ * Author: Michael Jochum <michael.jochum@omicron.at>
+ *
+ * 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/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <asm/mach/pci.h>
+#include <asm/irq.h>
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+
+#define MAX_DEV		4
+#define IRQ_LINES	4
+
+/* PCI controller GPIO to IRQ pin mappings */
+#define INTA		1
+#define INTB		2
+#define INTC		3
+#define INTD		4
+
+
+void __init miccpt_pci_preinit(void)
+{
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW);
+	ixp4xx_pci_preinit();
+}
+
+static int __init miccpt_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	static int pci_irq_table[IRQ_LINES] = {
+		IXP4XX_GPIO_IRQ(INTA),
+		IXP4XX_GPIO_IRQ(INTB),
+		IXP4XX_GPIO_IRQ(INTC),
+		IXP4XX_GPIO_IRQ(INTD)
+	};
+
+	if (slot >= 1 && slot <= MAX_DEV && pin >= 1 && pin <= IRQ_LINES)
+		return pci_irq_table[(slot + pin - 2) % 4];
+
+	return -1;
+}
+
+struct hw_pci miccpt_pci __initdata = {
+	.nr_controllers = 1,
+	.ops		= &ixp4xx_ops,
+	.preinit	= miccpt_pci_preinit,
+	.setup		= ixp4xx_setup,
+	.map_irq	= miccpt_map_irq,
+};
+
+int __init miccpt_pci_init(void)
+{
+	if (machine_is_miccpt())
+		pci_common_init(&miccpt_pci);
+	return 0;
+}
+
+subsys_initcall(miccpt_pci_init);
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/nas100d-pci.c b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/nas100d-pci.c
new file mode 100644
index 0000000..8f0eba0
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/nas100d-pci.c
@@ -0,0 +1,75 @@
+/*
+ * arch/arm/mach-ixp4xx/nas100d-pci.c
+ *
+ * NAS 100d board-level PCI initialization
+ *
+ * based on ixdp425-pci.c:
+ *	Copyright (C) 2002 Intel Corporation.
+ *	Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ * Maintainer: http://www.nslu2-linux.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/init.h>
+#include <linux/irq.h>
+#include <asm/mach/pci.h>
+#include <asm/mach-types.h>
+
+#define MAX_DEV		3
+#define IRQ_LINES	3
+
+/* PCI controller GPIO to IRQ pin mappings */
+#define INTA		11
+#define INTB		10
+#define INTC		9
+#define INTD		8
+#define INTE		7
+
+void __init nas100d_pci_preinit(void)
+{
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTE), IRQ_TYPE_LEVEL_LOW);
+	ixp4xx_pci_preinit();
+}
+
+static int __init nas100d_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	static int pci_irq_table[MAX_DEV][IRQ_LINES] = {
+		{ IXP4XX_GPIO_IRQ(INTA), -1, -1 },
+		{ IXP4XX_GPIO_IRQ(INTB), -1, -1 },
+		{ IXP4XX_GPIO_IRQ(INTC), IXP4XX_GPIO_IRQ(INTD),
+		  IXP4XX_GPIO_IRQ(INTE) },
+	};
+
+	if (slot >= 1 && slot <= MAX_DEV && pin >= 1 && pin <= IRQ_LINES)
+		return pci_irq_table[slot - 1][pin - 1];
+
+	return -1;
+}
+
+struct hw_pci __initdata nas100d_pci = {
+	.nr_controllers = 1,
+	.ops		= &ixp4xx_ops,
+	.preinit	= nas100d_pci_preinit,
+	.setup		= ixp4xx_setup,
+	.map_irq	= nas100d_map_irq,
+};
+
+int __init nas100d_pci_init(void)
+{
+	if (machine_is_nas100d())
+		pci_common_init(&nas100d_pci);
+
+	return 0;
+}
+
+subsys_initcall(nas100d_pci_init);
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/nas100d-setup.c b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/nas100d-setup.c
new file mode 100644
index 0000000..1b8170d
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/nas100d-setup.c
@@ -0,0 +1,337 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * arch/arm/mach-ixp4xx/nas100d-setup.c
+ *
+ * NAS 100d board-setup
+ *
+ * Copyright (C) 2008 Rod Whitby <rod@whitby.id.au>
+ *
+ * based on ixdp425-setup.c:
+ *      Copyright (C) 2003-2004 MontaVista Software, Inc.
+ * based on nas100d-power.c:
+ *	Copyright (C) 2005 Tower Technologies
+ * based on nas100d-io.c
+ *	Copyright (C) 2004 Karen Spearel
+ *
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ * Author: Rod Whitby <rod@whitby.id.au>
+ * Maintainers: http://www.nslu2-linux.org/
+ *
+ */
+#include <linux/gpio.h>
+#include <linux/if_ether.h>
+#include <linux/irq.h>
+#include <linux/jiffies.h>
+#include <linux/timer.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/leds.h>
+#include <linux/reboot.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
+#include <linux/io.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+#define NAS100D_SDA_PIN		5
+#define NAS100D_SCL_PIN		6
+
+/* Buttons */
+#define NAS100D_PB_GPIO         14   /* power button */
+#define NAS100D_RB_GPIO         4    /* reset button */
+
+/* Power control */
+#define NAS100D_PO_GPIO         12   /* power off */
+
+/* LEDs */
+#define NAS100D_LED_WLAN_GPIO	0
+#define NAS100D_LED_DISK_GPIO	3
+#define NAS100D_LED_PWR_GPIO	15
+
+static struct flash_platform_data nas100d_flash_data = {
+	.map_name		= "cfi_probe",
+	.width			= 2,
+};
+
+static struct resource nas100d_flash_resource = {
+	.flags			= IORESOURCE_MEM,
+};
+
+static struct platform_device nas100d_flash = {
+	.name			= "IXP4XX-Flash",
+	.id			= 0,
+	.dev.platform_data	= &nas100d_flash_data,
+	.num_resources		= 1,
+	.resource		= &nas100d_flash_resource,
+};
+
+static struct i2c_board_info __initdata nas100d_i2c_board_info [] = {
+	{
+		I2C_BOARD_INFO("pcf8563", 0x51),
+	},
+};
+
+static struct gpio_led nas100d_led_pins[] = {
+	{
+		.name		= "nas100d:green:wlan",
+		.gpio		= NAS100D_LED_WLAN_GPIO,
+		.active_low	= true,
+	},
+	{
+		.name		= "nas100d:blue:power",  /* (off=flashing) */
+		.gpio		= NAS100D_LED_PWR_GPIO,
+		.active_low	= true,
+	},
+	{
+		.name		= "nas100d:yellow:disk",
+		.gpio		= NAS100D_LED_DISK_GPIO,
+		.active_low	= true,
+	},
+};
+
+static struct gpio_led_platform_data nas100d_led_data = {
+	.num_leds		= ARRAY_SIZE(nas100d_led_pins),
+	.leds			= nas100d_led_pins,
+};
+
+static struct platform_device nas100d_leds = {
+	.name			= "leds-gpio",
+	.id			= -1,
+	.dev.platform_data	= &nas100d_led_data,
+};
+
+static struct i2c_gpio_platform_data nas100d_i2c_gpio_data = {
+	.sda_pin		= NAS100D_SDA_PIN,
+	.scl_pin		= NAS100D_SCL_PIN,
+};
+
+static struct platform_device nas100d_i2c_gpio = {
+	.name			= "i2c-gpio",
+	.id			= 0,
+	.dev	 = {
+		.platform_data	= &nas100d_i2c_gpio_data,
+	},
+};
+
+static struct resource nas100d_uart_resources[] = {
+	{
+		.start		= IXP4XX_UART1_BASE_PHYS,
+		.end		= IXP4XX_UART1_BASE_PHYS + 0x0fff,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= IXP4XX_UART2_BASE_PHYS,
+		.end		= IXP4XX_UART2_BASE_PHYS + 0x0fff,
+		.flags		= IORESOURCE_MEM,
+	}
+};
+
+static struct plat_serial8250_port nas100d_uart_data[] = {
+	{
+		.mapbase	= IXP4XX_UART1_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART1,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	},
+	{
+		.mapbase	= IXP4XX_UART2_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART2,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	},
+	{ }
+};
+
+static struct platform_device nas100d_uart = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev.platform_data	= nas100d_uart_data,
+	.num_resources		= 2,
+	.resource		= nas100d_uart_resources,
+};
+
+/* Built-in 10/100 Ethernet MAC interfaces */
+static struct eth_plat_info nas100d_plat_eth[] = {
+	{
+		.phy		= 0,
+		.rxq		= 3,
+		.txreadyq	= 20,
+	}
+};
+
+static struct platform_device nas100d_eth[] = {
+	{
+		.name			= "ixp4xx_eth",
+		.id			= IXP4XX_ETH_NPEB,
+		.dev.platform_data	= nas100d_plat_eth,
+	}
+};
+
+static struct platform_device *nas100d_devices[] __initdata = {
+	&nas100d_i2c_gpio,
+	&nas100d_flash,
+	&nas100d_leds,
+	&nas100d_eth[0],
+};
+
+static void nas100d_power_off(void)
+{
+	/* This causes the box to drop the power and go dead. */
+
+	/* enable the pwr cntl gpio and assert power off */
+	gpio_direction_output(NAS100D_PO_GPIO, 1);
+}
+
+/* This is used to make sure the power-button pusher is serious.  The button
+ * must be held until the value of this counter reaches zero.
+ */
+static int power_button_countdown;
+
+/* Must hold the button down for at least this many counts to be processed */
+#define PBUTTON_HOLDDOWN_COUNT 4 /* 2 secs */
+
+static void nas100d_power_handler(unsigned long data);
+static DEFINE_TIMER(nas100d_power_timer, nas100d_power_handler, 0, 0);
+
+static void nas100d_power_handler(unsigned long data)
+{
+	/* This routine is called twice per second to check the
+	 * state of the power button.
+	 */
+
+	if (gpio_get_value(NAS100D_PB_GPIO)) {
+
+		/* IO Pin is 1 (button pushed) */
+		if (power_button_countdown > 0)
+			power_button_countdown--;
+
+	} else {
+
+		/* Done on button release, to allow for auto-power-on mods. */
+		if (power_button_countdown == 0) {
+			/* Signal init to do the ctrlaltdel action,
+			 * this will bypass init if it hasn't started
+			 * and do a kernel_restart.
+			 */
+			ctrl_alt_del();
+
+			/* Change the state of the power LED to "blink" */
+			gpio_set_value(NAS100D_LED_PWR_GPIO, 0);
+		} else {
+			power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
+		}
+	}
+
+	mod_timer(&nas100d_power_timer, jiffies + msecs_to_jiffies(500));
+}
+
+static irqreturn_t nas100d_reset_handler(int irq, void *dev_id)
+{
+	/* This is the paper-clip reset, it shuts the machine down directly. */
+	machine_power_off();
+
+	return IRQ_HANDLED;
+}
+
+static int __init nas100d_gpio_init(void)
+{
+	if (!machine_is_nas100d())
+		return 0;
+
+	/*
+	 * The power button on the Iomega NAS100d is on GPIO 14, but
+	 * it cannot handle interrupts on that GPIO line.  So we'll
+	 * have to poll it with a kernel timer.
+	 */
+
+	/* Request the power off GPIO */
+	gpio_request(NAS100D_PO_GPIO, "power off");
+
+	/* Make sure that the power button GPIO is set up as an input */
+	gpio_request(NAS100D_PB_GPIO, "power button");
+	gpio_direction_input(NAS100D_PB_GPIO);
+
+	/* Set the initial value for the power button IRQ handler */
+	power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
+
+	mod_timer(&nas100d_power_timer, jiffies + msecs_to_jiffies(500));
+
+	return 0;
+}
+device_initcall(nas100d_gpio_init);
+
+static void __init nas100d_init(void)
+{
+	uint8_t __iomem *f;
+	int i;
+
+	ixp4xx_sys_init();
+
+	/* gpio 14 and 15 are _not_ clocks */
+	*IXP4XX_GPIO_GPCLKR = 0;
+
+	nas100d_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+	nas100d_flash_resource.end =
+		IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
+
+	i2c_register_board_info(0, nas100d_i2c_board_info,
+				ARRAY_SIZE(nas100d_i2c_board_info));
+
+	/*
+	 * This is only useful on a modified machine, but it is valuable
+	 * to have it first in order to see debug messages, and so that
+	 * it does *not* get removed if platform_add_devices fails!
+	 */
+	(void)platform_device_register(&nas100d_uart);
+
+	platform_add_devices(nas100d_devices, ARRAY_SIZE(nas100d_devices));
+
+	pm_power_off = nas100d_power_off;
+
+	if (request_irq(gpio_to_irq(NAS100D_RB_GPIO), &nas100d_reset_handler,
+		IRQF_TRIGGER_LOW, "NAS100D reset button", NULL) < 0) {
+
+		printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
+			gpio_to_irq(NAS100D_RB_GPIO));
+	}
+
+	/*
+	 * Map in a portion of the flash and read the MAC address.
+	 * Since it is stored in BE in the flash itself, we need to
+	 * byteswap it if we're in LE mode.
+	 */
+	f = ioremap(IXP4XX_EXP_BUS_BASE(0), 0x1000000);
+	if (f) {
+		for (i = 0; i < 6; i++)
+#ifdef __ARMEB__
+			nas100d_plat_eth[0].hwaddr[i] = readb(f + 0xFC0FD8 + i);
+#else
+			nas100d_plat_eth[0].hwaddr[i] = readb(f + 0xFC0FD8 + (i^3));
+#endif
+		iounmap(f);
+	}
+	printk(KERN_INFO "NAS100D: Using MAC address %pM for port 0\n",
+	       nas100d_plat_eth[0].hwaddr);
+
+}
+
+MACHINE_START(NAS100D, "Iomega NAS 100d")
+	/* Maintainer: www.nslu2-linux.org */
+	.atag_offset	= 0x100,
+	.map_io		= ixp4xx_map_io,
+	.init_early	= ixp4xx_init_early,
+	.init_irq	= ixp4xx_init_irq,
+	.init_time	= ixp4xx_timer_init,
+	.init_machine	= nas100d_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
+	.restart	= ixp4xx_restart,
+MACHINE_END
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/nslu2-pci.c b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/nslu2-pci.c
new file mode 100644
index 0000000..032defe
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/nslu2-pci.c
@@ -0,0 +1,71 @@
+/*
+ * arch/arm/mach-ixp4xx/nslu2-pci.c
+ *
+ * NSLU2 board-level PCI initialization
+ *
+ * based on ixdp425-pci.c:
+ *	Copyright (C) 2002 Intel Corporation.
+ *	Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ * Maintainer: http://www.nslu2-linux.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/init.h>
+#include <linux/irq.h>
+#include <asm/mach/pci.h>
+#include <asm/mach-types.h>
+
+#define MAX_DEV		3
+#define IRQ_LINES	3
+
+/* PCI controller GPIO to IRQ pin mappings */
+#define INTA		11
+#define INTB		10
+#define INTC		9
+#define INTD		8
+
+void __init nslu2_pci_preinit(void)
+{
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
+	ixp4xx_pci_preinit();
+}
+
+static int __init nslu2_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	static int pci_irq_table[IRQ_LINES] = {
+		IXP4XX_GPIO_IRQ(INTA),
+		IXP4XX_GPIO_IRQ(INTB),
+		IXP4XX_GPIO_IRQ(INTC),
+	};
+
+	if (slot >= 1 && slot <= MAX_DEV && pin >= 1 && pin <= IRQ_LINES)
+		return pci_irq_table[(slot + pin - 2) % IRQ_LINES];
+
+	return -1;
+}
+
+struct hw_pci __initdata nslu2_pci = {
+	.nr_controllers = 1,
+	.ops		= &ixp4xx_ops,
+	.preinit	= nslu2_pci_preinit,
+	.setup		= ixp4xx_setup,
+	.map_irq	= nslu2_map_irq,
+};
+
+int __init nslu2_pci_init(void) /* monkey see, monkey do */
+{
+	if (machine_is_nslu2())
+		pci_common_init(&nslu2_pci);
+
+	return 0;
+}
+
+subsys_initcall(nslu2_pci_init);
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/nslu2-setup.c b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/nslu2-setup.c
new file mode 100644
index 0000000..bd8dc65
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/nslu2-setup.c
@@ -0,0 +1,314 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * arch/arm/mach-ixp4xx/nslu2-setup.c
+ *
+ * NSLU2 board-setup
+ *
+ * Copyright (C) 2008 Rod Whitby <rod@whitby.id.au>
+ *
+ * based on ixdp425-setup.c:
+ *      Copyright (C) 2003-2004 MontaVista Software, Inc.
+ * based on nslu2-power.c:
+ *	Copyright (C) 2005 Tower Technologies
+ *
+ * Author: Mark Rakes <mrakes at mac.com>
+ * Author: Rod Whitby <rod@whitby.id.au>
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ * Maintainers: http://www.nslu2-linux.org/
+ *
+ */
+#include <linux/gpio.h>
+#include <linux/if_ether.h>
+#include <linux/irq.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/leds.h>
+#include <linux/reboot.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
+#include <linux/io.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/time.h>
+
+#define NSLU2_SDA_PIN		7
+#define NSLU2_SCL_PIN		6
+
+/* NSLU2 Timer */
+#define NSLU2_FREQ 66000000
+
+/* Buttons */
+#define NSLU2_PB_GPIO		5	/* power button */
+#define NSLU2_PO_GPIO		8	/* power off */
+#define NSLU2_RB_GPIO		12	/* reset button */
+
+/* Buzzer */
+#define NSLU2_GPIO_BUZZ		4
+
+/* LEDs */
+#define NSLU2_LED_RED_GPIO	0
+#define NSLU2_LED_GRN_GPIO	1
+#define NSLU2_LED_DISK1_GPIO	3
+#define NSLU2_LED_DISK2_GPIO	2
+
+static struct flash_platform_data nslu2_flash_data = {
+	.map_name		= "cfi_probe",
+	.width			= 2,
+};
+
+static struct resource nslu2_flash_resource = {
+	.flags			= IORESOURCE_MEM,
+};
+
+static struct platform_device nslu2_flash = {
+	.name			= "IXP4XX-Flash",
+	.id			= 0,
+	.dev.platform_data	= &nslu2_flash_data,
+	.num_resources		= 1,
+	.resource		= &nslu2_flash_resource,
+};
+
+static struct i2c_gpio_platform_data nslu2_i2c_gpio_data = {
+	.sda_pin		= NSLU2_SDA_PIN,
+	.scl_pin		= NSLU2_SCL_PIN,
+};
+
+static struct i2c_board_info __initdata nslu2_i2c_board_info [] = {
+	{
+		I2C_BOARD_INFO("x1205", 0x6f),
+	},
+};
+
+static struct gpio_led nslu2_led_pins[] = {
+	{
+		.name		= "nslu2:green:ready",
+		.gpio		= NSLU2_LED_GRN_GPIO,
+	},
+	{
+		.name		= "nslu2:red:status",
+		.gpio		= NSLU2_LED_RED_GPIO,
+	},
+	{
+		.name		= "nslu2:green:disk-1",
+		.gpio		= NSLU2_LED_DISK1_GPIO,
+		.active_low	= true,
+	},
+	{
+		.name		= "nslu2:green:disk-2",
+		.gpio		= NSLU2_LED_DISK2_GPIO,
+		.active_low	= true,
+	},
+};
+
+static struct gpio_led_platform_data nslu2_led_data = {
+	.num_leds		= ARRAY_SIZE(nslu2_led_pins),
+	.leds			= nslu2_led_pins,
+};
+
+static struct platform_device nslu2_leds = {
+	.name			= "leds-gpio",
+	.id			= -1,
+	.dev.platform_data	= &nslu2_led_data,
+};
+
+static struct platform_device nslu2_i2c_gpio = {
+	.name			= "i2c-gpio",
+	.id			= 0,
+	.dev	 = {
+		.platform_data	= &nslu2_i2c_gpio_data,
+	},
+};
+
+static struct platform_device nslu2_beeper = {
+	.name			= "ixp4xx-beeper",
+	.id			= NSLU2_GPIO_BUZZ,
+	.num_resources		= 0,
+};
+
+static struct resource nslu2_uart_resources[] = {
+	{
+		.start		= IXP4XX_UART1_BASE_PHYS,
+		.end		= IXP4XX_UART1_BASE_PHYS + 0x0fff,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= IXP4XX_UART2_BASE_PHYS,
+		.end		= IXP4XX_UART2_BASE_PHYS + 0x0fff,
+		.flags		= IORESOURCE_MEM,
+	}
+};
+
+static struct plat_serial8250_port nslu2_uart_data[] = {
+	{
+		.mapbase	= IXP4XX_UART1_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART1,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	},
+	{
+		.mapbase	= IXP4XX_UART2_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART2,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	},
+	{ }
+};
+
+static struct platform_device nslu2_uart = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev.platform_data	= nslu2_uart_data,
+	.num_resources		= 2,
+	.resource		= nslu2_uart_resources,
+};
+
+/* Built-in 10/100 Ethernet MAC interfaces */
+static struct eth_plat_info nslu2_plat_eth[] = {
+	{
+		.phy		= 1,
+		.rxq		= 3,
+		.txreadyq	= 20,
+	}
+};
+
+static struct platform_device nslu2_eth[] = {
+	{
+		.name			= "ixp4xx_eth",
+		.id			= IXP4XX_ETH_NPEB,
+		.dev.platform_data	= nslu2_plat_eth,
+	}
+};
+
+static struct platform_device *nslu2_devices[] __initdata = {
+	&nslu2_i2c_gpio,
+	&nslu2_flash,
+	&nslu2_beeper,
+	&nslu2_leds,
+	&nslu2_eth[0],
+};
+
+static void nslu2_power_off(void)
+{
+	/* This causes the box to drop the power and go dead. */
+
+	/* enable the pwr cntl gpio and assert power off */
+	gpio_direction_output(NSLU2_PO_GPIO, 1);
+}
+
+static irqreturn_t nslu2_power_handler(int irq, void *dev_id)
+{
+	/* Signal init to do the ctrlaltdel action, this will bypass init if
+	 * it hasn't started and do a kernel_restart.
+	 */
+	ctrl_alt_del();
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t nslu2_reset_handler(int irq, void *dev_id)
+{
+	/* This is the paper-clip reset, it shuts the machine down directly.
+	 */
+	machine_power_off();
+
+	return IRQ_HANDLED;
+}
+
+static int __init nslu2_gpio_init(void)
+{
+	if (!machine_is_nslu2())
+		return 0;
+
+	/* Request the power off GPIO */
+	return gpio_request(NSLU2_PO_GPIO, "power off");
+}
+device_initcall(nslu2_gpio_init);
+
+static void __init nslu2_timer_init(void)
+{
+    /* The xtal on this machine is non-standard. */
+    ixp4xx_timer_freq = NSLU2_FREQ;
+
+    /* Call standard timer_init function. */
+    ixp4xx_timer_init();
+}
+
+static void __init nslu2_init(void)
+{
+	uint8_t __iomem *f;
+	int i;
+
+	ixp4xx_sys_init();
+
+	nslu2_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+	nslu2_flash_resource.end =
+		IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
+
+	i2c_register_board_info(0, nslu2_i2c_board_info,
+				ARRAY_SIZE(nslu2_i2c_board_info));
+
+	/*
+	 * This is only useful on a modified machine, but it is valuable
+	 * to have it first in order to see debug messages, and so that
+	 * it does *not* get removed if platform_add_devices fails!
+	 */
+	(void)platform_device_register(&nslu2_uart);
+
+	platform_add_devices(nslu2_devices, ARRAY_SIZE(nslu2_devices));
+
+	pm_power_off = nslu2_power_off;
+
+	if (request_irq(gpio_to_irq(NSLU2_RB_GPIO), &nslu2_reset_handler,
+		IRQF_TRIGGER_LOW, "NSLU2 reset button", NULL) < 0) {
+
+		printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
+			gpio_to_irq(NSLU2_RB_GPIO));
+	}
+
+	if (request_irq(gpio_to_irq(NSLU2_PB_GPIO), &nslu2_power_handler,
+		IRQF_TRIGGER_HIGH, "NSLU2 power button", NULL) < 0) {
+
+		printk(KERN_DEBUG "Power Button IRQ %d not available\n",
+			gpio_to_irq(NSLU2_PB_GPIO));
+	}
+
+	/*
+	 * Map in a portion of the flash and read the MAC address.
+	 * Since it is stored in BE in the flash itself, we need to
+	 * byteswap it if we're in LE mode.
+	 */
+	f = ioremap(IXP4XX_EXP_BUS_BASE(0), 0x40000);
+	if (f) {
+		for (i = 0; i < 6; i++)
+#ifdef __ARMEB__
+			nslu2_plat_eth[0].hwaddr[i] = readb(f + 0x3FFB0 + i);
+#else
+			nslu2_plat_eth[0].hwaddr[i] = readb(f + 0x3FFB0 + (i^3));
+#endif
+		iounmap(f);
+	}
+	printk(KERN_INFO "NSLU2: Using MAC address %pM for port 0\n",
+	       nslu2_plat_eth[0].hwaddr);
+
+}
+
+MACHINE_START(NSLU2, "Linksys NSLU2")
+	/* Maintainer: www.nslu2-linux.org */
+	.atag_offset	= 0x100,
+	.map_io		= ixp4xx_map_io,
+	.init_early	= ixp4xx_init_early,
+	.init_irq	= ixp4xx_init_irq,
+	.init_time	= nslu2_timer_init,
+	.init_machine	= nslu2_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
+	.restart	= ixp4xx_restart,
+MACHINE_END
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/omixp-setup.c b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/omixp-setup.c
new file mode 100644
index 0000000..2d494b4
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/omixp-setup.c
@@ -0,0 +1,279 @@
+/*
+ * arch/arm/mach-ixp4xx/omixp-setup.c
+ *
+ * omicron ixp4xx board setup
+ *      Copyright (C) 2009 OMICRON electronics GmbH
+ *
+ * based nslu2-setup.c, ixdp425-setup.c:
+ *      Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ * 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/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/leds.h>
+
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+#include <mach/hardware.h>
+
+static struct resource omixp_flash_resources[] = {
+	{
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct mtd_partition omixp_partitions[] = {
+	{
+		.name =		"Recovery Bootloader",
+		.size =		0x00020000,
+		.offset =	0,
+	}, {
+		.name =		"Calibration Data",
+		.size =		0x00020000,
+		.offset =	0x00020000,
+	}, {
+		.name =		"Recovery FPGA",
+		.size =		0x00020000,
+		.offset =	0x00040000,
+	}, {
+		.name =		"Release Bootloader",
+		.size =		0x00020000,
+		.offset =	0x00060000,
+	}, {
+		.name =		"Release FPGA",
+		.size =		0x00020000,
+		.offset =	0x00080000,
+	}, {
+		.name =		"Kernel",
+		.size =		0x00160000,
+		.offset =	0x000a0000,
+	}, {
+		.name =		"Filesystem",
+		.size =		0x00C00000,
+		.offset =	0x00200000,
+	}, {
+		.name =		"Persistent Storage",
+		.size =		0x00200000,
+		.offset =	0x00E00000,
+	},
+};
+
+static struct flash_platform_data omixp_flash_data[] = {
+	{
+		.map_name	= "cfi_probe",
+		.parts		= omixp_partitions,
+		.nr_parts	= ARRAY_SIZE(omixp_partitions),
+	}, {
+		.map_name	= "cfi_probe",
+		.parts		= NULL,
+		.nr_parts	= 0,
+	},
+};
+
+static struct platform_device omixp_flash_device[] = {
+	{
+		.name		= "IXP4XX-Flash",
+		.id		= 0,
+		.dev = {
+			.platform_data = &omixp_flash_data[0],
+		},
+		.resource = &omixp_flash_resources[0],
+		.num_resources = 1,
+	}, {
+		.name		= "IXP4XX-Flash",
+		.id		= 1,
+		.dev = {
+			.platform_data = &omixp_flash_data[1],
+		},
+		.resource = &omixp_flash_resources[1],
+		.num_resources = 1,
+	},
+};
+
+/* Swap UART's - These boards have the console on UART2. The following
+ * configuration is used:
+ *      ttyS0 .. UART2
+ *      ttyS1 .. UART1
+ * This way standard images can be used with the kernel that expect
+ * the console on ttyS0.
+ */
+static struct resource omixp_uart_resources[] = {
+	{
+		.start		= IXP4XX_UART2_BASE_PHYS,
+		.end		= IXP4XX_UART2_BASE_PHYS + 0x0fff,
+		.flags		= IORESOURCE_MEM,
+	}, {
+		.start		= IXP4XX_UART1_BASE_PHYS,
+		.end		= IXP4XX_UART1_BASE_PHYS + 0x0fff,
+		.flags		= IORESOURCE_MEM,
+	},
+};
+
+static struct plat_serial8250_port omixp_uart_data[] = {
+	{
+		.mapbase	= IXP4XX_UART2_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART2,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	}, {
+		.mapbase	= IXP4XX_UART1_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART1,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	}, {
+		/* list termination */
+	}
+};
+
+static struct platform_device omixp_uart = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev.platform_data	= omixp_uart_data,
+	.num_resources		= 2,
+	.resource		= omixp_uart_resources,
+};
+
+static struct gpio_led mic256_led_pins[] = {
+	{
+		.name		= "LED-A",
+		.gpio		= 7,
+	},
+};
+
+static struct gpio_led_platform_data mic256_led_data = {
+	.num_leds		= ARRAY_SIZE(mic256_led_pins),
+	.leds			= mic256_led_pins,
+};
+
+static struct platform_device mic256_leds = {
+	.name			= "leds-gpio",
+	.id			= -1,
+	.dev.platform_data	= &mic256_led_data,
+};
+
+/* Built-in 10/100 Ethernet MAC interfaces */
+static struct eth_plat_info ixdp425_plat_eth[] = {
+	{
+		.phy		= 0,
+		.rxq		= 3,
+		.txreadyq	= 20,
+	}, {
+		.phy		= 1,
+		.rxq		= 4,
+		.txreadyq	= 21,
+	},
+};
+
+static struct platform_device ixdp425_eth[] = {
+	{
+		.name			= "ixp4xx_eth",
+		.id			= IXP4XX_ETH_NPEB,
+		.dev.platform_data	= ixdp425_plat_eth,
+	}, {
+		.name			= "ixp4xx_eth",
+		.id			= IXP4XX_ETH_NPEC,
+		.dev.platform_data	= ixdp425_plat_eth + 1,
+	},
+};
+
+
+static struct platform_device *devixp_pldev[] __initdata = {
+	&omixp_uart,
+	&omixp_flash_device[0],
+	&ixdp425_eth[0],
+	&ixdp425_eth[1],
+};
+
+static struct platform_device *mic256_pldev[] __initdata = {
+	&omixp_uart,
+	&omixp_flash_device[0],
+	&mic256_leds,
+	&ixdp425_eth[0],
+	&ixdp425_eth[1],
+};
+
+static struct platform_device *miccpt_pldev[] __initdata = {
+	&omixp_uart,
+	&omixp_flash_device[0],
+	&omixp_flash_device[1],
+	&ixdp425_eth[0],
+	&ixdp425_eth[1],
+};
+
+static void __init omixp_init(void)
+{
+	ixp4xx_sys_init();
+
+	/* 16MiB Boot Flash */
+	omixp_flash_resources[0].start = IXP4XX_EXP_BUS_BASE(0);
+	omixp_flash_resources[0].end   = IXP4XX_EXP_BUS_END(0);
+
+	/* 32 MiB Data Flash */
+	omixp_flash_resources[1].start = IXP4XX_EXP_BUS_BASE(2);
+	omixp_flash_resources[1].end   = IXP4XX_EXP_BUS_END(2);
+
+	if (machine_is_devixp())
+		platform_add_devices(devixp_pldev, ARRAY_SIZE(devixp_pldev));
+	else if (machine_is_miccpt())
+		platform_add_devices(miccpt_pldev, ARRAY_SIZE(miccpt_pldev));
+	else if (machine_is_mic256())
+		platform_add_devices(mic256_pldev, ARRAY_SIZE(mic256_pldev));
+}
+
+#ifdef CONFIG_MACH_DEVIXP
+MACHINE_START(DEVIXP, "Omicron DEVIXP")
+	.atag_offset    = 0x100,
+	.map_io		= ixp4xx_map_io,
+	.init_early	= ixp4xx_init_early,
+	.init_irq	= ixp4xx_init_irq,
+	.init_time	= ixp4xx_timer_init,
+	.init_machine	= omixp_init,
+	.restart	= ixp4xx_restart,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_MICCPT
+MACHINE_START(MICCPT, "Omicron MICCPT")
+	.atag_offset    = 0x100,
+	.map_io		= ixp4xx_map_io,
+	.init_early	= ixp4xx_init_early,
+	.init_irq	= ixp4xx_init_irq,
+	.init_time	= ixp4xx_timer_init,
+	.init_machine	= omixp_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
+	.restart	= ixp4xx_restart,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_MIC256
+MACHINE_START(MIC256, "Omicron MIC256")
+	.atag_offset    = 0x100,
+	.map_io		= ixp4xx_map_io,
+	.init_early	= ixp4xx_init_early,
+	.init_irq	= ixp4xx_init_irq,
+	.init_time	= ixp4xx_timer_init,
+	.init_machine	= omixp_init,
+	.restart	= ixp4xx_restart,
+MACHINE_END
+#endif
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/vulcan-pci.c b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/vulcan-pci.c
new file mode 100644
index 0000000..a4220fa
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/vulcan-pci.c
@@ -0,0 +1,72 @@
+/*
+ * arch/arch/mach-ixp4xx/vulcan-pci.c
+ *
+ * Vulcan board-level PCI initialization
+ *
+ * Copyright (C) 2010 Marc Zyngier <maz@misterjones.org>
+ *
+ * based on ixdp425-pci.c:
+ *	Copyright (C) 2002 Intel Corporation.
+ *	Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ * 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/init.h>
+#include <linux/irq.h>
+#include <asm/mach/pci.h>
+#include <asm/mach-types.h>
+
+/* PCI controller GPIO to IRQ pin mappings */
+#define INTA	2
+#define INTB	3
+
+void __init vulcan_pci_preinit(void)
+{
+#ifndef CONFIG_IXP4XX_INDIRECT_PCI
+	/*
+	 * Cardbus bridge wants way more than the SoC can actually offer,
+	 * and leaves the whole PCI bus in a mess. Artificially limit it
+	 * to 8MB per region. Of course indirect mode doesn't have this
+	 * limitation...
+	 */
+	pci_cardbus_mem_size = SZ_8M;
+	pr_info("Vulcan PCI: limiting CardBus memory size to %dMB\n",
+		(int)(pci_cardbus_mem_size >> 20));
+#endif
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
+	ixp4xx_pci_preinit();
+}
+
+static int __init vulcan_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	if (slot == 1)
+		return IXP4XX_GPIO_IRQ(INTA);
+
+	if (slot == 2)
+		return IXP4XX_GPIO_IRQ(INTB);
+
+	return -1;
+}
+
+struct hw_pci vulcan_pci __initdata = {
+	.nr_controllers	= 1,
+	.ops		= &ixp4xx_ops,
+	.preinit	= vulcan_pci_preinit,
+	.setup		= ixp4xx_setup,
+	.map_irq	= vulcan_map_irq,
+};
+
+int __init vulcan_pci_init(void)
+{
+	if (machine_is_arcom_vulcan())
+		pci_common_init(&vulcan_pci);
+	return 0;
+}
+
+subsys_initcall(vulcan_pci_init);
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/vulcan-setup.c b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/vulcan-setup.c
new file mode 100644
index 0000000..731fb20
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/vulcan-setup.c
@@ -0,0 +1,251 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * arch/arm/mach-ixp4xx/vulcan-setup.c
+ *
+ * Arcom/Eurotech Vulcan board-setup
+ *
+ * Copyright (C) 2010 Marc Zyngier <maz@misterjones.org>
+ *
+ * based on fsg-setup.c:
+ *	Copyright (C) 2008 Rod Whitby <rod@whitby.id.au>
+ */
+
+#include <linux/if_ether.h>
+#include <linux/irq.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/io.h>
+#include <linux/w1-gpio.h>
+#include <linux/mtd/plat-ram.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+static struct flash_platform_data vulcan_flash_data = {
+	.map_name	= "cfi_probe",
+	.width		= 2,
+};
+
+static struct resource vulcan_flash_resource = {
+	.flags			= IORESOURCE_MEM,
+};
+
+static struct platform_device vulcan_flash = {
+	.name			= "IXP4XX-Flash",
+	.id			= 0,
+	.dev = {
+		.platform_data	= &vulcan_flash_data,
+	},
+	.resource		= &vulcan_flash_resource,
+	.num_resources		= 1,
+};
+
+static struct platdata_mtd_ram vulcan_sram_data = {
+	.mapname	= "Vulcan SRAM",
+	.bankwidth	= 1,
+};
+
+static struct resource vulcan_sram_resource = {
+	.flags			= IORESOURCE_MEM,
+};
+
+static struct platform_device vulcan_sram = {
+	.name			= "mtd-ram",
+	.id			= 0,
+	.dev = {
+		.platform_data	= &vulcan_sram_data,
+	},
+	.resource		= &vulcan_sram_resource,
+	.num_resources		= 1,
+};
+
+static struct resource vulcan_uart_resources[] = {
+	[0] = {
+		.start		= IXP4XX_UART1_BASE_PHYS,
+		.end		= IXP4XX_UART1_BASE_PHYS + 0x0fff,
+		.flags		= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start		= IXP4XX_UART2_BASE_PHYS,
+		.end		= IXP4XX_UART2_BASE_PHYS + 0x0fff,
+		.flags		= IORESOURCE_MEM,
+	},
+	[2] = {
+		.flags		= IORESOURCE_MEM,
+	},
+};
+
+static struct plat_serial8250_port vulcan_uart_data[] = {
+	[0] = {
+		.mapbase	= IXP4XX_UART1_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART1,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	},
+	[1] = {
+		.mapbase	= IXP4XX_UART2_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART2,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	},
+	[2] = {
+		.irq		= IXP4XX_GPIO_IRQ(4),
+		.irqflags	= IRQF_TRIGGER_LOW,
+		.flags		= UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.uartclk	= 1843200,
+	},
+	[3] = {
+		.irq		= IXP4XX_GPIO_IRQ(4),
+		.irqflags	= IRQF_TRIGGER_LOW,
+		.flags		= UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.uartclk	= 1843200,
+	},
+	{ }
+};
+
+static struct platform_device vulcan_uart = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev = {
+		.platform_data	= vulcan_uart_data,
+	},
+	.resource		= vulcan_uart_resources,
+	.num_resources		= ARRAY_SIZE(vulcan_uart_resources),
+};
+
+static struct eth_plat_info vulcan_plat_eth[] = {
+	[0] = {
+		.phy		= 0,
+		.rxq		= 3,
+		.txreadyq	= 20,
+	},
+	[1] = {
+		.phy		= 1,
+		.rxq		= 4,
+		.txreadyq	= 21,
+	},
+};
+
+static struct platform_device vulcan_eth[] = {
+	[0] = {
+		.name			= "ixp4xx_eth",
+		.id			= IXP4XX_ETH_NPEB,
+		.dev = {
+			.platform_data	= &vulcan_plat_eth[0],
+		},
+	},
+	[1] = {
+		.name			= "ixp4xx_eth",
+		.id			= IXP4XX_ETH_NPEC,
+		.dev = {
+			.platform_data	= &vulcan_plat_eth[1],
+		},
+	},
+};
+
+static struct resource vulcan_max6369_resource = {
+	.flags			= IORESOURCE_MEM,
+};
+
+static struct platform_device vulcan_max6369 = {
+	.name			= "max6369_wdt",
+	.id			= -1,
+	.resource		= &vulcan_max6369_resource,
+	.num_resources		= 1,
+};
+
+static struct w1_gpio_platform_data vulcan_w1_gpio_pdata = {
+	.pin			= 14,
+	.ext_pullup_enable_pin	= -EINVAL,
+};
+
+static struct platform_device vulcan_w1_gpio = {
+	.name			= "w1-gpio",
+	.id			= 0,
+	.dev			= {
+		.platform_data	= &vulcan_w1_gpio_pdata,
+	},
+};
+
+static struct platform_device *vulcan_devices[] __initdata = {
+	&vulcan_uart,
+	&vulcan_flash,
+	&vulcan_sram,
+	&vulcan_max6369,
+	&vulcan_eth[0],
+	&vulcan_eth[1],
+	&vulcan_w1_gpio,
+};
+
+static void __init vulcan_init(void)
+{
+	ixp4xx_sys_init();
+
+	/* Flash is spread over both CS0 and CS1 */
+	vulcan_flash_resource.start	 = IXP4XX_EXP_BUS_BASE(0);
+	vulcan_flash_resource.end	 = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1;
+	*IXP4XX_EXP_CS0 = IXP4XX_EXP_BUS_CS_EN		|
+			  IXP4XX_EXP_BUS_STROBE_T(3)	|
+			  IXP4XX_EXP_BUS_SIZE(0xF)	|
+			  IXP4XX_EXP_BUS_BYTE_RD16	|
+			  IXP4XX_EXP_BUS_WR_EN;
+	*IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0;
+
+	/* SRAM on CS2, (256kB, 8bit, writable) */
+	vulcan_sram_resource.start	= IXP4XX_EXP_BUS_BASE(2);
+	vulcan_sram_resource.end	= IXP4XX_EXP_BUS_BASE(2) + SZ_256K - 1;
+	*IXP4XX_EXP_CS2 = IXP4XX_EXP_BUS_CS_EN		|
+			  IXP4XX_EXP_BUS_STROBE_T(1)	|
+			  IXP4XX_EXP_BUS_HOLD_T(2)	|
+			  IXP4XX_EXP_BUS_SIZE(9)	|
+			  IXP4XX_EXP_BUS_SPLT_EN	|
+			  IXP4XX_EXP_BUS_WR_EN		|
+			  IXP4XX_EXP_BUS_BYTE_EN;
+
+	/* XR16L2551 on CS3 (Moto style, 512 bytes, 8bits, writable) */
+	vulcan_uart_resources[2].start	= IXP4XX_EXP_BUS_BASE(3);
+	vulcan_uart_resources[2].end	= IXP4XX_EXP_BUS_BASE(3) + 16 - 1;
+	vulcan_uart_data[2].mapbase	= vulcan_uart_resources[2].start;
+	vulcan_uart_data[3].mapbase	= vulcan_uart_data[2].mapbase + 8;
+	*IXP4XX_EXP_CS3 = IXP4XX_EXP_BUS_CS_EN		|
+			  IXP4XX_EXP_BUS_STROBE_T(3)	|
+			  IXP4XX_EXP_BUS_CYCLES(IXP4XX_EXP_BUS_CYCLES_MOTOROLA)|
+			  IXP4XX_EXP_BUS_WR_EN		|
+			  IXP4XX_EXP_BUS_BYTE_EN;
+
+	/* GPIOS on CS4 (512 bytes, 8bits, writable) */
+	*IXP4XX_EXP_CS4 = IXP4XX_EXP_BUS_CS_EN		|
+			  IXP4XX_EXP_BUS_WR_EN		|
+			  IXP4XX_EXP_BUS_BYTE_EN;
+
+	/* max6369 on CS5 (512 bytes, 8bits, writable) */
+	vulcan_max6369_resource.start	= IXP4XX_EXP_BUS_BASE(5);
+	vulcan_max6369_resource.end	= IXP4XX_EXP_BUS_BASE(5);
+	*IXP4XX_EXP_CS5 = IXP4XX_EXP_BUS_CS_EN		|
+			  IXP4XX_EXP_BUS_WR_EN		|
+			  IXP4XX_EXP_BUS_BYTE_EN;
+
+	platform_add_devices(vulcan_devices, ARRAY_SIZE(vulcan_devices));
+}
+
+MACHINE_START(ARCOM_VULCAN, "Arcom/Eurotech Vulcan")
+	/* Maintainer: Marc Zyngier <maz@misterjones.org> */
+	.map_io		= ixp4xx_map_io,
+	.init_early	= ixp4xx_init_early,
+	.init_irq	= ixp4xx_init_irq,
+	.init_time	= ixp4xx_timer_init,
+	.atag_offset	= 0x100,
+	.init_machine	= vulcan_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
+	.restart	= ixp4xx_restart,
+MACHINE_END
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/wg302v2-pci.c b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/wg302v2-pci.c
new file mode 100644
index 0000000..c92e5b8
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/wg302v2-pci.c
@@ -0,0 +1,62 @@
+/*
+ * arch/arch/mach-ixp4xx/wg302v2-pci.c
+ *
+ * PCI setup routines for the Netgear WG302 v2 and WAG302 v2
+ *
+ * Copyright (C) 2007 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * based on coyote-pci.c:
+ *	Copyright (C) 2002 Jungo Software Technologies.
+ *	Copyright (C) 2003 MontaVista Software, Inc.
+ *
+ * Maintainer: 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/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+
+#include <asm/mach/pci.h>
+
+void __init wg302v2_pci_preinit(void)
+{
+	irq_set_irq_type(IRQ_IXP4XX_GPIO8, IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IRQ_IXP4XX_GPIO9, IRQ_TYPE_LEVEL_LOW);
+
+	ixp4xx_pci_preinit();
+}
+
+static int __init wg302v2_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	if (slot == 1)
+		return IRQ_IXP4XX_GPIO8;
+	else if (slot == 2)
+		return IRQ_IXP4XX_GPIO9;
+	else return -1;
+}
+
+struct hw_pci wg302v2_pci __initdata = {
+	.nr_controllers = 1,
+	.ops = &ixp4xx_ops,
+	.preinit =        wg302v2_pci_preinit,
+	.setup =          ixp4xx_setup,
+	.map_irq =        wg302v2_map_irq,
+};
+
+int __init wg302v2_pci_init(void)
+{
+	if (machine_is_wg302v2())
+		pci_common_init(&wg302v2_pci);
+	return 0;
+}
+
+subsys_initcall(wg302v2_pci_init);
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/wg302v2-setup.c b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/wg302v2-setup.c
new file mode 100644
index 0000000..90b3c60
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ixp4xx/wg302v2-setup.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * arch/arm/mach-ixp4xx/wg302-setup.c
+ *
+ * Board setup for the Netgear WG302 v2 and WAG302 v2
+ *
+ * Copyright (C) 2007 Imre Kaloz <Kaloz@openwrt.org>
+ *
+ * based on coyote-setup.c:
+ *      Copyright (C) 2003-2005 MontaVista Software, Inc.
+ *
+ * Author: Imre Kaloz <kaloz@openwrt.org>
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_8250.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <mach/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+static struct flash_platform_data wg302v2_flash_data = {
+	.map_name	= "cfi_probe",
+	.width		= 2,
+};
+
+static struct resource wg302v2_flash_resource = {
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device wg302v2_flash = {
+	.name		= "IXP4XX-Flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &wg302v2_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &wg302v2_flash_resource,
+};
+
+static struct resource wg302v2_uart_resource = {
+	.start	= IXP4XX_UART2_BASE_PHYS,
+	.end	= IXP4XX_UART2_BASE_PHYS + 0x0fff,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct plat_serial8250_port wg302v2_uart_data[] = {
+	{
+		.mapbase	= IXP4XX_UART2_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART2,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	},
+	{ },
+};
+
+static struct platform_device wg302v2_uart = {
+	.name		= "serial8250",
+	.id		= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= wg302v2_uart_data,
+	},
+	.num_resources	= 1,
+	.resource	= &wg302v2_uart_resource,
+};
+
+static struct platform_device *wg302v2_devices[] __initdata = {
+	&wg302v2_flash,
+	&wg302v2_uart,
+};
+
+static void __init wg302v2_init(void)
+{
+	ixp4xx_sys_init();
+
+	wg302v2_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+	wg302v2_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1;
+
+	*IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE;
+	*IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0;
+
+	platform_add_devices(wg302v2_devices, ARRAY_SIZE(wg302v2_devices));
+}
+
+#ifdef CONFIG_MACH_WG302V2
+MACHINE_START(WG302V2, "Netgear WG302 v2 / WAG302 v2")
+	/* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
+	.map_io		= ixp4xx_map_io,
+	.init_early	= ixp4xx_init_early,
+	.init_irq	= ixp4xx_init_irq,
+	.init_time	= ixp4xx_timer_init,
+	.atag_offset	= 0x100,
+	.init_machine	= wg302v2_init,
+#if defined(CONFIG_PCI)
+	.dma_zone_size	= SZ_64M,
+#endif
+	.restart	= ixp4xx_restart,
+MACHINE_END
+#endif