[Feature]add MT2731_MP2_MR2_SVN388 baseline version

Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/Kconfig b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/Kconfig
new file mode 100644
index 0000000..61a75ca
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/Kconfig
@@ -0,0 +1,146 @@
+if ARCH_EP93XX
+
+menu "Cirrus EP93xx Implementation Options"
+
+config EP93XX_SOC_COMMON
+	bool
+	default y
+	select SOC_BUS
+	select LEDS_GPIO_REGISTER
+
+config CRUNCH
+	bool "Support for MaverickCrunch"
+	help
+	  Enable kernel support for MaverickCrunch.
+
+comment "EP93xx Platforms"
+
+config MACH_ADSSPHERE
+	bool "Support ADS Sphere"
+	help
+	  Say 'Y' here if you want your kernel to support the ADS
+	  Sphere board.
+
+config MACH_EDB93XX
+	bool
+
+config MACH_EDB9301
+	bool "Support Cirrus Logic EDB9301"
+	select MACH_EDB93XX
+	help
+	  Say 'Y' here if you want your kernel to support the Cirrus
+	  Logic EDB9301 Evaluation Board.
+
+config MACH_EDB9302
+	bool "Support Cirrus Logic EDB9302"
+	select MACH_EDB93XX
+	help
+	  Say 'Y' here if you want your kernel to support the Cirrus
+	  Logic EDB9302 Evaluation Board.
+
+config MACH_EDB9302A
+	bool "Support Cirrus Logic EDB9302A"
+	select MACH_EDB93XX
+	help
+	  Say 'Y' here if you want your kernel to support the Cirrus
+	  Logic EDB9302A Evaluation Board.
+
+config MACH_EDB9307
+	bool "Support Cirrus Logic EDB9307"
+	select MACH_EDB93XX
+	help
+	  Say 'Y' here if you want your kernel to support the Cirrus
+	  Logic EDB9307 Evaluation Board.
+
+config MACH_EDB9307A
+	bool "Support Cirrus Logic EDB9307A"
+	select MACH_EDB93XX
+	help
+	  Say 'Y' here if you want your kernel to support the Cirrus
+	  Logic EDB9307A Evaluation Board.
+
+config MACH_EDB9312
+	bool "Support Cirrus Logic EDB9312"
+	select MACH_EDB93XX
+	help
+	  Say 'Y' here if you want your kernel to support the Cirrus
+	  Logic EDB9312 Evaluation Board.
+
+config MACH_EDB9315
+	bool "Support Cirrus Logic EDB9315"
+	select MACH_EDB93XX
+	help
+	  Say 'Y' here if you want your kernel to support the Cirrus
+	  Logic EDB9315 Evaluation Board.
+
+config MACH_EDB9315A
+	bool "Support Cirrus Logic EDB9315A"
+	select MACH_EDB93XX
+	help
+	  Say 'Y' here if you want your kernel to support the Cirrus
+	  Logic EDB9315A Evaluation Board.
+
+config MACH_GESBC9312
+	bool "Support Glomation GESBC-9312-sx"
+	help
+	  Say 'Y' here if you want your kernel to support the Glomation
+	  GESBC-9312-sx board.
+
+config MACH_MICRO9
+	bool
+
+config MACH_MICRO9H
+	bool "Support Contec Micro9-High"
+	select MACH_MICRO9
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Contec Micro9-High board.
+
+config MACH_MICRO9M
+	bool "Support Contec Micro9-Mid"
+	select MACH_MICRO9
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Contec Micro9-Mid board.
+
+config MACH_MICRO9L
+	bool "Support Contec Micro9-Lite"
+	select MACH_MICRO9
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Contec Micro9-Lite board.
+
+config MACH_MICRO9S
+	bool "Support Contec Micro9-Slim"
+	select MACH_MICRO9
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Contec Micro9-Slim board.
+
+config MACH_SIM_ONE
+        bool "Support Simplemachines Sim.One board"
+        help
+          Say 'Y' here if you want your kernel to support the
+          Simplemachines Sim.One board.
+
+config MACH_SNAPPER_CL15
+	bool "Support Bluewater Systems Snapper CL15 Module"
+	help
+	  Say 'Y' here if you want your kernel to support the Bluewater
+	  Systems Snapper CL15 Module.
+
+config MACH_TS72XX
+	bool "Support Technologic Systems TS-72xx SBC"
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Technologic Systems TS-72xx board.
+
+config MACH_VISION_EP9307
+	bool "Support Vision Engraving Systems EP9307 SoM"
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Vision Engraving Systems EP9307 SoM.
+
+endmenu
+
+endif
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/Makefile b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/Makefile
new file mode 100644
index 0000000..8676849
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/Makefile
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for the linux kernel.
+#
+obj-y			:= core.o clock.o timer-ep93xx.o
+
+obj-$(CONFIG_EP93XX_DMA)	+= dma.o
+
+obj-$(CONFIG_CRUNCH)		+= crunch.o crunch-bits.o
+AFLAGS_crunch-bits.o		:= -Wa,-mcpu=ep9312
+
+obj-$(CONFIG_MACH_ADSSPHERE)	+= adssphere.o
+obj-$(CONFIG_MACH_EDB93XX)	+= edb93xx.o
+obj-$(CONFIG_MACH_GESBC9312)	+= gesbc9312.o
+obj-$(CONFIG_MACH_MICRO9)	+= micro9.o
+obj-$(CONFIG_MACH_SIM_ONE)	+= simone.o
+obj-$(CONFIG_MACH_SNAPPER_CL15)	+= snappercl15.o
+obj-$(CONFIG_MACH_TS72XX)	+= ts72xx.o
+obj-$(CONFIG_MACH_VISION_EP9307)+= vision_ep9307.o
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/Makefile.boot b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/Makefile.boot
new file mode 100644
index 0000000..ed82ed7
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/Makefile.boot
@@ -0,0 +1 @@
+# Empty file waiting for deletion once Makefile.boot isn't needed any more.
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/adssphere.c b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/adssphere.c
new file mode 100644
index 0000000..bda6c3a
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/adssphere.c
@@ -0,0 +1,45 @@
+/*
+ * arch/arm/mach-ep93xx/adssphere.c
+ * ADS Sphere support.
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/sizes.h>
+
+#include <mach/hardware.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include "soc.h"
+
+static struct ep93xx_eth_data __initdata adssphere_eth_data = {
+	.phy_id		= 1,
+};
+
+static void __init adssphere_init_machine(void)
+{
+	ep93xx_init_devices();
+	ep93xx_register_flash(4, EP93XX_CS6_PHYS_BASE, SZ_32M);
+	ep93xx_register_eth(&adssphere_eth_data, 1);
+}
+
+MACHINE_START(ADSSPHERE, "ADS Sphere board")
+	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
+	.atag_offset	= 0x100,
+	.map_io		= ep93xx_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.init_time	= ep93xx_timer_init,
+	.init_machine	= adssphere_init_machine,
+	.init_late	= ep93xx_init_late,
+	.restart	= ep93xx_restart,
+MACHINE_END
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/clock.c b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/clock.c
new file mode 100644
index 0000000..d2eee70
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/clock.c
@@ -0,0 +1,591 @@
+/*
+ * arch/arm/mach-ep93xx/clock.c
+ * Clock control for Cirrus EP93xx chips.
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/clkdev.h>
+
+#include <mach/hardware.h>
+
+#include <asm/div64.h>
+
+#include "soc.h"
+
+struct clk {
+	struct clk	*parent;
+	unsigned long	rate;
+	int		users;
+	int		sw_locked;
+	void __iomem	*enable_reg;
+	u32		enable_mask;
+
+	unsigned long	(*get_rate)(struct clk *clk);
+	int		(*set_rate)(struct clk *clk, unsigned long rate);
+};
+
+
+static unsigned long get_uart_rate(struct clk *clk);
+
+static int set_keytchclk_rate(struct clk *clk, unsigned long rate);
+static int set_div_rate(struct clk *clk, unsigned long rate);
+static int set_i2s_sclk_rate(struct clk *clk, unsigned long rate);
+static int set_i2s_lrclk_rate(struct clk *clk, unsigned long rate);
+
+static struct clk clk_xtali = {
+	.rate		= EP93XX_EXT_CLK_RATE,
+};
+static struct clk clk_uart1 = {
+	.parent		= &clk_xtali,
+	.sw_locked	= 1,
+	.enable_reg	= EP93XX_SYSCON_DEVCFG,
+	.enable_mask	= EP93XX_SYSCON_DEVCFG_U1EN,
+	.get_rate	= get_uart_rate,
+};
+static struct clk clk_uart2 = {
+	.parent		= &clk_xtali,
+	.sw_locked	= 1,
+	.enable_reg	= EP93XX_SYSCON_DEVCFG,
+	.enable_mask	= EP93XX_SYSCON_DEVCFG_U2EN,
+	.get_rate	= get_uart_rate,
+};
+static struct clk clk_uart3 = {
+	.parent		= &clk_xtali,
+	.sw_locked	= 1,
+	.enable_reg	= EP93XX_SYSCON_DEVCFG,
+	.enable_mask	= EP93XX_SYSCON_DEVCFG_U3EN,
+	.get_rate	= get_uart_rate,
+};
+static struct clk clk_pll1 = {
+	.parent		= &clk_xtali,
+};
+static struct clk clk_f = {
+	.parent		= &clk_pll1,
+};
+static struct clk clk_h = {
+	.parent		= &clk_pll1,
+};
+static struct clk clk_p = {
+	.parent		= &clk_pll1,
+};
+static struct clk clk_pll2 = {
+	.parent		= &clk_xtali,
+};
+static struct clk clk_usb_host = {
+	.parent		= &clk_pll2,
+	.enable_reg	= EP93XX_SYSCON_PWRCNT,
+	.enable_mask	= EP93XX_SYSCON_PWRCNT_USH_EN,
+};
+static struct clk clk_keypad = {
+	.parent		= &clk_xtali,
+	.sw_locked	= 1,
+	.enable_reg	= EP93XX_SYSCON_KEYTCHCLKDIV,
+	.enable_mask	= EP93XX_SYSCON_KEYTCHCLKDIV_KEN,
+	.set_rate	= set_keytchclk_rate,
+};
+static struct clk clk_adc = {
+	.parent		= &clk_xtali,
+	.sw_locked	= 1,
+	.enable_reg	= EP93XX_SYSCON_KEYTCHCLKDIV,
+	.enable_mask	= EP93XX_SYSCON_KEYTCHCLKDIV_TSEN,
+	.set_rate	= set_keytchclk_rate,
+};
+static struct clk clk_spi = {
+	.parent		= &clk_xtali,
+	.rate		= EP93XX_EXT_CLK_RATE,
+};
+static struct clk clk_pwm = {
+	.parent		= &clk_xtali,
+	.rate		= EP93XX_EXT_CLK_RATE,
+};
+
+static struct clk clk_video = {
+	.sw_locked	= 1,
+	.enable_reg     = EP93XX_SYSCON_VIDCLKDIV,
+	.enable_mask    = EP93XX_SYSCON_CLKDIV_ENABLE,
+	.set_rate	= set_div_rate,
+};
+
+static struct clk clk_i2s_mclk = {
+	.sw_locked	= 1,
+	.enable_reg	= EP93XX_SYSCON_I2SCLKDIV,
+	.enable_mask	= EP93XX_SYSCON_CLKDIV_ENABLE,
+	.set_rate	= set_div_rate,
+};
+
+static struct clk clk_i2s_sclk = {
+	.sw_locked	= 1,
+	.parent		= &clk_i2s_mclk,
+	.enable_reg	= EP93XX_SYSCON_I2SCLKDIV,
+	.enable_mask	= EP93XX_SYSCON_I2SCLKDIV_SENA,
+	.set_rate	= set_i2s_sclk_rate,
+};
+
+static struct clk clk_i2s_lrclk = {
+	.sw_locked	= 1,
+	.parent		= &clk_i2s_sclk,
+	.enable_reg	= EP93XX_SYSCON_I2SCLKDIV,
+	.enable_mask	= EP93XX_SYSCON_I2SCLKDIV_SENA,
+	.set_rate	= set_i2s_lrclk_rate,
+};
+
+/* DMA Clocks */
+static struct clk clk_m2p0 = {
+	.parent		= &clk_h,
+	.enable_reg	= EP93XX_SYSCON_PWRCNT,
+	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2P0,
+};
+static struct clk clk_m2p1 = {
+	.parent		= &clk_h,
+	.enable_reg	= EP93XX_SYSCON_PWRCNT,
+	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2P1,
+};
+static struct clk clk_m2p2 = {
+	.parent		= &clk_h,
+	.enable_reg	= EP93XX_SYSCON_PWRCNT,
+	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2P2,
+};
+static struct clk clk_m2p3 = {
+	.parent		= &clk_h,
+	.enable_reg	= EP93XX_SYSCON_PWRCNT,
+	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2P3,
+};
+static struct clk clk_m2p4 = {
+	.parent		= &clk_h,
+	.enable_reg	= EP93XX_SYSCON_PWRCNT,
+	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2P4,
+};
+static struct clk clk_m2p5 = {
+	.parent		= &clk_h,
+	.enable_reg	= EP93XX_SYSCON_PWRCNT,
+	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2P5,
+};
+static struct clk clk_m2p6 = {
+	.parent		= &clk_h,
+	.enable_reg	= EP93XX_SYSCON_PWRCNT,
+	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2P6,
+};
+static struct clk clk_m2p7 = {
+	.parent		= &clk_h,
+	.enable_reg	= EP93XX_SYSCON_PWRCNT,
+	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2P7,
+};
+static struct clk clk_m2p8 = {
+	.parent		= &clk_h,
+	.enable_reg	= EP93XX_SYSCON_PWRCNT,
+	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2P8,
+};
+static struct clk clk_m2p9 = {
+	.parent		= &clk_h,
+	.enable_reg	= EP93XX_SYSCON_PWRCNT,
+	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2P9,
+};
+static struct clk clk_m2m0 = {
+	.parent		= &clk_h,
+	.enable_reg	= EP93XX_SYSCON_PWRCNT,
+	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2M0,
+};
+static struct clk clk_m2m1 = {
+	.parent		= &clk_h,
+	.enable_reg	= EP93XX_SYSCON_PWRCNT,
+	.enable_mask	= EP93XX_SYSCON_PWRCNT_DMA_M2M1,
+};
+
+#define INIT_CK(dev,con,ck)					\
+	{ .dev_id = dev, .con_id = con, .clk = ck }
+
+static struct clk_lookup clocks[] = {
+	INIT_CK(NULL,			"xtali",	&clk_xtali),
+	INIT_CK("apb:uart1",		NULL,		&clk_uart1),
+	INIT_CK("apb:uart2",		NULL,		&clk_uart2),
+	INIT_CK("apb:uart3",		NULL,		&clk_uart3),
+	INIT_CK(NULL,			"pll1",		&clk_pll1),
+	INIT_CK(NULL,			"fclk",		&clk_f),
+	INIT_CK(NULL,			"hclk",		&clk_h),
+	INIT_CK(NULL,			"apb_pclk",	&clk_p),
+	INIT_CK(NULL,			"pll2",		&clk_pll2),
+	INIT_CK("ohci-platform",	NULL,		&clk_usb_host),
+	INIT_CK("ep93xx-keypad",	NULL,		&clk_keypad),
+	INIT_CK("ep93xx-adc",		NULL,		&clk_adc),
+	INIT_CK("ep93xx-fb",		NULL,		&clk_video),
+	INIT_CK("ep93xx-spi.0",		NULL,		&clk_spi),
+	INIT_CK("ep93xx-i2s",		"mclk",		&clk_i2s_mclk),
+	INIT_CK("ep93xx-i2s",		"sclk",		&clk_i2s_sclk),
+	INIT_CK("ep93xx-i2s",		"lrclk",	&clk_i2s_lrclk),
+	INIT_CK(NULL,			"pwm_clk",	&clk_pwm),
+	INIT_CK(NULL,			"m2p0",		&clk_m2p0),
+	INIT_CK(NULL,			"m2p1",		&clk_m2p1),
+	INIT_CK(NULL,			"m2p2",		&clk_m2p2),
+	INIT_CK(NULL,			"m2p3",		&clk_m2p3),
+	INIT_CK(NULL,			"m2p4",		&clk_m2p4),
+	INIT_CK(NULL,			"m2p5",		&clk_m2p5),
+	INIT_CK(NULL,			"m2p6",		&clk_m2p6),
+	INIT_CK(NULL,			"m2p7",		&clk_m2p7),
+	INIT_CK(NULL,			"m2p8",		&clk_m2p8),
+	INIT_CK(NULL,			"m2p9",		&clk_m2p9),
+	INIT_CK(NULL,			"m2m0",		&clk_m2m0),
+	INIT_CK(NULL,			"m2m1",		&clk_m2m1),
+};
+
+static DEFINE_SPINLOCK(clk_lock);
+
+static void __clk_enable(struct clk *clk)
+{
+	if (!clk->users++) {
+		if (clk->parent)
+			__clk_enable(clk->parent);
+
+		if (clk->enable_reg) {
+			u32 v;
+
+			v = __raw_readl(clk->enable_reg);
+			v |= clk->enable_mask;
+			if (clk->sw_locked)
+				ep93xx_syscon_swlocked_write(v, clk->enable_reg);
+			else
+				__raw_writel(v, clk->enable_reg);
+		}
+	}
+}
+
+int clk_enable(struct clk *clk)
+{
+	unsigned long flags;
+
+	if (!clk)
+		return -EINVAL;
+
+	spin_lock_irqsave(&clk_lock, flags);
+	__clk_enable(clk);
+	spin_unlock_irqrestore(&clk_lock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+static void __clk_disable(struct clk *clk)
+{
+	if (!--clk->users) {
+		if (clk->enable_reg) {
+			u32 v;
+
+			v = __raw_readl(clk->enable_reg);
+			v &= ~clk->enable_mask;
+			if (clk->sw_locked)
+				ep93xx_syscon_swlocked_write(v, clk->enable_reg);
+			else
+				__raw_writel(v, clk->enable_reg);
+		}
+
+		if (clk->parent)
+			__clk_disable(clk->parent);
+	}
+}
+
+void clk_disable(struct clk *clk)
+{
+	unsigned long flags;
+
+	if (!clk)
+		return;
+
+	spin_lock_irqsave(&clk_lock, flags);
+	__clk_disable(clk);
+	spin_unlock_irqrestore(&clk_lock, flags);
+}
+EXPORT_SYMBOL(clk_disable);
+
+static unsigned long get_uart_rate(struct clk *clk)
+{
+	unsigned long rate = clk_get_rate(clk->parent);
+	u32 value;
+
+	value = __raw_readl(EP93XX_SYSCON_PWRCNT);
+	if (value & EP93XX_SYSCON_PWRCNT_UARTBAUD)
+		return rate;
+	else
+		return rate / 2;
+}
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (clk->get_rate)
+		return clk->get_rate(clk);
+
+	return clk->rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+static int set_keytchclk_rate(struct clk *clk, unsigned long rate)
+{
+	u32 val;
+	u32 div_bit;
+
+	val = __raw_readl(clk->enable_reg);
+
+	/*
+	 * The Key Matrix and ADC clocks are configured using the same
+	 * System Controller register.  The clock used will be either
+	 * 1/4 or 1/16 the external clock rate depending on the
+	 * EP93XX_SYSCON_KEYTCHCLKDIV_KDIV/EP93XX_SYSCON_KEYTCHCLKDIV_ADIV
+	 * bit being set or cleared.
+	 */
+	div_bit = clk->enable_mask >> 15;
+
+	if (rate == EP93XX_KEYTCHCLK_DIV4)
+		val |= div_bit;
+	else if (rate == EP93XX_KEYTCHCLK_DIV16)
+		val &= ~div_bit;
+	else
+		return -EINVAL;
+
+	ep93xx_syscon_swlocked_write(val, clk->enable_reg);
+	clk->rate = rate;
+	return 0;
+}
+
+static int calc_clk_div(struct clk *clk, unsigned long rate,
+			int *psel, int *esel, int *pdiv, int *div)
+{
+	struct clk *mclk;
+	unsigned long max_rate, actual_rate, mclk_rate, rate_err = -1;
+	int i, found = 0, __div = 0, __pdiv = 0;
+
+	/* Don't exceed the maximum rate */
+	max_rate = max3(clk_pll1.rate / 4, clk_pll2.rate / 4, clk_xtali.rate / 4);
+	rate = min(rate, max_rate);
+
+	/*
+	 * Try the two pll's and the external clock
+	 * Because the valid predividers are 2, 2.5 and 3, we multiply
+	 * all the clocks by 2 to avoid floating point math.
+	 *
+	 * This is based on the algorithm in the ep93xx raster guide:
+	 * http://be-a-maverick.com/en/pubs/appNote/AN269REV1.pdf
+	 *
+	 */
+	for (i = 0; i < 3; i++) {
+		if (i == 0)
+			mclk = &clk_xtali;
+		else if (i == 1)
+			mclk = &clk_pll1;
+		else
+			mclk = &clk_pll2;
+		mclk_rate = mclk->rate * 2;
+
+		/* Try each predivider value */
+		for (__pdiv = 4; __pdiv <= 6; __pdiv++) {
+			__div = mclk_rate / (rate * __pdiv);
+			if (__div < 2 || __div > 127)
+				continue;
+
+			actual_rate = mclk_rate / (__pdiv * __div);
+
+			if (!found || abs(actual_rate - rate) < rate_err) {
+				*pdiv = __pdiv - 3;
+				*div = __div;
+				*psel = (i == 2);
+				*esel = (i != 0);
+				clk->parent = mclk;
+				clk->rate = actual_rate;
+				rate_err = abs(actual_rate - rate);
+				found = 1;
+			}
+		}
+	}
+
+	if (!found)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int set_div_rate(struct clk *clk, unsigned long rate)
+{
+	int err, psel = 0, esel = 0, pdiv = 0, div = 0;
+	u32 val;
+
+	err = calc_clk_div(clk, rate, &psel, &esel, &pdiv, &div);
+	if (err)
+		return err;
+
+	/* Clear the esel, psel, pdiv and div bits */
+	val = __raw_readl(clk->enable_reg);
+	val &= ~0x7fff;
+
+	/* Set the new esel, psel, pdiv and div bits for the new clock rate */
+	val |= (esel ? EP93XX_SYSCON_CLKDIV_ESEL : 0) |
+		(psel ? EP93XX_SYSCON_CLKDIV_PSEL : 0) |
+		(pdiv << EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | div;
+	ep93xx_syscon_swlocked_write(val, clk->enable_reg);
+	return 0;
+}
+
+static int set_i2s_sclk_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned val = __raw_readl(clk->enable_reg);
+
+	if (rate == clk_i2s_mclk.rate / 2)
+		ep93xx_syscon_swlocked_write(val & ~EP93XX_I2SCLKDIV_SDIV, 
+					     clk->enable_reg);
+	else if (rate == clk_i2s_mclk.rate / 4)
+		ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_SDIV, 
+					     clk->enable_reg);
+	else
+		return -EINVAL;
+
+	clk_i2s_sclk.rate = rate;
+	return 0;
+}
+
+static int set_i2s_lrclk_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned val = __raw_readl(clk->enable_reg) & 
+		~EP93XX_I2SCLKDIV_LRDIV_MASK;
+	
+	if (rate == clk_i2s_sclk.rate / 32)
+		ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV32,
+					     clk->enable_reg);
+	else if (rate == clk_i2s_sclk.rate / 64)
+		ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV64,
+					     clk->enable_reg);
+	else if (rate == clk_i2s_sclk.rate / 128)
+		ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV128,
+					     clk->enable_reg);
+	else
+		return -EINVAL;
+
+	clk_i2s_lrclk.rate = rate;
+	return 0;
+}
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	if (clk->set_rate)
+		return clk->set_rate(clk, rate);
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	WARN_ON(clk);
+	return 0;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	WARN_ON(clk);
+	return 0;
+}
+EXPORT_SYMBOL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+	return clk->parent;
+}
+EXPORT_SYMBOL(clk_get_parent);
+
+
+static char fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 };
+static char hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 };
+static char pclk_divisors[] = { 1, 2, 4, 8 };
+
+/*
+ * PLL rate = 14.7456 MHz * (X1FBD + 1) * (X2FBD + 1) / (X2IPD + 1) / 2^PS
+ */
+static unsigned long calc_pll_rate(u32 config_word)
+{
+	unsigned long long rate;
+	int i;
+
+	rate = clk_xtali.rate;
+	rate *= ((config_word >> 11) & 0x1f) + 1;		/* X1FBD */
+	rate *= ((config_word >> 5) & 0x3f) + 1;		/* X2FBD */
+	do_div(rate, (config_word & 0x1f) + 1);			/* X2IPD */
+	for (i = 0; i < ((config_word >> 16) & 3); i++)		/* PS */
+		rate >>= 1;
+
+	return (unsigned long)rate;
+}
+
+static void __init ep93xx_dma_clock_init(void)
+{
+	clk_m2p0.rate = clk_h.rate;
+	clk_m2p1.rate = clk_h.rate;
+	clk_m2p2.rate = clk_h.rate;
+	clk_m2p3.rate = clk_h.rate;
+	clk_m2p4.rate = clk_h.rate;
+	clk_m2p5.rate = clk_h.rate;
+	clk_m2p6.rate = clk_h.rate;
+	clk_m2p7.rate = clk_h.rate;
+	clk_m2p8.rate = clk_h.rate;
+	clk_m2p9.rate = clk_h.rate;
+	clk_m2m0.rate = clk_h.rate;
+	clk_m2m1.rate = clk_h.rate;
+}
+
+static int __init ep93xx_clock_init(void)
+{
+	u32 value;
+
+	/* Determine the bootloader configured pll1 rate */
+	value = __raw_readl(EP93XX_SYSCON_CLKSET1);
+	if (!(value & EP93XX_SYSCON_CLKSET1_NBYP1))
+		clk_pll1.rate = clk_xtali.rate;
+	else
+		clk_pll1.rate = calc_pll_rate(value);
+
+	/* Initialize the pll1 derived clocks */
+	clk_f.rate = clk_pll1.rate / fclk_divisors[(value >> 25) & 0x7];
+	clk_h.rate = clk_pll1.rate / hclk_divisors[(value >> 20) & 0x7];
+	clk_p.rate = clk_h.rate / pclk_divisors[(value >> 18) & 0x3];
+	ep93xx_dma_clock_init();
+
+	/* Determine the bootloader configured pll2 rate */
+	value = __raw_readl(EP93XX_SYSCON_CLKSET2);
+	if (!(value & EP93XX_SYSCON_CLKSET2_NBYP2))
+		clk_pll2.rate = clk_xtali.rate;
+	else if (value & EP93XX_SYSCON_CLKSET2_PLL2_EN)
+		clk_pll2.rate = calc_pll_rate(value);
+	else
+		clk_pll2.rate = 0;
+
+	/* Initialize the pll2 derived clocks */
+	clk_usb_host.rate = clk_pll2.rate / (((value >> 28) & 0xf) + 1);
+
+	/*
+	 * EP93xx SSP clock rate was doubled in version E2. For more information
+	 * see:
+	 *     http://www.cirrus.com/en/pubs/appNote/AN273REV4.pdf
+	 */
+	if (ep93xx_chip_revision() < EP93XX_CHIP_REV_E2)
+		clk_spi.rate /= 2;
+
+	pr_info("PLL1 running at %ld MHz, PLL2 at %ld MHz\n",
+		clk_pll1.rate / 1000000, clk_pll2.rate / 1000000);
+	pr_info("FCLK %ld MHz, HCLK %ld MHz, PCLK %ld MHz\n",
+		clk_f.rate / 1000000, clk_h.rate / 1000000,
+		clk_p.rate / 1000000);
+
+	clkdev_add_table(clocks, ARRAY_SIZE(clocks));
+	return 0;
+}
+postcore_initcall(ep93xx_clock_init);
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/core.c b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/core.c
new file mode 100644
index 0000000..f53c618
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/core.c
@@ -0,0 +1,998 @@
+/*
+ * arch/arm/mach-ep93xx/core.c
+ * Core routines for Cirrus EP93xx chips.
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org>
+ *
+ * Thanks go to Michael Burian and Ray Lehtiniemi for their key
+ * role in the ep93xx linux community.
+ *
+ * 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.
+ */
+
+#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/sys_soc.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/termios.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/serial.h>
+#include <linux/mtd/physmap.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/export.h>
+#include <linux/irqchip/arm-vic.h>
+#include <linux/reboot.h>
+#include <linux/usb/ohci_pdriver.h>
+#include <linux/random.h>
+
+#include <mach/hardware.h>
+#include <linux/platform_data/video-ep93xx.h>
+#include <linux/platform_data/keypad-ep93xx.h>
+#include <linux/platform_data/spi-ep93xx.h>
+#include <mach/gpio-ep93xx.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include "soc.h"
+
+/*************************************************************************
+ * Static I/O mappings that are needed for all EP93xx platforms
+ *************************************************************************/
+static struct map_desc ep93xx_io_desc[] __initdata = {
+	{
+		.virtual	= EP93XX_AHB_VIRT_BASE,
+		.pfn		= __phys_to_pfn(EP93XX_AHB_PHYS_BASE),
+		.length		= EP93XX_AHB_SIZE,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= EP93XX_APB_VIRT_BASE,
+		.pfn		= __phys_to_pfn(EP93XX_APB_PHYS_BASE),
+		.length		= EP93XX_APB_SIZE,
+		.type		= MT_DEVICE,
+	},
+};
+
+void __init ep93xx_map_io(void)
+{
+	iotable_init(ep93xx_io_desc, ARRAY_SIZE(ep93xx_io_desc));
+}
+
+/*************************************************************************
+ * EP93xx IRQ handling
+ *************************************************************************/
+void __init ep93xx_init_irq(void)
+{
+	vic_init(EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK, 0);
+	vic_init(EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK, 0);
+}
+
+
+/*************************************************************************
+ * EP93xx System Controller Software Locked register handling
+ *************************************************************************/
+
+/*
+ * syscon_swlock prevents anything else from writing to the syscon
+ * block while a software locked register is being written.
+ */
+static DEFINE_SPINLOCK(syscon_swlock);
+
+void ep93xx_syscon_swlocked_write(unsigned int val, void __iomem *reg)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&syscon_swlock, flags);
+
+	__raw_writel(0xaa, EP93XX_SYSCON_SWLOCK);
+	__raw_writel(val, reg);
+
+	spin_unlock_irqrestore(&syscon_swlock, flags);
+}
+
+void ep93xx_devcfg_set_clear(unsigned int set_bits, unsigned int clear_bits)
+{
+	unsigned long flags;
+	unsigned int val;
+
+	spin_lock_irqsave(&syscon_swlock, flags);
+
+	val = __raw_readl(EP93XX_SYSCON_DEVCFG);
+	val &= ~clear_bits;
+	val |= set_bits;
+	__raw_writel(0xaa, EP93XX_SYSCON_SWLOCK);
+	__raw_writel(val, EP93XX_SYSCON_DEVCFG);
+
+	spin_unlock_irqrestore(&syscon_swlock, flags);
+}
+
+/**
+ * ep93xx_chip_revision() - returns the EP93xx chip revision
+ *
+ * See <mach/platform.h> for more information.
+ */
+unsigned int ep93xx_chip_revision(void)
+{
+	unsigned int v;
+
+	v = __raw_readl(EP93XX_SYSCON_SYSCFG);
+	v &= EP93XX_SYSCON_SYSCFG_REV_MASK;
+	v >>= EP93XX_SYSCON_SYSCFG_REV_SHIFT;
+	return v;
+}
+EXPORT_SYMBOL_GPL(ep93xx_chip_revision);
+
+/*************************************************************************
+ * EP93xx GPIO
+ *************************************************************************/
+static struct resource ep93xx_gpio_resource[] = {
+	DEFINE_RES_MEM(EP93XX_GPIO_PHYS_BASE, 0xcc),
+};
+
+static struct platform_device ep93xx_gpio_device = {
+	.name		= "gpio-ep93xx",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(ep93xx_gpio_resource),
+	.resource	= ep93xx_gpio_resource,
+};
+
+/*************************************************************************
+ * EP93xx peripheral handling
+ *************************************************************************/
+#define EP93XX_UART_MCR_OFFSET		(0x0100)
+
+static void ep93xx_uart_set_mctrl(struct amba_device *dev,
+				  void __iomem *base, unsigned int mctrl)
+{
+	unsigned int mcr;
+
+	mcr = 0;
+	if (mctrl & TIOCM_RTS)
+		mcr |= 2;
+	if (mctrl & TIOCM_DTR)
+		mcr |= 1;
+
+	__raw_writel(mcr, base + EP93XX_UART_MCR_OFFSET);
+}
+
+static struct amba_pl010_data ep93xx_uart_data = {
+	.set_mctrl	= ep93xx_uart_set_mctrl,
+};
+
+static AMBA_APB_DEVICE(uart1, "apb:uart1", 0x00041010, EP93XX_UART1_PHYS_BASE,
+	{ IRQ_EP93XX_UART1 }, &ep93xx_uart_data);
+
+static AMBA_APB_DEVICE(uart2, "apb:uart2", 0x00041010, EP93XX_UART2_PHYS_BASE,
+	{ IRQ_EP93XX_UART2 }, NULL);
+
+static AMBA_APB_DEVICE(uart3, "apb:uart3", 0x00041010, EP93XX_UART3_PHYS_BASE,
+	{ IRQ_EP93XX_UART3 }, &ep93xx_uart_data);
+
+static struct resource ep93xx_rtc_resource[] = {
+	DEFINE_RES_MEM(EP93XX_RTC_PHYS_BASE, 0x10c),
+};
+
+static struct platform_device ep93xx_rtc_device = {
+	.name		= "ep93xx-rtc",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(ep93xx_rtc_resource),
+	.resource	= ep93xx_rtc_resource,
+};
+
+/*************************************************************************
+ * EP93xx OHCI USB Host
+ *************************************************************************/
+
+static struct clk *ep93xx_ohci_host_clock;
+
+static int ep93xx_ohci_power_on(struct platform_device *pdev)
+{
+	if (!ep93xx_ohci_host_clock) {
+		ep93xx_ohci_host_clock = devm_clk_get(&pdev->dev, NULL);
+		if (IS_ERR(ep93xx_ohci_host_clock))
+			return PTR_ERR(ep93xx_ohci_host_clock);
+	}
+
+	return clk_enable(ep93xx_ohci_host_clock);
+}
+
+static void ep93xx_ohci_power_off(struct platform_device *pdev)
+{
+	clk_disable(ep93xx_ohci_host_clock);
+}
+
+static struct usb_ohci_pdata ep93xx_ohci_pdata = {
+	.power_on	= ep93xx_ohci_power_on,
+	.power_off	= ep93xx_ohci_power_off,
+	.power_suspend	= ep93xx_ohci_power_off,
+};
+
+static struct resource ep93xx_ohci_resources[] = {
+	DEFINE_RES_MEM(EP93XX_USB_PHYS_BASE, 0x1000),
+	DEFINE_RES_IRQ(IRQ_EP93XX_USB),
+};
+
+static u64 ep93xx_ohci_dma_mask = DMA_BIT_MASK(32);
+
+static struct platform_device ep93xx_ohci_device = {
+	.name		= "ohci-platform",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(ep93xx_ohci_resources),
+	.resource	= ep93xx_ohci_resources,
+	.dev		= {
+		.dma_mask		= &ep93xx_ohci_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.platform_data		= &ep93xx_ohci_pdata,
+	},
+};
+
+/*************************************************************************
+ * EP93xx physmap'ed flash
+ *************************************************************************/
+static struct physmap_flash_data ep93xx_flash_data;
+
+static struct resource ep93xx_flash_resource = {
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device ep93xx_flash = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &ep93xx_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &ep93xx_flash_resource,
+};
+
+/**
+ * ep93xx_register_flash() - Register the external flash device.
+ * @width:	bank width in octets
+ * @start:	resource start address
+ * @size:	resource size
+ */
+void __init ep93xx_register_flash(unsigned int width,
+				  resource_size_t start, resource_size_t size)
+{
+	ep93xx_flash_data.width		= width;
+
+	ep93xx_flash_resource.start	= start;
+	ep93xx_flash_resource.end	= start + size - 1;
+
+	platform_device_register(&ep93xx_flash);
+}
+
+
+/*************************************************************************
+ * EP93xx ethernet peripheral handling
+ *************************************************************************/
+static struct ep93xx_eth_data ep93xx_eth_data;
+
+static struct resource ep93xx_eth_resource[] = {
+	DEFINE_RES_MEM(EP93XX_ETHERNET_PHYS_BASE, 0x10000),
+	DEFINE_RES_IRQ(IRQ_EP93XX_ETHERNET),
+};
+
+static u64 ep93xx_eth_dma_mask = DMA_BIT_MASK(32);
+
+static struct platform_device ep93xx_eth_device = {
+	.name		= "ep93xx-eth",
+	.id		= -1,
+	.dev		= {
+		.platform_data		= &ep93xx_eth_data,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.dma_mask		= &ep93xx_eth_dma_mask,
+	},
+	.num_resources	= ARRAY_SIZE(ep93xx_eth_resource),
+	.resource	= ep93xx_eth_resource,
+};
+
+/**
+ * ep93xx_register_eth - Register the built-in ethernet platform device.
+ * @data:	platform specific ethernet configuration (__initdata)
+ * @copy_addr:	flag indicating that the MAC address should be copied
+ *		from the IndAd registers (as programmed by the bootloader)
+ */
+void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr)
+{
+	if (copy_addr)
+		memcpy_fromio(data->dev_addr, EP93XX_ETHERNET_BASE + 0x50, 6);
+
+	ep93xx_eth_data = *data;
+	platform_device_register(&ep93xx_eth_device);
+}
+
+
+/*************************************************************************
+ * EP93xx i2c peripheral handling
+ *************************************************************************/
+static struct i2c_gpio_platform_data ep93xx_i2c_data;
+
+static struct platform_device ep93xx_i2c_device = {
+	.name		= "i2c-gpio",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &ep93xx_i2c_data,
+	},
+};
+
+/**
+ * ep93xx_register_i2c - Register the i2c platform device.
+ * @data:	platform specific i2c-gpio configuration (__initdata)
+ * @devices:	platform specific i2c bus device information (__initdata)
+ * @num:	the number of devices on the i2c bus
+ */
+void __init ep93xx_register_i2c(struct i2c_gpio_platform_data *data,
+				struct i2c_board_info *devices, int num)
+{
+	/*
+	 * Set the EEPROM interface pin drive type control.
+	 * Defines the driver type for the EECLK and EEDAT pins as either
+	 * open drain, which will require an external pull-up, or a normal
+	 * CMOS driver.
+	 */
+	if (data->sda_is_open_drain && data->sda_pin != EP93XX_GPIO_LINE_EEDAT)
+		pr_warning("sda != EEDAT, open drain has no effect\n");
+	if (data->scl_is_open_drain && data->scl_pin != EP93XX_GPIO_LINE_EECLK)
+		pr_warning("scl != EECLK, open drain has no effect\n");
+
+	__raw_writel((data->sda_is_open_drain << 1) |
+		     (data->scl_is_open_drain << 0),
+		     EP93XX_GPIO_EEDRIVE);
+
+	ep93xx_i2c_data = *data;
+	i2c_register_board_info(0, devices, num);
+	platform_device_register(&ep93xx_i2c_device);
+}
+
+/*************************************************************************
+ * EP93xx SPI peripheral handling
+ *************************************************************************/
+static struct ep93xx_spi_info ep93xx_spi_master_data;
+
+static struct resource ep93xx_spi_resources[] = {
+	DEFINE_RES_MEM(EP93XX_SPI_PHYS_BASE, 0x18),
+	DEFINE_RES_IRQ(IRQ_EP93XX_SSP),
+};
+
+static u64 ep93xx_spi_dma_mask = DMA_BIT_MASK(32);
+
+static struct platform_device ep93xx_spi_device = {
+	.name		= "ep93xx-spi",
+	.id		= 0,
+	.dev		= {
+		.platform_data		= &ep93xx_spi_master_data,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.dma_mask		= &ep93xx_spi_dma_mask,
+	},
+	.num_resources	= ARRAY_SIZE(ep93xx_spi_resources),
+	.resource	= ep93xx_spi_resources,
+};
+
+/**
+ * ep93xx_register_spi() - registers spi platform device
+ * @info: ep93xx board specific spi master info (__initdata)
+ * @devices: SPI devices to register (__initdata)
+ * @num: number of SPI devices to register
+ *
+ * This function registers platform device for the EP93xx SPI controller and
+ * also makes sure that SPI pins are muxed so that I2S is not using those pins.
+ */
+void __init ep93xx_register_spi(struct ep93xx_spi_info *info,
+				struct spi_board_info *devices, int num)
+{
+	/*
+	 * When SPI is used, we need to make sure that I2S is muxed off from
+	 * SPI pins.
+	 */
+	ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2SONSSP);
+
+	ep93xx_spi_master_data = *info;
+	spi_register_board_info(devices, num);
+	platform_device_register(&ep93xx_spi_device);
+}
+
+/*************************************************************************
+ * EP93xx LEDs
+ *************************************************************************/
+static const struct gpio_led ep93xx_led_pins[] __initconst = {
+	{
+		.name	= "platform:grled",
+		.gpio	= EP93XX_GPIO_LINE_GRLED,
+	}, {
+		.name	= "platform:rdled",
+		.gpio	= EP93XX_GPIO_LINE_RDLED,
+	},
+};
+
+static const struct gpio_led_platform_data ep93xx_led_data __initconst = {
+	.num_leds	= ARRAY_SIZE(ep93xx_led_pins),
+	.leds		= ep93xx_led_pins,
+};
+
+/*************************************************************************
+ * EP93xx pwm peripheral handling
+ *************************************************************************/
+static struct resource ep93xx_pwm0_resource[] = {
+	DEFINE_RES_MEM(EP93XX_PWM_PHYS_BASE, 0x10),
+};
+
+static struct platform_device ep93xx_pwm0_device = {
+	.name		= "ep93xx-pwm",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(ep93xx_pwm0_resource),
+	.resource	= ep93xx_pwm0_resource,
+};
+
+static struct resource ep93xx_pwm1_resource[] = {
+	DEFINE_RES_MEM(EP93XX_PWM_PHYS_BASE + 0x20, 0x10),
+};
+
+static struct platform_device ep93xx_pwm1_device = {
+	.name		= "ep93xx-pwm",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(ep93xx_pwm1_resource),
+	.resource	= ep93xx_pwm1_resource,
+};
+
+void __init ep93xx_register_pwm(int pwm0, int pwm1)
+{
+	if (pwm0)
+		platform_device_register(&ep93xx_pwm0_device);
+
+	/* NOTE: EP9307 does not have PWMOUT1 (pin EGPIO14) */
+	if (pwm1)
+		platform_device_register(&ep93xx_pwm1_device);
+}
+
+int ep93xx_pwm_acquire_gpio(struct platform_device *pdev)
+{
+	int err;
+
+	if (pdev->id == 0) {
+		err = 0;
+	} else if (pdev->id == 1) {
+		err = gpio_request(EP93XX_GPIO_LINE_EGPIO14,
+				   dev_name(&pdev->dev));
+		if (err)
+			return err;
+		err = gpio_direction_output(EP93XX_GPIO_LINE_EGPIO14, 0);
+		if (err)
+			goto fail;
+
+		/* PWM 1 output on EGPIO[14] */
+		ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_PONG);
+	} else {
+		err = -ENODEV;
+	}
+
+	return err;
+
+fail:
+	gpio_free(EP93XX_GPIO_LINE_EGPIO14);
+	return err;
+}
+EXPORT_SYMBOL(ep93xx_pwm_acquire_gpio);
+
+void ep93xx_pwm_release_gpio(struct platform_device *pdev)
+{
+	if (pdev->id == 1) {
+		gpio_direction_input(EP93XX_GPIO_LINE_EGPIO14);
+		gpio_free(EP93XX_GPIO_LINE_EGPIO14);
+
+		/* EGPIO[14] used for GPIO */
+		ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_PONG);
+	}
+}
+EXPORT_SYMBOL(ep93xx_pwm_release_gpio);
+
+
+/*************************************************************************
+ * EP93xx video peripheral handling
+ *************************************************************************/
+static struct ep93xxfb_mach_info ep93xxfb_data;
+
+static struct resource ep93xx_fb_resource[] = {
+	DEFINE_RES_MEM(EP93XX_RASTER_PHYS_BASE, 0x800),
+};
+
+static struct platform_device ep93xx_fb_device = {
+	.name			= "ep93xx-fb",
+	.id			= -1,
+	.dev			= {
+		.platform_data		= &ep93xxfb_data,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.dma_mask		= &ep93xx_fb_device.dev.coherent_dma_mask,
+	},
+	.num_resources		= ARRAY_SIZE(ep93xx_fb_resource),
+	.resource		= ep93xx_fb_resource,
+};
+
+/* The backlight use a single register in the framebuffer's register space */
+#define EP93XX_RASTER_REG_BRIGHTNESS 0x20
+
+static struct resource ep93xx_bl_resources[] = {
+	DEFINE_RES_MEM(EP93XX_RASTER_PHYS_BASE +
+		       EP93XX_RASTER_REG_BRIGHTNESS, 0x04),
+};
+
+static struct platform_device ep93xx_bl_device = {
+	.name		= "ep93xx-bl",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(ep93xx_bl_resources),
+	.resource	= ep93xx_bl_resources,
+};
+
+/**
+ * ep93xx_register_fb - Register the framebuffer platform device.
+ * @data:	platform specific framebuffer configuration (__initdata)
+ */
+void __init ep93xx_register_fb(struct ep93xxfb_mach_info *data)
+{
+	ep93xxfb_data = *data;
+	platform_device_register(&ep93xx_fb_device);
+	platform_device_register(&ep93xx_bl_device);
+}
+
+
+/*************************************************************************
+ * EP93xx matrix keypad peripheral handling
+ *************************************************************************/
+static struct ep93xx_keypad_platform_data ep93xx_keypad_data;
+
+static struct resource ep93xx_keypad_resource[] = {
+	DEFINE_RES_MEM(EP93XX_KEY_MATRIX_PHYS_BASE, 0x0c),
+	DEFINE_RES_IRQ(IRQ_EP93XX_KEY),
+};
+
+static struct platform_device ep93xx_keypad_device = {
+	.name		= "ep93xx-keypad",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &ep93xx_keypad_data,
+	},
+	.num_resources	= ARRAY_SIZE(ep93xx_keypad_resource),
+	.resource	= ep93xx_keypad_resource,
+};
+
+/**
+ * ep93xx_register_keypad - Register the keypad platform device.
+ * @data:	platform specific keypad configuration (__initdata)
+ */
+void __init ep93xx_register_keypad(struct ep93xx_keypad_platform_data *data)
+{
+	ep93xx_keypad_data = *data;
+	platform_device_register(&ep93xx_keypad_device);
+}
+
+int ep93xx_keypad_acquire_gpio(struct platform_device *pdev)
+{
+	int err;
+	int i;
+
+	for (i = 0; i < 8; i++) {
+		err = gpio_request(EP93XX_GPIO_LINE_C(i), dev_name(&pdev->dev));
+		if (err)
+			goto fail_gpio_c;
+		err = gpio_request(EP93XX_GPIO_LINE_D(i), dev_name(&pdev->dev));
+		if (err)
+			goto fail_gpio_d;
+	}
+
+	/* Enable the keypad controller; GPIO ports C and D used for keypad */
+	ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_KEYS |
+				 EP93XX_SYSCON_DEVCFG_GONK);
+
+	return 0;
+
+fail_gpio_d:
+	gpio_free(EP93XX_GPIO_LINE_C(i));
+fail_gpio_c:
+	for (--i; i >= 0; --i) {
+		gpio_free(EP93XX_GPIO_LINE_C(i));
+		gpio_free(EP93XX_GPIO_LINE_D(i));
+	}
+	return err;
+}
+EXPORT_SYMBOL(ep93xx_keypad_acquire_gpio);
+
+void ep93xx_keypad_release_gpio(struct platform_device *pdev)
+{
+	int i;
+
+	for (i = 0; i < 8; i++) {
+		gpio_free(EP93XX_GPIO_LINE_C(i));
+		gpio_free(EP93XX_GPIO_LINE_D(i));
+	}
+
+	/* Disable the keypad controller; GPIO ports C and D used for GPIO */
+	ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_KEYS |
+			       EP93XX_SYSCON_DEVCFG_GONK);
+}
+EXPORT_SYMBOL(ep93xx_keypad_release_gpio);
+
+/*************************************************************************
+ * EP93xx I2S audio peripheral handling
+ *************************************************************************/
+static struct resource ep93xx_i2s_resource[] = {
+	DEFINE_RES_MEM(EP93XX_I2S_PHYS_BASE, 0x100),
+};
+
+static struct platform_device ep93xx_i2s_device = {
+	.name		= "ep93xx-i2s",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(ep93xx_i2s_resource),
+	.resource	= ep93xx_i2s_resource,
+};
+
+static struct platform_device ep93xx_pcm_device = {
+	.name		= "ep93xx-pcm-audio",
+	.id		= -1,
+};
+
+void __init ep93xx_register_i2s(void)
+{
+	platform_device_register(&ep93xx_i2s_device);
+	platform_device_register(&ep93xx_pcm_device);
+}
+
+#define EP93XX_SYSCON_DEVCFG_I2S_MASK	(EP93XX_SYSCON_DEVCFG_I2SONSSP | \
+					 EP93XX_SYSCON_DEVCFG_I2SONAC97)
+
+#define EP93XX_I2SCLKDIV_MASK		(EP93XX_SYSCON_I2SCLKDIV_ORIDE | \
+					 EP93XX_SYSCON_I2SCLKDIV_SPOL)
+
+int ep93xx_i2s_acquire(void)
+{
+	unsigned val;
+
+	ep93xx_devcfg_set_clear(EP93XX_SYSCON_DEVCFG_I2SONAC97,
+			EP93XX_SYSCON_DEVCFG_I2S_MASK);
+
+	/*
+	 * This is potentially racy with the clock api for i2s_mclk, sclk and 
+	 * lrclk. Since the i2s driver is the only user of those clocks we
+	 * rely on it to prevent parallel use of this function and the 
+	 * clock api for the i2s clocks.
+	 */
+	val = __raw_readl(EP93XX_SYSCON_I2SCLKDIV);
+	val &= ~EP93XX_I2SCLKDIV_MASK;
+	val |= EP93XX_SYSCON_I2SCLKDIV_ORIDE | EP93XX_SYSCON_I2SCLKDIV_SPOL;
+	ep93xx_syscon_swlocked_write(val, EP93XX_SYSCON_I2SCLKDIV);
+
+	return 0;
+}
+EXPORT_SYMBOL(ep93xx_i2s_acquire);
+
+void ep93xx_i2s_release(void)
+{
+	ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2S_MASK);
+}
+EXPORT_SYMBOL(ep93xx_i2s_release);
+
+/*************************************************************************
+ * EP93xx AC97 audio peripheral handling
+ *************************************************************************/
+static struct resource ep93xx_ac97_resources[] = {
+	DEFINE_RES_MEM(EP93XX_AAC_PHYS_BASE, 0xac),
+	DEFINE_RES_IRQ(IRQ_EP93XX_AACINTR),
+};
+
+static struct platform_device ep93xx_ac97_device = {
+	.name		= "ep93xx-ac97",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(ep93xx_ac97_resources),
+	.resource	= ep93xx_ac97_resources,
+};
+
+void __init ep93xx_register_ac97(void)
+{
+	/*
+	 * Make sure that the AC97 pins are not used by I2S.
+	 */
+	ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2SONAC97);
+
+	platform_device_register(&ep93xx_ac97_device);
+	platform_device_register(&ep93xx_pcm_device);
+}
+
+/*************************************************************************
+ * EP93xx Watchdog
+ *************************************************************************/
+static struct resource ep93xx_wdt_resources[] = {
+	DEFINE_RES_MEM(EP93XX_WATCHDOG_PHYS_BASE, 0x08),
+};
+
+static struct platform_device ep93xx_wdt_device = {
+	.name		= "ep93xx-wdt",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(ep93xx_wdt_resources),
+	.resource	= ep93xx_wdt_resources,
+};
+
+/*************************************************************************
+ * EP93xx IDE
+ *************************************************************************/
+static struct resource ep93xx_ide_resources[] = {
+	DEFINE_RES_MEM(EP93XX_IDE_PHYS_BASE, 0x38),
+	DEFINE_RES_IRQ(IRQ_EP93XX_EXT3),
+};
+
+static struct platform_device ep93xx_ide_device = {
+	.name		= "ep93xx-ide",
+	.id		= -1,
+	.dev		= {
+		.dma_mask		= &ep93xx_ide_device.dev.coherent_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+	.num_resources	= ARRAY_SIZE(ep93xx_ide_resources),
+	.resource	= ep93xx_ide_resources,
+};
+
+void __init ep93xx_register_ide(void)
+{
+	platform_device_register(&ep93xx_ide_device);
+}
+
+int ep93xx_ide_acquire_gpio(struct platform_device *pdev)
+{
+	int err;
+	int i;
+
+	err = gpio_request(EP93XX_GPIO_LINE_EGPIO2, dev_name(&pdev->dev));
+	if (err)
+		return err;
+	err = gpio_request(EP93XX_GPIO_LINE_EGPIO15, dev_name(&pdev->dev));
+	if (err)
+		goto fail_egpio15;
+	for (i = 2; i < 8; i++) {
+		err = gpio_request(EP93XX_GPIO_LINE_E(i), dev_name(&pdev->dev));
+		if (err)
+			goto fail_gpio_e;
+	}
+	for (i = 4; i < 8; i++) {
+		err = gpio_request(EP93XX_GPIO_LINE_G(i), dev_name(&pdev->dev));
+		if (err)
+			goto fail_gpio_g;
+	}
+	for (i = 0; i < 8; i++) {
+		err = gpio_request(EP93XX_GPIO_LINE_H(i), dev_name(&pdev->dev));
+		if (err)
+			goto fail_gpio_h;
+	}
+
+	/* GPIO ports E[7:2], G[7:4] and H used by IDE */
+	ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_EONIDE |
+				 EP93XX_SYSCON_DEVCFG_GONIDE |
+				 EP93XX_SYSCON_DEVCFG_HONIDE);
+	return 0;
+
+fail_gpio_h:
+	for (--i; i >= 0; --i)
+		gpio_free(EP93XX_GPIO_LINE_H(i));
+	i = 8;
+fail_gpio_g:
+	for (--i; i >= 4; --i)
+		gpio_free(EP93XX_GPIO_LINE_G(i));
+	i = 8;
+fail_gpio_e:
+	for (--i; i >= 2; --i)
+		gpio_free(EP93XX_GPIO_LINE_E(i));
+	gpio_free(EP93XX_GPIO_LINE_EGPIO15);
+fail_egpio15:
+	gpio_free(EP93XX_GPIO_LINE_EGPIO2);
+	return err;
+}
+EXPORT_SYMBOL(ep93xx_ide_acquire_gpio);
+
+void ep93xx_ide_release_gpio(struct platform_device *pdev)
+{
+	int i;
+
+	for (i = 2; i < 8; i++)
+		gpio_free(EP93XX_GPIO_LINE_E(i));
+	for (i = 4; i < 8; i++)
+		gpio_free(EP93XX_GPIO_LINE_G(i));
+	for (i = 0; i < 8; i++)
+		gpio_free(EP93XX_GPIO_LINE_H(i));
+	gpio_free(EP93XX_GPIO_LINE_EGPIO15);
+	gpio_free(EP93XX_GPIO_LINE_EGPIO2);
+
+
+	/* GPIO ports E[7:2], G[7:4] and H used by GPIO */
+	ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_EONIDE |
+			       EP93XX_SYSCON_DEVCFG_GONIDE |
+			       EP93XX_SYSCON_DEVCFG_HONIDE);
+}
+EXPORT_SYMBOL(ep93xx_ide_release_gpio);
+
+/*************************************************************************
+ * EP93xx ADC
+ *************************************************************************/
+static struct resource ep93xx_adc_resources[] = {
+	DEFINE_RES_MEM(EP93XX_ADC_PHYS_BASE, 0x28),
+	DEFINE_RES_IRQ(IRQ_EP93XX_TOUCH),
+};
+
+static struct platform_device ep93xx_adc_device = {
+	.name		= "ep93xx-adc",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(ep93xx_adc_resources),
+	.resource	= ep93xx_adc_resources,
+};
+
+void __init ep93xx_register_adc(void)
+{
+	/* Power up ADC, deactivate Touch Screen Controller */
+	ep93xx_devcfg_set_clear(EP93XX_SYSCON_DEVCFG_TIN,
+				EP93XX_SYSCON_DEVCFG_ADCPD);
+
+	platform_device_register(&ep93xx_adc_device);
+}
+
+/*************************************************************************
+ * EP93xx Security peripheral
+ *************************************************************************/
+
+/*
+ * The Maverick Key is 256 bits of micro fuses blown at the factory during
+ * manufacturing to uniquely identify a part.
+ *
+ * See: http://arm.cirrus.com/forum/viewtopic.php?t=486&highlight=maverick+key
+ */
+#define EP93XX_SECURITY_REG(x)		(EP93XX_SECURITY_BASE + (x))
+#define EP93XX_SECURITY_SECFLG		EP93XX_SECURITY_REG(0x2400)
+#define EP93XX_SECURITY_FUSEFLG		EP93XX_SECURITY_REG(0x2410)
+#define EP93XX_SECURITY_UNIQID		EP93XX_SECURITY_REG(0x2440)
+#define EP93XX_SECURITY_UNIQCHK		EP93XX_SECURITY_REG(0x2450)
+#define EP93XX_SECURITY_UNIQVAL		EP93XX_SECURITY_REG(0x2460)
+#define EP93XX_SECURITY_SECID1		EP93XX_SECURITY_REG(0x2500)
+#define EP93XX_SECURITY_SECID2		EP93XX_SECURITY_REG(0x2504)
+#define EP93XX_SECURITY_SECCHK1		EP93XX_SECURITY_REG(0x2520)
+#define EP93XX_SECURITY_SECCHK2		EP93XX_SECURITY_REG(0x2524)
+#define EP93XX_SECURITY_UNIQID2		EP93XX_SECURITY_REG(0x2700)
+#define EP93XX_SECURITY_UNIQID3		EP93XX_SECURITY_REG(0x2704)
+#define EP93XX_SECURITY_UNIQID4		EP93XX_SECURITY_REG(0x2708)
+#define EP93XX_SECURITY_UNIQID5		EP93XX_SECURITY_REG(0x270c)
+
+static char ep93xx_soc_id[33];
+
+static const char __init *ep93xx_get_soc_id(void)
+{
+	unsigned int id, id2, id3, id4, id5;
+
+	if (__raw_readl(EP93XX_SECURITY_UNIQVAL) != 1)
+		return "bad Hamming code";
+
+	id = __raw_readl(EP93XX_SECURITY_UNIQID);
+	id2 = __raw_readl(EP93XX_SECURITY_UNIQID2);
+	id3 = __raw_readl(EP93XX_SECURITY_UNIQID3);
+	id4 = __raw_readl(EP93XX_SECURITY_UNIQID4);
+	id5 = __raw_readl(EP93XX_SECURITY_UNIQID5);
+
+	if (id != id2)
+		return "invalid";
+
+	/* Toss the unique ID into the entropy pool */
+	add_device_randomness(&id2, 4);
+	add_device_randomness(&id3, 4);
+	add_device_randomness(&id4, 4);
+	add_device_randomness(&id5, 4);
+
+	snprintf(ep93xx_soc_id, sizeof(ep93xx_soc_id),
+		 "%08x%08x%08x%08x", id2, id3, id4, id5);
+
+	return ep93xx_soc_id;
+}
+
+static const char __init *ep93xx_get_soc_rev(void)
+{
+	int rev = ep93xx_chip_revision();
+
+	switch (rev) {
+	case EP93XX_CHIP_REV_D0:
+		return "D0";
+	case EP93XX_CHIP_REV_D1:
+		return "D1";
+	case EP93XX_CHIP_REV_E0:
+		return "E0";
+	case EP93XX_CHIP_REV_E1:
+		return "E1";
+	case EP93XX_CHIP_REV_E2:
+		return "E2";
+	default:
+		return "unknown";
+	}
+}
+
+static const char __init *ep93xx_get_machine_name(void)
+{
+	return kasprintf(GFP_KERNEL,"%s", machine_desc->name);
+}
+
+static struct device __init *ep93xx_init_soc(void)
+{
+	struct soc_device_attribute *soc_dev_attr;
+	struct soc_device *soc_dev;
+
+	soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+	if (!soc_dev_attr)
+		return NULL;
+
+	soc_dev_attr->machine = ep93xx_get_machine_name();
+	soc_dev_attr->family = "Cirrus Logic EP93xx";
+	soc_dev_attr->revision = ep93xx_get_soc_rev();
+	soc_dev_attr->soc_id = ep93xx_get_soc_id();
+
+	soc_dev = soc_device_register(soc_dev_attr);
+	if (IS_ERR(soc_dev)) {
+		kfree(soc_dev_attr->machine);
+		kfree(soc_dev_attr);
+		return NULL;
+	}
+
+	return soc_device_to_device(soc_dev);
+}
+
+struct device __init *ep93xx_init_devices(void)
+{
+	struct device *parent;
+
+	/* Disallow access to MaverickCrunch initially */
+	ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_CPENA);
+
+	/* Default all ports to GPIO */
+	ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_KEYS |
+			       EP93XX_SYSCON_DEVCFG_GONK |
+			       EP93XX_SYSCON_DEVCFG_EONIDE |
+			       EP93XX_SYSCON_DEVCFG_GONIDE |
+			       EP93XX_SYSCON_DEVCFG_HONIDE);
+
+	parent = ep93xx_init_soc();
+
+	/* Get the GPIO working early, other devices need it */
+	platform_device_register(&ep93xx_gpio_device);
+
+	amba_device_register(&uart1_device, &iomem_resource);
+	amba_device_register(&uart2_device, &iomem_resource);
+	amba_device_register(&uart3_device, &iomem_resource);
+
+	platform_device_register(&ep93xx_rtc_device);
+	platform_device_register(&ep93xx_ohci_device);
+	platform_device_register(&ep93xx_wdt_device);
+
+	gpio_led_register_device(-1, &ep93xx_led_data);
+
+	return parent;
+}
+
+void ep93xx_restart(enum reboot_mode mode, const char *cmd)
+{
+	/*
+	 * Set then clear the SWRST bit to initiate a software reset
+	 */
+	ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_SWRST);
+	ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_SWRST);
+
+	while (1)
+		;
+}
+
+void __init ep93xx_init_late(void)
+{
+	crunch_init();
+}
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/crunch-bits.S b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/crunch-bits.S
new file mode 100644
index 0000000..ee0be2a
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/crunch-bits.S
@@ -0,0 +1,313 @@
+/*
+ * arch/arm/kernel/crunch-bits.S
+ * Cirrus MaverickCrunch context switching and handling
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ *
+ * Shamelessly stolen from the iWMMXt code by Nicolas Pitre, which is
+ * 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/linkage.h>
+#include <asm/ptrace.h>
+#include <asm/thread_info.h>
+#include <asm/asm-offsets.h>
+#include <asm/assembler.h>
+#include <mach/ep93xx-regs.h>
+
+/*
+ * We can't use hex constants here due to a bug in gas.
+ */
+#define CRUNCH_MVDX0		0
+#define CRUNCH_MVDX1		8
+#define CRUNCH_MVDX2		16
+#define CRUNCH_MVDX3		24
+#define CRUNCH_MVDX4		32
+#define CRUNCH_MVDX5		40
+#define CRUNCH_MVDX6		48
+#define CRUNCH_MVDX7		56
+#define CRUNCH_MVDX8		64
+#define CRUNCH_MVDX9		72
+#define CRUNCH_MVDX10		80
+#define CRUNCH_MVDX11		88
+#define CRUNCH_MVDX12		96
+#define CRUNCH_MVDX13		104
+#define CRUNCH_MVDX14		112
+#define CRUNCH_MVDX15		120
+#define CRUNCH_MVAX0L		128
+#define CRUNCH_MVAX0M		132
+#define CRUNCH_MVAX0H		136
+#define CRUNCH_MVAX1L		140
+#define CRUNCH_MVAX1M		144
+#define CRUNCH_MVAX1H		148
+#define CRUNCH_MVAX2L		152
+#define CRUNCH_MVAX2M		156
+#define CRUNCH_MVAX2H		160
+#define CRUNCH_MVAX3L		164
+#define CRUNCH_MVAX3M		168
+#define CRUNCH_MVAX3H		172
+#define CRUNCH_DSPSC		176
+
+#define CRUNCH_SIZE		184
+
+	.text
+
+/*
+ * Lazy switching of crunch coprocessor context
+ *
+ * r10 = struct thread_info pointer
+ * r9  = ret_from_exception
+ * lr  = undefined instr exit
+ *
+ * called from prefetch exception handler with interrupts enabled
+ */
+ENTRY(crunch_task_enable)
+	inc_preempt_count r10, r3
+
+	ldr	r8, =(EP93XX_APB_VIRT_BASE + 0x00130000)	@ syscon addr
+
+	ldr	r1, [r8, #0x80]
+	tst	r1, #0x00800000			@ access to crunch enabled?
+	bne	2f				@ if so no business here
+	mov	r3, #0xaa			@ unlock syscon swlock
+	str	r3, [r8, #0xc0]
+	orr	r1, r1, #0x00800000		@ enable access to crunch
+	str	r1, [r8, #0x80]
+
+	ldr	r3, =crunch_owner
+	add	r0, r10, #TI_CRUNCH_STATE	@ get task crunch save area
+	ldr	r2, [sp, #60]			@ current task pc value
+	ldr	r1, [r3]			@ get current crunch owner
+	str	r0, [r3]			@ this task now owns crunch
+	sub	r2, r2, #4			@ adjust pc back
+	str	r2, [sp, #60]
+
+	ldr	r2, [r8, #0x80]
+	mov	r2, r2				@ flush out enable (@@@)
+
+	teq	r1, #0				@ test for last ownership
+	mov	lr, r9				@ normal exit from exception
+	beq	crunch_load			@ no owner, skip save
+
+crunch_save:
+	cfstr64		mvdx0, [r1, #CRUNCH_MVDX0]	@ save 64b registers
+	cfstr64		mvdx1, [r1, #CRUNCH_MVDX1]
+	cfstr64		mvdx2, [r1, #CRUNCH_MVDX2]
+	cfstr64		mvdx3, [r1, #CRUNCH_MVDX3]
+	cfstr64		mvdx4, [r1, #CRUNCH_MVDX4]
+	cfstr64		mvdx5, [r1, #CRUNCH_MVDX5]
+	cfstr64		mvdx6, [r1, #CRUNCH_MVDX6]
+	cfstr64		mvdx7, [r1, #CRUNCH_MVDX7]
+	cfstr64		mvdx8, [r1, #CRUNCH_MVDX8]
+	cfstr64		mvdx9, [r1, #CRUNCH_MVDX9]
+	cfstr64		mvdx10, [r1, #CRUNCH_MVDX10]
+	cfstr64		mvdx11, [r1, #CRUNCH_MVDX11]
+	cfstr64		mvdx12, [r1, #CRUNCH_MVDX12]
+	cfstr64		mvdx13, [r1, #CRUNCH_MVDX13]
+	cfstr64		mvdx14, [r1, #CRUNCH_MVDX14]
+	cfstr64		mvdx15, [r1, #CRUNCH_MVDX15]
+
+#ifdef __ARMEB__
+#error fix me for ARMEB
+#endif
+
+	cfmv32al	mvfx0, mvax0			@ save 72b accumulators
+	cfstr32		mvfx0, [r1, #CRUNCH_MVAX0L]
+	cfmv32am	mvfx0, mvax0
+	cfstr32		mvfx0, [r1, #CRUNCH_MVAX0M]
+	cfmv32ah	mvfx0, mvax0
+	cfstr32		mvfx0, [r1, #CRUNCH_MVAX0H]
+	cfmv32al	mvfx0, mvax1
+	cfstr32		mvfx0, [r1, #CRUNCH_MVAX1L]
+	cfmv32am	mvfx0, mvax1
+	cfstr32		mvfx0, [r1, #CRUNCH_MVAX1M]
+	cfmv32ah	mvfx0, mvax1
+	cfstr32		mvfx0, [r1, #CRUNCH_MVAX1H]
+	cfmv32al	mvfx0, mvax2
+	cfstr32		mvfx0, [r1, #CRUNCH_MVAX2L]
+	cfmv32am	mvfx0, mvax2
+	cfstr32		mvfx0, [r1, #CRUNCH_MVAX2M]
+	cfmv32ah	mvfx0, mvax2
+	cfstr32		mvfx0, [r1, #CRUNCH_MVAX2H]
+	cfmv32al	mvfx0, mvax3
+	cfstr32		mvfx0, [r1, #CRUNCH_MVAX3L]
+	cfmv32am	mvfx0, mvax3
+	cfstr32		mvfx0, [r1, #CRUNCH_MVAX3M]
+	cfmv32ah	mvfx0, mvax3
+	cfstr32		mvfx0, [r1, #CRUNCH_MVAX3H]
+
+	cfmv32sc	mvdx0, dspsc			@ save status word
+	cfstr64		mvdx0, [r1, #CRUNCH_DSPSC]
+
+	teq		r0, #0				@ anything to load?
+	cfldr64eq	mvdx0, [r1, #CRUNCH_MVDX0]	@ mvdx0 was clobbered
+	beq		1f
+
+crunch_load:
+	cfldr64		mvdx0, [r0, #CRUNCH_DSPSC]	@ load status word
+	cfmvsc32	dspsc, mvdx0
+
+	cfldr32		mvfx0, [r0, #CRUNCH_MVAX0L]	@ load 72b accumulators
+	cfmval32	mvax0, mvfx0
+	cfldr32		mvfx0, [r0, #CRUNCH_MVAX0M]
+	cfmvam32	mvax0, mvfx0
+	cfldr32		mvfx0, [r0, #CRUNCH_MVAX0H]
+	cfmvah32	mvax0, mvfx0
+	cfldr32		mvfx0, [r0, #CRUNCH_MVAX1L]
+	cfmval32	mvax1, mvfx0
+	cfldr32		mvfx0, [r0, #CRUNCH_MVAX1M]
+	cfmvam32	mvax1, mvfx0
+	cfldr32		mvfx0, [r0, #CRUNCH_MVAX1H]
+	cfmvah32	mvax1, mvfx0
+	cfldr32		mvfx0, [r0, #CRUNCH_MVAX2L]
+	cfmval32	mvax2, mvfx0
+	cfldr32		mvfx0, [r0, #CRUNCH_MVAX2M]
+	cfmvam32	mvax2, mvfx0
+	cfldr32		mvfx0, [r0, #CRUNCH_MVAX2H]
+	cfmvah32	mvax2, mvfx0
+	cfldr32		mvfx0, [r0, #CRUNCH_MVAX3L]
+	cfmval32	mvax3, mvfx0
+	cfldr32		mvfx0, [r0, #CRUNCH_MVAX3M]
+	cfmvam32	mvax3, mvfx0
+	cfldr32		mvfx0, [r0, #CRUNCH_MVAX3H]
+	cfmvah32	mvax3, mvfx0
+
+	cfldr64		mvdx0, [r0, #CRUNCH_MVDX0]	@ load 64b registers
+	cfldr64		mvdx1, [r0, #CRUNCH_MVDX1]
+	cfldr64		mvdx2, [r0, #CRUNCH_MVDX2]
+	cfldr64		mvdx3, [r0, #CRUNCH_MVDX3]
+	cfldr64		mvdx4, [r0, #CRUNCH_MVDX4]
+	cfldr64		mvdx5, [r0, #CRUNCH_MVDX5]
+	cfldr64		mvdx6, [r0, #CRUNCH_MVDX6]
+	cfldr64		mvdx7, [r0, #CRUNCH_MVDX7]
+	cfldr64		mvdx8, [r0, #CRUNCH_MVDX8]
+	cfldr64		mvdx9, [r0, #CRUNCH_MVDX9]
+	cfldr64		mvdx10, [r0, #CRUNCH_MVDX10]
+	cfldr64		mvdx11, [r0, #CRUNCH_MVDX11]
+	cfldr64		mvdx12, [r0, #CRUNCH_MVDX12]
+	cfldr64		mvdx13, [r0, #CRUNCH_MVDX13]
+	cfldr64		mvdx14, [r0, #CRUNCH_MVDX14]
+	cfldr64		mvdx15, [r0, #CRUNCH_MVDX15]
+
+1:
+#ifdef CONFIG_PREEMPT_COUNT
+	get_thread_info r10
+#endif
+2:	dec_preempt_count r10, r3
+	ret	lr
+
+/*
+ * Back up crunch regs to save area and disable access to them
+ * (mainly for gdb or sleep mode usage)
+ *
+ * r0 = struct thread_info pointer of target task or NULL for any
+ */
+ENTRY(crunch_task_disable)
+	stmfd	sp!, {r4, r5, lr}
+
+	mrs	ip, cpsr
+	orr	r2, ip, #PSR_I_BIT		@ disable interrupts
+	msr	cpsr_c, r2
+
+	ldr	r4, =(EP93XX_APB_VIRT_BASE + 0x00130000)	@ syscon addr
+
+	ldr	r3, =crunch_owner
+	add	r2, r0, #TI_CRUNCH_STATE	@ get task crunch save area
+	ldr	r1, [r3]			@ get current crunch owner
+	teq	r1, #0				@ any current owner?
+	beq	1f				@ no: quit
+	teq	r0, #0				@ any owner?
+	teqne	r1, r2				@ or specified one?
+	bne	1f				@ no: quit
+
+	ldr	r5, [r4, #0x80]			@ enable access to crunch
+	mov	r2, #0xaa
+	str	r2, [r4, #0xc0]
+	orr	r5, r5, #0x00800000
+	str	r5, [r4, #0x80]
+
+	mov	r0, #0				@ nothing to load
+	str	r0, [r3]			@ no more current owner
+	ldr	r2, [r4, #0x80]			@ flush out enable (@@@)
+	mov	r2, r2
+	bl	crunch_save
+
+	mov	r2, #0xaa			@ disable access to crunch
+	str	r2, [r4, #0xc0]
+	bic	r5, r5, #0x00800000
+	str	r5, [r4, #0x80]
+	ldr	r5, [r4, #0x80]			@ flush out enable (@@@)
+	mov	r5, r5
+
+1:	msr	cpsr_c, ip			@ restore interrupt mode
+	ldmfd	sp!, {r4, r5, pc}
+
+/*
+ * Copy crunch state to given memory address
+ *
+ * r0 = struct thread_info pointer of target task
+ * r1 = memory address where to store crunch state
+ *
+ * this is called mainly in the creation of signal stack frames
+ */
+ENTRY(crunch_task_copy)
+	mrs	ip, cpsr
+	orr	r2, ip, #PSR_I_BIT		@ disable interrupts
+	msr	cpsr_c, r2
+
+	ldr	r3, =crunch_owner
+	add	r2, r0, #TI_CRUNCH_STATE	@ get task crunch save area
+	ldr	r3, [r3]			@ get current crunch owner
+	teq	r2, r3				@ does this task own it...
+	beq	1f
+
+	@ current crunch values are in the task save area
+	msr	cpsr_c, ip			@ restore interrupt mode
+	mov	r0, r1
+	mov	r1, r2
+	mov	r2, #CRUNCH_SIZE
+	b	memcpy
+
+1:	@ this task owns crunch regs -- grab a copy from there
+	mov	r0, #0				@ nothing to load
+	mov	r3, lr				@ preserve return address
+	bl	crunch_save
+	msr	cpsr_c, ip			@ restore interrupt mode
+	ret	r3
+
+/*
+ * Restore crunch state from given memory address
+ *
+ * r0 = struct thread_info pointer of target task
+ * r1 = memory address where to get crunch state from
+ *
+ * this is used to restore crunch state when unwinding a signal stack frame
+ */
+ENTRY(crunch_task_restore)
+	mrs	ip, cpsr
+	orr	r2, ip, #PSR_I_BIT		@ disable interrupts
+	msr	cpsr_c, r2
+
+	ldr	r3, =crunch_owner
+	add	r2, r0, #TI_CRUNCH_STATE	@ get task crunch save area
+	ldr	r3, [r3]			@ get current crunch owner
+	teq	r2, r3				@ does this task own it...
+	beq	1f
+
+	@ this task doesn't own crunch regs -- use its save area
+	msr	cpsr_c, ip			@ restore interrupt mode
+	mov	r0, r2
+	mov	r2, #CRUNCH_SIZE
+	b	memcpy
+
+1:	@ this task owns crunch regs -- load them directly
+	mov	r0, r1
+	mov	r1, #0				@ nothing to save
+	mov	r3, lr				@ preserve return address
+	bl	crunch_load
+	msr	cpsr_c, ip			@ restore interrupt mode
+	ret	r3
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/crunch.c b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/crunch.c
new file mode 100644
index 0000000..a4a2ab9
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/crunch.c
@@ -0,0 +1,88 @@
+/*
+ * arch/arm/kernel/crunch.c
+ * Cirrus MaverickCrunch context switching and handling
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.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/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <asm/thread_notify.h>
+
+#include "soc.h"
+
+struct crunch_state *crunch_owner;
+
+void crunch_task_release(struct thread_info *thread)
+{
+	local_irq_disable();
+	if (crunch_owner == &thread->crunchstate)
+		crunch_owner = NULL;
+	local_irq_enable();
+}
+
+static int crunch_enabled(u32 devcfg)
+{
+	return !!(devcfg & EP93XX_SYSCON_DEVCFG_CPENA);
+}
+
+static int crunch_do(struct notifier_block *self, unsigned long cmd, void *t)
+{
+	struct thread_info *thread = (struct thread_info *)t;
+	struct crunch_state *crunch_state;
+	u32 devcfg;
+
+	crunch_state = &thread->crunchstate;
+
+	switch (cmd) {
+	case THREAD_NOTIFY_FLUSH:
+		memset(crunch_state, 0, sizeof(*crunch_state));
+
+		/*
+		 * FALLTHROUGH: Ensure we don't try to overwrite our newly
+		 * initialised state information on the first fault.
+		 */
+
+	case THREAD_NOTIFY_EXIT:
+		crunch_task_release(thread);
+		break;
+
+	case THREAD_NOTIFY_SWITCH:
+		devcfg = __raw_readl(EP93XX_SYSCON_DEVCFG);
+		if (crunch_enabled(devcfg) || crunch_owner == crunch_state) {
+			/*
+			 * We don't use ep93xx_syscon_swlocked_write() here
+			 * because we are on the context switch path and
+			 * preemption is already disabled.
+			 */
+			devcfg ^= EP93XX_SYSCON_DEVCFG_CPENA;
+			__raw_writel(0xaa, EP93XX_SYSCON_SWLOCK);
+			__raw_writel(devcfg, EP93XX_SYSCON_DEVCFG);
+		}
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block crunch_notifier_block = {
+	.notifier_call	= crunch_do,
+};
+
+int __init crunch_init(void)
+{
+	thread_register_notifier(&crunch_notifier_block);
+	elf_hwcap |= HWCAP_CRUNCH;
+
+	return 0;
+}
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/dma.c b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/dma.c
new file mode 100644
index 0000000..88a4c9b
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/dma.c
@@ -0,0 +1,118 @@
+/*
+ * arch/arm/mach-ep93xx/dma.c
+ *
+ * Platform support code for the EP93xx dmaengine driver.
+ *
+ * Copyright (C) 2011 Mika Westerberg
+ *
+ * This work is based on the original dma-m2p implementation with
+ * following copyrights:
+ *
+ *   Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ *   Copyright (C) 2006 Applied Data Systems
+ *   Copyright (C) 2009 Ryan Mallon <rmallon@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include <linux/platform_data/dma-ep93xx.h>
+#include <mach/hardware.h>
+
+#include "soc.h"
+
+#define DMA_CHANNEL(_name, _base, _irq) \
+	{ .name = (_name), .base = (_base), .irq = (_irq) }
+
+/*
+ * DMA M2P channels.
+ *
+ * On the EP93xx chip the following peripherals my be allocated to the 10
+ * Memory to Internal Peripheral (M2P) channels (5 transmit + 5 receive).
+ *
+ *	I2S	contains 3 Tx and 3 Rx DMA Channels
+ *	AAC	contains 3 Tx and 3 Rx DMA Channels
+ *	UART1	contains 1 Tx and 1 Rx DMA Channels
+ *	UART2	contains 1 Tx and 1 Rx DMA Channels
+ *	UART3	contains 1 Tx and 1 Rx DMA Channels
+ *	IrDA	contains 1 Tx and 1 Rx DMA Channels
+ *
+ * Registers are mapped statically in ep93xx_map_io().
+ */
+static struct ep93xx_dma_chan_data ep93xx_dma_m2p_channels[] = {
+	DMA_CHANNEL("m2p0", EP93XX_DMA_BASE + 0x0000, IRQ_EP93XX_DMAM2P0),
+	DMA_CHANNEL("m2p1", EP93XX_DMA_BASE + 0x0040, IRQ_EP93XX_DMAM2P1),
+	DMA_CHANNEL("m2p2", EP93XX_DMA_BASE + 0x0080, IRQ_EP93XX_DMAM2P2),
+	DMA_CHANNEL("m2p3", EP93XX_DMA_BASE + 0x00c0, IRQ_EP93XX_DMAM2P3),
+	DMA_CHANNEL("m2p4", EP93XX_DMA_BASE + 0x0240, IRQ_EP93XX_DMAM2P4),
+	DMA_CHANNEL("m2p5", EP93XX_DMA_BASE + 0x0200, IRQ_EP93XX_DMAM2P5),
+	DMA_CHANNEL("m2p6", EP93XX_DMA_BASE + 0x02c0, IRQ_EP93XX_DMAM2P6),
+	DMA_CHANNEL("m2p7", EP93XX_DMA_BASE + 0x0280, IRQ_EP93XX_DMAM2P7),
+	DMA_CHANNEL("m2p8", EP93XX_DMA_BASE + 0x0340, IRQ_EP93XX_DMAM2P8),
+	DMA_CHANNEL("m2p9", EP93XX_DMA_BASE + 0x0300, IRQ_EP93XX_DMAM2P9),
+};
+
+static struct ep93xx_dma_platform_data ep93xx_dma_m2p_data = {
+	.channels		= ep93xx_dma_m2p_channels,
+	.num_channels		= ARRAY_SIZE(ep93xx_dma_m2p_channels),
+};
+
+static u64 ep93xx_dma_m2p_mask = DMA_BIT_MASK(32);
+
+static struct platform_device ep93xx_dma_m2p_device = {
+	.name			= "ep93xx-dma-m2p",
+	.id			= -1,
+	.dev			= {
+		.platform_data		= &ep93xx_dma_m2p_data,
+		.dma_mask		= &ep93xx_dma_m2p_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+/*
+ * DMA M2M channels.
+ *
+ * There are 2 M2M channels which support memcpy/memset and in addition simple
+ * hardware requests from/to SSP and IDE. We do not implement an external
+ * hardware requests.
+ *
+ * Registers are mapped statically in ep93xx_map_io().
+ */
+static struct ep93xx_dma_chan_data ep93xx_dma_m2m_channels[] = {
+	DMA_CHANNEL("m2m0", EP93XX_DMA_BASE + 0x0100, IRQ_EP93XX_DMAM2M0),
+	DMA_CHANNEL("m2m1", EP93XX_DMA_BASE + 0x0140, IRQ_EP93XX_DMAM2M1),
+};
+
+static struct ep93xx_dma_platform_data ep93xx_dma_m2m_data = {
+	.channels		= ep93xx_dma_m2m_channels,
+	.num_channels		= ARRAY_SIZE(ep93xx_dma_m2m_channels),
+};
+
+static u64 ep93xx_dma_m2m_mask = DMA_BIT_MASK(32);
+
+static struct platform_device ep93xx_dma_m2m_device = {
+	.name			= "ep93xx-dma-m2m",
+	.id			= -1,
+	.dev			= {
+		.platform_data		= &ep93xx_dma_m2m_data,
+		.dma_mask		= &ep93xx_dma_m2m_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+static int __init ep93xx_dma_init(void)
+{
+	platform_device_register(&ep93xx_dma_m2p_device);
+	platform_device_register(&ep93xx_dma_m2m_device);
+	return 0;
+}
+arch_initcall(ep93xx_dma_init);
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/edb93xx.c b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/edb93xx.c
new file mode 100644
index 0000000..7a7f280
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/edb93xx.c
@@ -0,0 +1,354 @@
+/*
+ * arch/arm/mach-ep93xx/edb93xx.c
+ * Cirrus Logic EDB93xx Development Board support.
+ *
+ * EDB93XX, EDB9301, EDB9307A
+ * Copyright (C) 2008-2009 H Hartley Sweeten <hsweeten@visionengravers.com>
+ *
+ * EDB9302
+ * Copyright (C) 2006 George Kashperko <george@chas.com.ua>
+ *
+ * EDB9302A, EDB9315, EDB9315A
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ *
+ * EDB9307
+ * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org>
+ *
+ * EDB9312
+ * Copyright (C) 2006 Infosys Technologies Limited
+ *                    Toufeeq Hussain <toufeeq_hussain@infosys.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
+#include <linux/spi/spi.h>
+
+#include <sound/cs4271.h>
+
+#include <mach/hardware.h>
+#include <linux/platform_data/video-ep93xx.h>
+#include <linux/platform_data/spi-ep93xx.h>
+#include <mach/gpio-ep93xx.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include "soc.h"
+
+static void __init edb93xx_register_flash(void)
+{
+	if (machine_is_edb9307() || machine_is_edb9312() ||
+	    machine_is_edb9315()) {
+		ep93xx_register_flash(4, EP93XX_CS6_PHYS_BASE, SZ_32M);
+	} else {
+		ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_16M);
+	}
+}
+
+static struct ep93xx_eth_data __initdata edb93xx_eth_data = {
+	.phy_id		= 1,
+};
+
+
+/*************************************************************************
+ * EDB93xx i2c peripheral handling
+ *************************************************************************/
+static struct i2c_gpio_platform_data __initdata edb93xx_i2c_gpio_data = {
+	.sda_pin		= EP93XX_GPIO_LINE_EEDAT,
+	.sda_is_open_drain	= 0,
+	.scl_pin		= EP93XX_GPIO_LINE_EECLK,
+	.scl_is_open_drain	= 0,
+	.udelay			= 0,	/* default to 100 kHz */
+	.timeout		= 0,	/* default to 100 ms */
+};
+
+static struct i2c_board_info __initdata edb93xxa_i2c_board_info[] = {
+	{
+		I2C_BOARD_INFO("isl1208", 0x6f),
+	},
+};
+
+static struct i2c_board_info __initdata edb93xx_i2c_board_info[] = {
+	{
+		I2C_BOARD_INFO("ds1337", 0x68),
+	},
+};
+
+static void __init edb93xx_register_i2c(void)
+{
+	if (machine_is_edb9302a() || machine_is_edb9307a() ||
+	    machine_is_edb9315a()) {
+		ep93xx_register_i2c(&edb93xx_i2c_gpio_data,
+				    edb93xxa_i2c_board_info,
+				    ARRAY_SIZE(edb93xxa_i2c_board_info));
+	} else if (machine_is_edb9302() || machine_is_edb9307()
+		|| machine_is_edb9312() || machine_is_edb9315()) {
+		ep93xx_register_i2c(&edb93xx_i2c_gpio_data,
+				    edb93xx_i2c_board_info,
+				    ARRAY_SIZE(edb93xx_i2c_board_info));
+	}
+}
+
+
+/*************************************************************************
+ * EDB93xx SPI peripheral handling
+ *************************************************************************/
+static struct cs4271_platform_data edb93xx_cs4271_data = {
+	.gpio_nreset	= -EINVAL,	/* filled in later */
+};
+
+static struct spi_board_info edb93xx_spi_board_info[] __initdata = {
+	{
+		.modalias		= "cs4271",
+		.platform_data		= &edb93xx_cs4271_data,
+		.max_speed_hz		= 6000000,
+		.bus_num		= 0,
+		.chip_select		= 0,
+		.mode			= SPI_MODE_3,
+	},
+};
+
+static int edb93xx_spi_chipselects[] __initdata = {
+	EP93XX_GPIO_LINE_EGPIO6,
+};
+
+static struct ep93xx_spi_info edb93xx_spi_info __initdata = {
+	.chipselect	= edb93xx_spi_chipselects,
+	.num_chipselect	= ARRAY_SIZE(edb93xx_spi_chipselects),
+};
+
+static void __init edb93xx_register_spi(void)
+{
+	if (machine_is_edb9301() || machine_is_edb9302())
+		edb93xx_cs4271_data.gpio_nreset = EP93XX_GPIO_LINE_EGPIO1;
+	else if (machine_is_edb9302a() || machine_is_edb9307a())
+		edb93xx_cs4271_data.gpio_nreset = EP93XX_GPIO_LINE_H(2);
+	else if (machine_is_edb9315a())
+		edb93xx_cs4271_data.gpio_nreset = EP93XX_GPIO_LINE_EGPIO14;
+
+	ep93xx_register_spi(&edb93xx_spi_info, edb93xx_spi_board_info,
+			    ARRAY_SIZE(edb93xx_spi_board_info));
+}
+
+
+/*************************************************************************
+ * EDB93xx I2S
+ *************************************************************************/
+static struct platform_device edb93xx_audio_device = {
+	.name		= "edb93xx-audio",
+	.id		= -1,
+};
+
+static int __init edb93xx_has_audio(void)
+{
+	return (machine_is_edb9301() || machine_is_edb9302() ||
+		machine_is_edb9302a() || machine_is_edb9307a() ||
+		machine_is_edb9315a());
+}
+
+static void __init edb93xx_register_i2s(void)
+{
+	if (edb93xx_has_audio()) {
+		ep93xx_register_i2s();
+		platform_device_register(&edb93xx_audio_device);
+	}
+}
+
+
+/*************************************************************************
+ * EDB93xx pwm
+ *************************************************************************/
+static void __init edb93xx_register_pwm(void)
+{
+	if (machine_is_edb9301() ||
+	    machine_is_edb9302() || machine_is_edb9302a()) {
+		/* EP9301 and EP9302 only have pwm.1 (EGPIO14) */
+		ep93xx_register_pwm(0, 1);
+	} else if (machine_is_edb9307() || machine_is_edb9307a()) {
+		/* EP9307 only has pwm.0 (PWMOUT) */
+		ep93xx_register_pwm(1, 0);
+	} else {
+		/* EP9312 and EP9315 have both */
+		ep93xx_register_pwm(1, 1);
+	}
+}
+
+
+/*************************************************************************
+ * EDB93xx framebuffer
+ *************************************************************************/
+static struct ep93xxfb_mach_info __initdata edb93xxfb_info = {
+	.flags		= 0,
+};
+
+static int __init edb93xx_has_fb(void)
+{
+	/* These platforms have an ep93xx with video capability */
+	return machine_is_edb9307() || machine_is_edb9307a() ||
+	       machine_is_edb9312() || machine_is_edb9315() ||
+	       machine_is_edb9315a();
+}
+
+static void __init edb93xx_register_fb(void)
+{
+	if (!edb93xx_has_fb())
+		return;
+
+	if (machine_is_edb9307a() || machine_is_edb9315a())
+		edb93xxfb_info.flags |= EP93XXFB_USE_SDCSN0;
+	else
+		edb93xxfb_info.flags |= EP93XXFB_USE_SDCSN3;
+
+	ep93xx_register_fb(&edb93xxfb_info);
+}
+
+
+/*************************************************************************
+ * EDB93xx IDE
+ *************************************************************************/
+static int __init edb93xx_has_ide(void)
+{
+	/*
+	 * Although EDB9312 and EDB9315 do have IDE capability, they have
+	 * INTRQ line wired as pull-up, which makes using IDE interface
+	 * problematic.
+	 */
+	return machine_is_edb9312() || machine_is_edb9315() ||
+	       machine_is_edb9315a();
+}
+
+static void __init edb93xx_register_ide(void)
+{
+	if (!edb93xx_has_ide())
+		return;
+
+	ep93xx_register_ide();
+}
+
+
+static void __init edb93xx_init_machine(void)
+{
+	ep93xx_init_devices();
+	edb93xx_register_flash();
+	ep93xx_register_eth(&edb93xx_eth_data, 1);
+	edb93xx_register_i2c();
+	edb93xx_register_spi();
+	edb93xx_register_i2s();
+	edb93xx_register_pwm();
+	edb93xx_register_fb();
+	edb93xx_register_ide();
+	ep93xx_register_adc();
+}
+
+
+#ifdef CONFIG_MACH_EDB9301
+MACHINE_START(EDB9301, "Cirrus Logic EDB9301 Evaluation Board")
+	/* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
+	.atag_offset	= 0x100,
+	.map_io		= ep93xx_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.init_time	= ep93xx_timer_init,
+	.init_machine	= edb93xx_init_machine,
+	.init_late	= ep93xx_init_late,
+	.restart	= ep93xx_restart,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_EDB9302
+MACHINE_START(EDB9302, "Cirrus Logic EDB9302 Evaluation Board")
+	/* Maintainer: George Kashperko <george@chas.com.ua> */
+	.atag_offset	= 0x100,
+	.map_io		= ep93xx_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.init_time	= ep93xx_timer_init,
+	.init_machine	= edb93xx_init_machine,
+	.init_late	= ep93xx_init_late,
+	.restart	= ep93xx_restart,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_EDB9302A
+MACHINE_START(EDB9302A, "Cirrus Logic EDB9302A Evaluation Board")
+	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
+	.atag_offset	= 0x100,
+	.map_io		= ep93xx_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.init_time	= ep93xx_timer_init,
+	.init_machine	= edb93xx_init_machine,
+	.init_late	= ep93xx_init_late,
+	.restart	= ep93xx_restart,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_EDB9307
+MACHINE_START(EDB9307, "Cirrus Logic EDB9307 Evaluation Board")
+	/* Maintainer: Herbert Valerio Riedel <hvr@gnu.org> */
+	.atag_offset	= 0x100,
+	.map_io		= ep93xx_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.init_time	= ep93xx_timer_init,
+	.init_machine	= edb93xx_init_machine,
+	.init_late	= ep93xx_init_late,
+	.restart	= ep93xx_restart,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_EDB9307A
+MACHINE_START(EDB9307A, "Cirrus Logic EDB9307A Evaluation Board")
+	/* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
+	.atag_offset	= 0x100,
+	.map_io		= ep93xx_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.init_time	= ep93xx_timer_init,
+	.init_machine	= edb93xx_init_machine,
+	.init_late	= ep93xx_init_late,
+	.restart	= ep93xx_restart,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_EDB9312
+MACHINE_START(EDB9312, "Cirrus Logic EDB9312 Evaluation Board")
+	/* Maintainer: Toufeeq Hussain <toufeeq_hussain@infosys.com> */
+	.atag_offset	= 0x100,
+	.map_io		= ep93xx_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.init_time	= ep93xx_timer_init,
+	.init_machine	= edb93xx_init_machine,
+	.init_late	= ep93xx_init_late,
+	.restart	= ep93xx_restart,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_EDB9315
+MACHINE_START(EDB9315, "Cirrus Logic EDB9315 Evaluation Board")
+	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
+	.atag_offset	= 0x100,
+	.map_io		= ep93xx_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.init_time	= ep93xx_timer_init,
+	.init_machine	= edb93xx_init_machine,
+	.init_late	= ep93xx_init_late,
+	.restart	= ep93xx_restart,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_EDB9315A
+MACHINE_START(EDB9315A, "Cirrus Logic EDB9315A Evaluation Board")
+	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
+	.atag_offset	= 0x100,
+	.map_io		= ep93xx_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.init_time	= ep93xx_timer_init,
+	.init_machine	= edb93xx_init_machine,
+	.init_late	= ep93xx_init_late,
+	.restart	= ep93xx_restart,
+MACHINE_END
+#endif
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/gesbc9312.c b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/gesbc9312.c
new file mode 100644
index 0000000..0cca5b1
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/gesbc9312.c
@@ -0,0 +1,45 @@
+/*
+ * arch/arm/mach-ep93xx/gesbc9312.c
+ * Glomation GESBC-9312-sx support.
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/sizes.h>
+
+#include <mach/hardware.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include "soc.h"
+
+static struct ep93xx_eth_data __initdata gesbc9312_eth_data = {
+	.phy_id		= 1,
+};
+
+static void __init gesbc9312_init_machine(void)
+{
+	ep93xx_init_devices();
+	ep93xx_register_flash(4, EP93XX_CS6_PHYS_BASE, SZ_8M);
+	ep93xx_register_eth(&gesbc9312_eth_data, 0);
+}
+
+MACHINE_START(GESBC9312, "Glomation GESBC-9312-sx")
+	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
+	.atag_offset	= 0x100,
+	.map_io		= ep93xx_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.init_time	= ep93xx_timer_init,
+	.init_machine	= gesbc9312_init_machine,
+	.init_late	= ep93xx_init_late,
+	.restart	= ep93xx_restart,
+MACHINE_END
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
new file mode 100644
index 0000000..6839ea0
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
+ */
+
+#ifndef __ASM_ARCH_EP93XX_REGS_H
+#define __ASM_ARCH_EP93XX_REGS_H
+
+/*
+ * EP93xx linux memory map:
+ *
+ * virt		phys		size
+ * fe800000			5M		per-platform mappings
+ * fed00000	80800000	2M		APB
+ * fef00000	80000000	1M		AHB
+ */
+
+#define EP93XX_AHB_PHYS_BASE		0x80000000
+#define EP93XX_AHB_VIRT_BASE		0xfef00000
+#define EP93XX_AHB_SIZE			0x00100000
+
+#define EP93XX_AHB_PHYS(x)		(EP93XX_AHB_PHYS_BASE + (x))
+#define EP93XX_AHB_IOMEM(x)		IOMEM(EP93XX_AHB_VIRT_BASE + (x))
+
+#define EP93XX_APB_PHYS_BASE		0x80800000
+#define EP93XX_APB_VIRT_BASE		0xfed00000
+#define EP93XX_APB_SIZE			0x00200000
+
+#define EP93XX_APB_PHYS(x)		(EP93XX_APB_PHYS_BASE + (x))
+#define EP93XX_APB_IOMEM(x)		IOMEM(EP93XX_APB_VIRT_BASE + (x))
+
+/* APB UARTs */
+#define EP93XX_UART1_PHYS_BASE		EP93XX_APB_PHYS(0x000c0000)
+#define EP93XX_UART1_BASE		EP93XX_APB_IOMEM(0x000c0000)
+
+#define EP93XX_UART2_PHYS_BASE		EP93XX_APB_PHYS(0x000d0000)
+#define EP93XX_UART2_BASE		EP93XX_APB_IOMEM(0x000d0000)
+
+#define EP93XX_UART3_PHYS_BASE		EP93XX_APB_PHYS(0x000e0000)
+#define EP93XX_UART3_BASE		EP93XX_APB_IOMEM(0x000e0000)
+
+#endif
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h
new file mode 100644
index 0000000..242af4a
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/include/mach/gpio-ep93xx.h
@@ -0,0 +1,111 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Include file for the EP93XX GPIO controller machine specifics */
+
+#ifndef __GPIO_EP93XX_H
+#define __GPIO_EP93XX_H
+
+#include <mach/ep93xx-regs.h>
+
+#define EP93XX_GPIO_PHYS_BASE		EP93XX_APB_PHYS(0x00040000)
+#define EP93XX_GPIO_BASE		EP93XX_APB_IOMEM(0x00040000)
+#define EP93XX_GPIO_REG(x)		(EP93XX_GPIO_BASE + (x))
+#define EP93XX_GPIO_F_INT_STATUS	EP93XX_GPIO_REG(0x5c)
+#define EP93XX_GPIO_A_INT_STATUS	EP93XX_GPIO_REG(0xa0)
+#define EP93XX_GPIO_B_INT_STATUS	EP93XX_GPIO_REG(0xbc)
+#define EP93XX_GPIO_EEDRIVE		EP93XX_GPIO_REG(0xc8)
+
+/* GPIO port A.  */
+#define EP93XX_GPIO_LINE_A(x)		((x) + 0)
+#define EP93XX_GPIO_LINE_EGPIO0		EP93XX_GPIO_LINE_A(0)
+#define EP93XX_GPIO_LINE_EGPIO1		EP93XX_GPIO_LINE_A(1)
+#define EP93XX_GPIO_LINE_EGPIO2		EP93XX_GPIO_LINE_A(2)
+#define EP93XX_GPIO_LINE_EGPIO3		EP93XX_GPIO_LINE_A(3)
+#define EP93XX_GPIO_LINE_EGPIO4		EP93XX_GPIO_LINE_A(4)
+#define EP93XX_GPIO_LINE_EGPIO5		EP93XX_GPIO_LINE_A(5)
+#define EP93XX_GPIO_LINE_EGPIO6		EP93XX_GPIO_LINE_A(6)
+#define EP93XX_GPIO_LINE_EGPIO7		EP93XX_GPIO_LINE_A(7)
+
+/* GPIO port B.  */
+#define EP93XX_GPIO_LINE_B(x)		((x) + 8)
+#define EP93XX_GPIO_LINE_EGPIO8		EP93XX_GPIO_LINE_B(0)
+#define EP93XX_GPIO_LINE_EGPIO9		EP93XX_GPIO_LINE_B(1)
+#define EP93XX_GPIO_LINE_EGPIO10	EP93XX_GPIO_LINE_B(2)
+#define EP93XX_GPIO_LINE_EGPIO11	EP93XX_GPIO_LINE_B(3)
+#define EP93XX_GPIO_LINE_EGPIO12	EP93XX_GPIO_LINE_B(4)
+#define EP93XX_GPIO_LINE_EGPIO13	EP93XX_GPIO_LINE_B(5)
+#define EP93XX_GPIO_LINE_EGPIO14	EP93XX_GPIO_LINE_B(6)
+#define EP93XX_GPIO_LINE_EGPIO15	EP93XX_GPIO_LINE_B(7)
+
+/* GPIO port C.  */
+#define EP93XX_GPIO_LINE_C(x)		((x) + 40)
+#define EP93XX_GPIO_LINE_ROW0		EP93XX_GPIO_LINE_C(0)
+#define EP93XX_GPIO_LINE_ROW1		EP93XX_GPIO_LINE_C(1)
+#define EP93XX_GPIO_LINE_ROW2		EP93XX_GPIO_LINE_C(2)
+#define EP93XX_GPIO_LINE_ROW3		EP93XX_GPIO_LINE_C(3)
+#define EP93XX_GPIO_LINE_ROW4		EP93XX_GPIO_LINE_C(4)
+#define EP93XX_GPIO_LINE_ROW5		EP93XX_GPIO_LINE_C(5)
+#define EP93XX_GPIO_LINE_ROW6		EP93XX_GPIO_LINE_C(6)
+#define EP93XX_GPIO_LINE_ROW7		EP93XX_GPIO_LINE_C(7)
+
+/* GPIO port D.  */
+#define EP93XX_GPIO_LINE_D(x)		((x) + 24)
+#define EP93XX_GPIO_LINE_COL0		EP93XX_GPIO_LINE_D(0)
+#define EP93XX_GPIO_LINE_COL1		EP93XX_GPIO_LINE_D(1)
+#define EP93XX_GPIO_LINE_COL2		EP93XX_GPIO_LINE_D(2)
+#define EP93XX_GPIO_LINE_COL3		EP93XX_GPIO_LINE_D(3)
+#define EP93XX_GPIO_LINE_COL4		EP93XX_GPIO_LINE_D(4)
+#define EP93XX_GPIO_LINE_COL5		EP93XX_GPIO_LINE_D(5)
+#define EP93XX_GPIO_LINE_COL6		EP93XX_GPIO_LINE_D(6)
+#define EP93XX_GPIO_LINE_COL7		EP93XX_GPIO_LINE_D(7)
+
+/* GPIO port E.  */
+#define EP93XX_GPIO_LINE_E(x)		((x) + 32)
+#define EP93XX_GPIO_LINE_GRLED		EP93XX_GPIO_LINE_E(0)
+#define EP93XX_GPIO_LINE_RDLED		EP93XX_GPIO_LINE_E(1)
+#define EP93XX_GPIO_LINE_DIORn		EP93XX_GPIO_LINE_E(2)
+#define EP93XX_GPIO_LINE_IDECS1n	EP93XX_GPIO_LINE_E(3)
+#define EP93XX_GPIO_LINE_IDECS2n	EP93XX_GPIO_LINE_E(4)
+#define EP93XX_GPIO_LINE_IDEDA0		EP93XX_GPIO_LINE_E(5)
+#define EP93XX_GPIO_LINE_IDEDA1		EP93XX_GPIO_LINE_E(6)
+#define EP93XX_GPIO_LINE_IDEDA2		EP93XX_GPIO_LINE_E(7)
+
+/* GPIO port F.  */
+#define EP93XX_GPIO_LINE_F(x)		((x) + 16)
+#define EP93XX_GPIO_LINE_WP		EP93XX_GPIO_LINE_F(0)
+#define EP93XX_GPIO_LINE_MCCD1		EP93XX_GPIO_LINE_F(1)
+#define EP93XX_GPIO_LINE_MCCD2		EP93XX_GPIO_LINE_F(2)
+#define EP93XX_GPIO_LINE_MCBVD1		EP93XX_GPIO_LINE_F(3)
+#define EP93XX_GPIO_LINE_MCBVD2		EP93XX_GPIO_LINE_F(4)
+#define EP93XX_GPIO_LINE_VS1		EP93XX_GPIO_LINE_F(5)
+#define EP93XX_GPIO_LINE_READY		EP93XX_GPIO_LINE_F(6)
+#define EP93XX_GPIO_LINE_VS2		EP93XX_GPIO_LINE_F(7)
+
+/* GPIO port G.  */
+#define EP93XX_GPIO_LINE_G(x)		((x) + 48)
+#define EP93XX_GPIO_LINE_EECLK		EP93XX_GPIO_LINE_G(0)
+#define EP93XX_GPIO_LINE_EEDAT		EP93XX_GPIO_LINE_G(1)
+#define EP93XX_GPIO_LINE_SLA0		EP93XX_GPIO_LINE_G(2)
+#define EP93XX_GPIO_LINE_SLA1		EP93XX_GPIO_LINE_G(3)
+#define EP93XX_GPIO_LINE_DD12		EP93XX_GPIO_LINE_G(4)
+#define EP93XX_GPIO_LINE_DD13		EP93XX_GPIO_LINE_G(5)
+#define EP93XX_GPIO_LINE_DD14		EP93XX_GPIO_LINE_G(6)
+#define EP93XX_GPIO_LINE_DD15		EP93XX_GPIO_LINE_G(7)
+
+/* GPIO port H.  */
+#define EP93XX_GPIO_LINE_H(x)		((x) + 56)
+#define EP93XX_GPIO_LINE_DD0		EP93XX_GPIO_LINE_H(0)
+#define EP93XX_GPIO_LINE_DD1		EP93XX_GPIO_LINE_H(1)
+#define EP93XX_GPIO_LINE_DD2		EP93XX_GPIO_LINE_H(2)
+#define EP93XX_GPIO_LINE_DD3		EP93XX_GPIO_LINE_H(3)
+#define EP93XX_GPIO_LINE_DD4		EP93XX_GPIO_LINE_H(4)
+#define EP93XX_GPIO_LINE_DD5		EP93XX_GPIO_LINE_H(5)
+#define EP93XX_GPIO_LINE_DD6		EP93XX_GPIO_LINE_H(6)
+#define EP93XX_GPIO_LINE_DD7		EP93XX_GPIO_LINE_H(7)
+
+/* maximum value for gpio line identifiers */
+#define EP93XX_GPIO_LINE_MAX		EP93XX_GPIO_LINE_H(7)
+
+/* maximum value for irq capable line identifiers */
+#define EP93XX_GPIO_LINE_MAX_IRQ	EP93XX_GPIO_LINE_F(7)
+
+#endif /* __GPIO_EP93XX_H */
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/include/mach/hardware.h b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/include/mach/hardware.h
new file mode 100644
index 0000000..8938906
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/include/mach/hardware.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * arch/arm/mach-ep93xx/include/mach/hardware.h
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <mach/platform.h>
+
+/*
+ * The EP93xx has two external crystal oscillators.  To generate the
+ * required high-frequency clocks, the processor uses two phase-locked-
+ * loops (PLLs) to multiply the incoming external clock signal to much
+ * higher frequencies that are then divided down by programmable dividers
+ * to produce the needed clocks.  The PLLs operate independently of one
+ * another.
+ */
+#define EP93XX_EXT_CLK_RATE	14745600
+#define EP93XX_EXT_RTC_RATE	32768
+
+#define EP93XX_KEYTCHCLK_DIV4	(EP93XX_EXT_CLK_RATE / 4)
+#define EP93XX_KEYTCHCLK_DIV16	(EP93XX_EXT_CLK_RATE / 16)
+
+#endif
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/include/mach/irqs.h b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/include/mach/irqs.h
new file mode 100644
index 0000000..244daf8
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/include/mach/irqs.h
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * arch/arm/mach-ep93xx/include/mach/irqs.h
+ */
+
+#ifndef __ASM_ARCH_IRQS_H
+#define __ASM_ARCH_IRQS_H
+
+#define IRQ_EP93XX_COMMRX		2
+#define IRQ_EP93XX_COMMTX		3
+#define IRQ_EP93XX_TIMER1		4
+#define IRQ_EP93XX_TIMER2		5
+#define IRQ_EP93XX_AACINTR		6
+#define IRQ_EP93XX_DMAM2P0		7
+#define IRQ_EP93XX_DMAM2P1		8
+#define IRQ_EP93XX_DMAM2P2		9
+#define IRQ_EP93XX_DMAM2P3		10
+#define IRQ_EP93XX_DMAM2P4		11
+#define IRQ_EP93XX_DMAM2P5		12
+#define IRQ_EP93XX_DMAM2P6		13
+#define IRQ_EP93XX_DMAM2P7		14
+#define IRQ_EP93XX_DMAM2P8		15
+#define IRQ_EP93XX_DMAM2P9		16
+#define IRQ_EP93XX_DMAM2M0		17
+#define IRQ_EP93XX_DMAM2M1		18
+#define IRQ_EP93XX_GPIO0MUX		19
+#define IRQ_EP93XX_GPIO1MUX		20
+#define IRQ_EP93XX_GPIO2MUX		21
+#define IRQ_EP93XX_GPIO3MUX		22
+#define IRQ_EP93XX_UART1RX		23
+#define IRQ_EP93XX_UART1TX		24
+#define IRQ_EP93XX_UART2RX		25
+#define IRQ_EP93XX_UART2TX		26
+#define IRQ_EP93XX_UART3RX		27
+#define IRQ_EP93XX_UART3TX		28
+#define IRQ_EP93XX_KEY			29
+#define IRQ_EP93XX_TOUCH		30
+#define EP93XX_VIC1_VALID_IRQ_MASK	0x7ffffffc
+
+#define IRQ_EP93XX_EXT0			32
+#define IRQ_EP93XX_EXT1			33
+#define IRQ_EP93XX_EXT2			34
+#define IRQ_EP93XX_64HZ			35
+#define IRQ_EP93XX_WATCHDOG		36
+#define IRQ_EP93XX_RTC			37
+#define IRQ_EP93XX_IRDA			38
+#define IRQ_EP93XX_ETHERNET		39
+#define IRQ_EP93XX_EXT3			40
+#define IRQ_EP93XX_PROG			41
+#define IRQ_EP93XX_1HZ			42
+#define IRQ_EP93XX_VSYNC		43
+#define IRQ_EP93XX_VIDEO_FIFO		44
+#define IRQ_EP93XX_SSP1RX		45
+#define IRQ_EP93XX_SSP1TX		46
+#define IRQ_EP93XX_GPIO4MUX		47
+#define IRQ_EP93XX_GPIO5MUX		48
+#define IRQ_EP93XX_GPIO6MUX		49
+#define IRQ_EP93XX_GPIO7MUX		50
+#define IRQ_EP93XX_TIMER3		51
+#define IRQ_EP93XX_UART1		52
+#define IRQ_EP93XX_SSP			53
+#define IRQ_EP93XX_UART2		54
+#define IRQ_EP93XX_UART3		55
+#define IRQ_EP93XX_USB			56
+#define IRQ_EP93XX_ETHERNET_PME		57
+#define IRQ_EP93XX_DSP			58
+#define IRQ_EP93XX_GPIO_AB		59
+#define IRQ_EP93XX_SAI			60
+#define EP93XX_VIC2_VALID_IRQ_MASK	0x1fffffff
+
+#define NR_EP93XX_IRQS			(64 + 24)
+
+#define EP93XX_BOARD_IRQ(x)		(NR_EP93XX_IRQS + (x))
+#define EP93XX_BOARD_IRQS		32
+
+#define NR_IRQS				(NR_EP93XX_IRQS + EP93XX_BOARD_IRQS)
+
+
+#endif
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/include/mach/platform.h b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/include/mach/platform.h
new file mode 100644
index 0000000..3bbe159
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/include/mach/platform.h
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * arch/arm/mach-ep93xx/include/mach/platform.h
+ */
+
+#ifndef __ASSEMBLY__
+
+#include <linux/reboot.h>
+
+struct device;
+struct i2c_gpio_platform_data;
+struct i2c_board_info;
+struct spi_board_info;
+struct platform_device;
+struct ep93xxfb_mach_info;
+struct ep93xx_keypad_platform_data;
+struct ep93xx_spi_info;
+
+struct ep93xx_eth_data
+{
+	unsigned char	dev_addr[6];
+	unsigned char	phy_id;
+};
+
+void ep93xx_map_io(void);
+void ep93xx_init_irq(void);
+
+#define EP93XX_CHIP_REV_D0	3
+#define EP93XX_CHIP_REV_D1	4
+#define EP93XX_CHIP_REV_E0	5
+#define EP93XX_CHIP_REV_E1	6
+#define EP93XX_CHIP_REV_E2	7
+
+unsigned int ep93xx_chip_revision(void);
+
+void ep93xx_register_flash(unsigned int width,
+			   resource_size_t start, resource_size_t size);
+
+void ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr);
+void ep93xx_register_i2c(struct i2c_gpio_platform_data *data,
+			 struct i2c_board_info *devices, int num);
+void ep93xx_register_spi(struct ep93xx_spi_info *info,
+			 struct spi_board_info *devices, int num);
+void ep93xx_register_fb(struct ep93xxfb_mach_info *data);
+void ep93xx_register_pwm(int pwm0, int pwm1);
+int ep93xx_pwm_acquire_gpio(struct platform_device *pdev);
+void ep93xx_pwm_release_gpio(struct platform_device *pdev);
+void ep93xx_register_keypad(struct ep93xx_keypad_platform_data *data);
+int ep93xx_keypad_acquire_gpio(struct platform_device *pdev);
+void ep93xx_keypad_release_gpio(struct platform_device *pdev);
+void ep93xx_register_i2s(void);
+int ep93xx_i2s_acquire(void);
+void ep93xx_i2s_release(void);
+void ep93xx_register_ac97(void);
+void ep93xx_register_ide(void);
+void ep93xx_register_adc(void);
+int ep93xx_ide_acquire_gpio(struct platform_device *pdev);
+void ep93xx_ide_release_gpio(struct platform_device *pdev);
+
+struct device *ep93xx_init_devices(void);
+extern void ep93xx_timer_init(void);
+
+void ep93xx_restart(enum reboot_mode, const char *);
+void ep93xx_init_late(void);
+
+#ifdef CONFIG_CRUNCH
+int crunch_init(void);
+#else
+static inline int crunch_init(void) { return 0; }
+#endif
+
+#endif
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/include/mach/uncompress.h b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/include/mach/uncompress.h
new file mode 100644
index 0000000..b0cf2de
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/include/mach/uncompress.h
@@ -0,0 +1,94 @@
+/*
+ * arch/arm/mach-ep93xx/include/mach/uncompress.h
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <mach/ep93xx-regs.h>
+#include <asm/mach-types.h>
+
+static unsigned char __raw_readb(unsigned int ptr)
+{
+	return *((volatile unsigned char *)ptr);
+}
+
+static unsigned int __raw_readl(unsigned int ptr)
+{
+	return *((volatile unsigned int *)ptr);
+}
+
+static void __raw_writeb(unsigned char value, unsigned int ptr)
+{
+	*((volatile unsigned char *)ptr) = value;
+}
+
+static void __raw_writel(unsigned int value, unsigned int ptr)
+{
+	*((volatile unsigned int *)ptr) = value;
+}
+
+#define PHYS_UART_DATA		(CONFIG_DEBUG_UART_PHYS + 0x00)
+#define PHYS_UART_FLAG		(CONFIG_DEBUG_UART_PHYS + 0x18)
+#define UART_FLAG_TXFF		0x20
+
+static inline void putc(int c)
+{
+	int i;
+
+	for (i = 0; i < 10000; i++) {
+		/* Transmit fifo not full? */
+		if (!(__raw_readb(PHYS_UART_FLAG) & UART_FLAG_TXFF))
+			break;
+	}
+
+	__raw_writeb(c, PHYS_UART_DATA);
+}
+
+static inline void flush(void)
+{
+}
+
+
+/*
+ * Some bootloaders don't turn off DMA from the ethernet MAC before
+ * jumping to linux, which means that we might end up with bits of RX
+ * status and packet data scribbled over the uncompressed kernel image.
+ * Work around this by resetting the ethernet MAC before we uncompress.
+ */
+#define PHYS_ETH_SELF_CTL		0x80010020
+#define ETH_SELF_CTL_RESET		0x00000001
+
+static void ethernet_reset(void)
+{
+	unsigned int v;
+
+	/* Reset the ethernet MAC.  */
+	v = __raw_readl(PHYS_ETH_SELF_CTL);
+	__raw_writel(v | ETH_SELF_CTL_RESET, PHYS_ETH_SELF_CTL);
+
+	/* Wait for reset to finish.  */
+	while (__raw_readl(PHYS_ETH_SELF_CTL) & ETH_SELF_CTL_RESET)
+		;
+}
+
+#define TS72XX_WDT_CONTROL_PHYS_BASE	0x23800000
+#define TS72XX_WDT_FEED_PHYS_BASE	0x23c00000
+#define TS72XX_WDT_FEED_VAL		0x05
+
+static void __maybe_unused ts72xx_watchdog_disable(void)
+{
+	__raw_writeb(TS72XX_WDT_FEED_VAL, TS72XX_WDT_FEED_PHYS_BASE);
+	__raw_writeb(0, TS72XX_WDT_CONTROL_PHYS_BASE);
+}
+
+static void arch_decomp_setup(void)
+{
+	if (machine_is_ts72xx())
+		ts72xx_watchdog_disable();
+	ethernet_reset();
+}
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/micro9.c b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/micro9.c
new file mode 100644
index 0000000..373583c
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/micro9.c
@@ -0,0 +1,128 @@
+/*
+ *  linux/arch/arm/mach-ep93xx/micro9.c
+ *
+ * Copyright (C) 2006 Contec Steuerungstechnik & Automation GmbH
+ *                    Manfred Gruber <m.gruber@tirol.com>
+ * Copyright (C) 2009 Contec Steuerungstechnik & Automation GmbH
+ *                    Hubert Feurstein <hubert.feurstein@contec.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/init.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include "soc.h"
+
+/*************************************************************************
+ * Micro9 NOR Flash
+ *
+ * Micro9-High has up to 64MB of 32-bit flash on CS1
+ * Micro9-Mid has up to 64MB of either 32-bit or 16-bit flash on CS1
+ * Micro9-Lite uses a separate MTD map driver for flash support
+ * Micro9-Slim has up to 64MB of either 32-bit or 16-bit flash on CS1
+ *************************************************************************/
+static unsigned int __init micro9_detect_bootwidth(void)
+{
+	u32 v;
+
+	/* Detect the bus width of the external flash memory */
+	v = __raw_readl(EP93XX_SYSCON_SYSCFG);
+	if (v & EP93XX_SYSCON_SYSCFG_LCSN7)
+		return 4; /* 32-bit */
+	else
+		return 2; /* 16-bit */
+}
+
+static void __init micro9_register_flash(void)
+{
+	unsigned int width;
+
+	if (machine_is_micro9())
+		width = 4;
+	else if (machine_is_micro9m() || machine_is_micro9s())
+		width = micro9_detect_bootwidth();
+	else
+		width = 0;
+
+	if (width)
+		ep93xx_register_flash(width, EP93XX_CS1_PHYS_BASE, SZ_64M);
+}
+
+
+/*************************************************************************
+ * Micro9 Ethernet
+ *************************************************************************/
+static struct ep93xx_eth_data __initdata micro9_eth_data = {
+	.phy_id		= 0x1f,
+};
+
+
+static void __init micro9_init_machine(void)
+{
+	ep93xx_init_devices();
+	ep93xx_register_eth(&micro9_eth_data, 1);
+	micro9_register_flash();
+}
+
+
+#ifdef CONFIG_MACH_MICRO9H
+MACHINE_START(MICRO9, "Contec Micro9-High")
+	/* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
+	.atag_offset	= 0x100,
+	.map_io		= ep93xx_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.init_time	= ep93xx_timer_init,
+	.init_machine	= micro9_init_machine,
+	.init_late	= ep93xx_init_late,
+	.restart	= ep93xx_restart,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_MICRO9M
+MACHINE_START(MICRO9M, "Contec Micro9-Mid")
+	/* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
+	.atag_offset	= 0x100,
+	.map_io		= ep93xx_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.init_time	= ep93xx_timer_init,
+	.init_machine	= micro9_init_machine,
+	.init_late	= ep93xx_init_late,
+	.restart	= ep93xx_restart,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_MICRO9L
+MACHINE_START(MICRO9L, "Contec Micro9-Lite")
+	/* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
+	.atag_offset	= 0x100,
+	.map_io		= ep93xx_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.init_time	= ep93xx_timer_init,
+	.init_machine	= micro9_init_machine,
+	.init_late	= ep93xx_init_late,
+	.restart	= ep93xx_restart,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_MICRO9S
+MACHINE_START(MICRO9S, "Contec Micro9-Slim")
+	/* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */
+	.atag_offset	= 0x100,
+	.map_io		= ep93xx_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.init_time	= ep93xx_timer_init,
+	.init_machine	= micro9_init_machine,
+	.init_late	= ep93xx_init_late,
+	.restart	= ep93xx_restart,
+MACHINE_END
+#endif
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/simone.c b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/simone.c
new file mode 100644
index 0000000..c7a40f2
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/simone.c
@@ -0,0 +1,180 @@
+/*
+ * arch/arm/mach-ep93xx/simone.c
+ * Simplemachines Sim.One support.
+ *
+ * Copyright (C) 2010 Ryan Mallon
+ *
+ * Based on the 2.6.24.7 support:
+ *   Copyright (C) 2009 Simplemachines
+ *   MMC support by Peter Ivanov <ivanovp@gmail.com>, 2007
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
+#include <linux/mmc/host.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/mmc_spi.h>
+#include <linux/platform_data/video-ep93xx.h>
+#include <linux/platform_data/spi-ep93xx.h>
+#include <linux/gpio.h>
+
+#include <mach/hardware.h>
+#include <mach/gpio-ep93xx.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include "soc.h"
+
+static struct ep93xx_eth_data __initdata simone_eth_data = {
+	.phy_id		= 1,
+};
+
+static struct ep93xxfb_mach_info __initdata simone_fb_info = {
+	.flags		= EP93XXFB_USE_SDCSN0 | EP93XXFB_PCLK_FALLING,
+};
+
+/*
+ * GPIO lines used for MMC card detection.
+ */
+#define MMC_CARD_DETECT_GPIO EP93XX_GPIO_LINE_EGPIO0
+
+/*
+ * MMC card detection GPIO setup.
+ */
+
+static int simone_mmc_spi_init(struct device *dev,
+	irqreturn_t (*irq_handler)(int, void *), void *mmc)
+{
+	unsigned int gpio = MMC_CARD_DETECT_GPIO;
+	int irq, err;
+
+	err = gpio_request(gpio, dev_name(dev));
+	if (err)
+		return err;
+
+	err = gpio_direction_input(gpio);
+	if (err)
+		goto fail;
+
+	irq = gpio_to_irq(gpio);
+	if (irq < 0)
+		goto fail;
+
+	err = request_irq(irq, irq_handler, IRQF_TRIGGER_FALLING,
+			  "MMC card detect", mmc);
+	if (err)
+		goto fail;
+
+	printk(KERN_INFO "%s: using irq %d for MMC card detection\n",
+	       dev_name(dev), irq);
+
+	return 0;
+fail:
+	gpio_free(gpio);
+	return err;
+}
+
+static void simone_mmc_spi_exit(struct device *dev, void *mmc)
+{
+	unsigned int gpio = MMC_CARD_DETECT_GPIO;
+
+	free_irq(gpio_to_irq(gpio), mmc);
+	gpio_free(gpio);
+}
+
+static struct mmc_spi_platform_data simone_mmc_spi_data = {
+	.init		= simone_mmc_spi_init,
+	.exit		= simone_mmc_spi_exit,
+	.detect_delay	= 500,
+	.ocr_mask	= MMC_VDD_32_33 | MMC_VDD_33_34,
+};
+
+static struct spi_board_info simone_spi_devices[] __initdata = {
+	{
+		.modalias		= "mmc_spi",
+		.platform_data		= &simone_mmc_spi_data,
+		/*
+		 * We use 10 MHz even though the maximum is 3.7 MHz. The driver
+		 * will limit it automatically to max. frequency.
+		 */
+		.max_speed_hz		= 10 * 1000 * 1000,
+		.bus_num		= 0,
+		.chip_select		= 0,
+		.mode			= SPI_MODE_3,
+	},
+};
+
+/*
+ * Up to v1.3, the Sim.One used SFRMOUT as SD card chip select, but this goes
+ * low between multi-message command blocks. From v1.4, it uses a GPIO instead.
+ * v1.3 parts will still work, since the signal on SFRMOUT is automatic.
+ */
+static int simone_spi_chipselects[] __initdata = {
+	EP93XX_GPIO_LINE_EGPIO1,
+};
+
+static struct ep93xx_spi_info simone_spi_info __initdata = {
+	.chipselect	= simone_spi_chipselects,
+	.num_chipselect	= ARRAY_SIZE(simone_spi_chipselects),
+	.use_dma = 1,
+};
+
+static struct i2c_gpio_platform_data __initdata simone_i2c_gpio_data = {
+	.sda_pin		= EP93XX_GPIO_LINE_EEDAT,
+	.sda_is_open_drain	= 0,
+	.scl_pin		= EP93XX_GPIO_LINE_EECLK,
+	.scl_is_open_drain	= 0,
+	.udelay			= 0,
+	.timeout		= 0,
+};
+
+static struct i2c_board_info __initdata simone_i2c_board_info[] = {
+	{
+		I2C_BOARD_INFO("ds1337", 0x68),
+	},
+};
+
+static struct platform_device simone_audio_device = {
+	.name		= "simone-audio",
+	.id		= -1,
+};
+
+static void __init simone_register_audio(void)
+{
+	ep93xx_register_ac97();
+	platform_device_register(&simone_audio_device);
+}
+
+static void __init simone_init_machine(void)
+{
+	ep93xx_init_devices();
+	ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_8M);
+	ep93xx_register_eth(&simone_eth_data, 1);
+	ep93xx_register_fb(&simone_fb_info);
+	ep93xx_register_i2c(&simone_i2c_gpio_data, simone_i2c_board_info,
+			    ARRAY_SIZE(simone_i2c_board_info));
+	ep93xx_register_spi(&simone_spi_info, simone_spi_devices,
+			    ARRAY_SIZE(simone_spi_devices));
+	simone_register_audio();
+}
+
+MACHINE_START(SIM_ONE, "Simplemachines Sim.One Board")
+	/* Maintainer: Ryan Mallon */
+	.atag_offset	= 0x100,
+	.map_io		= ep93xx_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.init_time	= ep93xx_timer_init,
+	.init_machine	= simone_init_machine,
+	.init_late	= ep93xx_init_late,
+	.restart	= ep93xx_restart,
+MACHINE_END
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/snappercl15.c b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/snappercl15.c
new file mode 100644
index 0000000..8b29398
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/snappercl15.c
@@ -0,0 +1,180 @@
+/*
+ * arch/arm/mach-ep93xx/snappercl15.c
+ * Bluewater Systems Snapper CL15 system module
+ *
+ * Copyright (C) 2009 Bluewater Systems Ltd
+ * Author: Ryan Mallon
+ *
+ * NAND code adapted from driver by:
+ *   Andre Renaud <andre@bluewatersys.com>
+ *   James R. McKaskill
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
+#include <linux/fb.h>
+
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/rawnand.h>
+
+#include <mach/hardware.h>
+#include <linux/platform_data/video-ep93xx.h>
+#include <mach/gpio-ep93xx.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include "soc.h"
+
+#define SNAPPERCL15_NAND_BASE	(EP93XX_CS7_PHYS_BASE + SZ_16M)
+
+#define SNAPPERCL15_NAND_WPN	(1 << 8)  /* Write protect (active low) */
+#define SNAPPERCL15_NAND_ALE	(1 << 9)  /* Address latch */
+#define SNAPPERCL15_NAND_CLE	(1 << 10) /* Command latch */
+#define SNAPPERCL15_NAND_CEN	(1 << 11) /* Chip enable (active low) */
+#define SNAPPERCL15_NAND_RDY	(1 << 14) /* Device ready */
+
+#define NAND_CTRL_ADDR(chip) 	(chip->IO_ADDR_W + 0x40)
+
+static void snappercl15_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
+				      unsigned int ctrl)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	static u16 nand_state = SNAPPERCL15_NAND_WPN;
+	u16 set;
+
+	if (ctrl & NAND_CTRL_CHANGE) {
+		set = SNAPPERCL15_NAND_CEN | SNAPPERCL15_NAND_WPN;
+
+		if (ctrl & NAND_NCE)
+			set &= ~SNAPPERCL15_NAND_CEN;
+		if (ctrl & NAND_CLE)
+			set |= SNAPPERCL15_NAND_CLE;
+		if (ctrl & NAND_ALE)
+			set |= SNAPPERCL15_NAND_ALE;
+
+		nand_state &= ~(SNAPPERCL15_NAND_CEN |
+				SNAPPERCL15_NAND_CLE |
+				SNAPPERCL15_NAND_ALE);
+		nand_state |= set;
+		__raw_writew(nand_state, NAND_CTRL_ADDR(chip));
+	}
+
+	if (cmd != NAND_CMD_NONE)
+		__raw_writew((cmd & 0xff) | nand_state, chip->IO_ADDR_W);
+}
+
+static int snappercl15_nand_dev_ready(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+
+	return !!(__raw_readw(NAND_CTRL_ADDR(chip)) & SNAPPERCL15_NAND_RDY);
+}
+
+static struct mtd_partition snappercl15_nand_parts[] = {
+	{
+		.name		= "Kernel",
+		.offset		= 0,
+		.size		= SZ_2M,
+	},
+	{
+		.name		= "Filesystem",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= MTDPART_SIZ_FULL,
+	},
+};
+
+static struct platform_nand_data snappercl15_nand_data = {
+	.chip = {
+		.nr_chips		= 1,
+		.partitions		= snappercl15_nand_parts,
+		.nr_partitions		= ARRAY_SIZE(snappercl15_nand_parts),
+		.chip_delay		= 25,
+	},
+	.ctrl = {
+		.dev_ready		= snappercl15_nand_dev_ready,
+		.cmd_ctrl		= snappercl15_nand_cmd_ctrl,
+	},
+};
+
+static struct resource snappercl15_nand_resource[] = {
+	{
+		.start		= SNAPPERCL15_NAND_BASE,
+		.end		= SNAPPERCL15_NAND_BASE + SZ_4K - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device snappercl15_nand_device = {
+	.name			= "gen_nand",
+	.id			= -1,
+	.dev.platform_data	= &snappercl15_nand_data,
+	.resource		= snappercl15_nand_resource,
+	.num_resources		= ARRAY_SIZE(snappercl15_nand_resource),
+};
+
+static struct ep93xx_eth_data __initdata snappercl15_eth_data = {
+	.phy_id			= 1,
+};
+
+static struct i2c_gpio_platform_data __initdata snappercl15_i2c_gpio_data = {
+	.sda_pin		= EP93XX_GPIO_LINE_EEDAT,
+	.sda_is_open_drain	= 0,
+	.scl_pin		= EP93XX_GPIO_LINE_EECLK,
+	.scl_is_open_drain	= 0,
+	.udelay			= 0,
+	.timeout		= 0,
+};
+
+static struct i2c_board_info __initdata snappercl15_i2c_data[] = {
+	{
+		/* Audio codec */
+		I2C_BOARD_INFO("tlv320aic23", 0x1a),
+	},
+};
+
+static struct ep93xxfb_mach_info __initdata snappercl15_fb_info = {
+};
+
+static struct platform_device snappercl15_audio_device = {
+	.name		= "snappercl15-audio",
+	.id		= -1,
+};
+
+static void __init snappercl15_register_audio(void)
+{
+	ep93xx_register_i2s();
+	platform_device_register(&snappercl15_audio_device);
+}
+
+static void __init snappercl15_init_machine(void)
+{
+	ep93xx_init_devices();
+	ep93xx_register_eth(&snappercl15_eth_data, 1);
+	ep93xx_register_i2c(&snappercl15_i2c_gpio_data, snappercl15_i2c_data,
+			    ARRAY_SIZE(snappercl15_i2c_data));
+	ep93xx_register_fb(&snappercl15_fb_info);
+	snappercl15_register_audio();
+	platform_device_register(&snappercl15_nand_device);
+}
+
+MACHINE_START(SNAPPER_CL15, "Bluewater Systems Snapper CL15")
+	/* Maintainer: Ryan Mallon */
+	.atag_offset	= 0x100,
+	.map_io		= ep93xx_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.init_time	= ep93xx_timer_init,
+	.init_machine	= snappercl15_init_machine,
+	.init_late	= ep93xx_init_late,
+	.restart	= ep93xx_restart,
+MACHINE_END
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/soc.h b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/soc.h
new file mode 100644
index 0000000..d20e631
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/soc.h
@@ -0,0 +1,215 @@
+/*
+ * arch/arm/mach-ep93xx/soc.h
+ *
+ * Copyright (C) 2012 Open Kernel Labs <www.ok-labs.com>
+ * Copyright (C) 2012 Ryan Mallon <rmallon@gmail.com>
+ *
+ * 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.
+ */
+
+#ifndef _EP93XX_SOC_H
+#define _EP93XX_SOC_H
+
+#include <mach/ep93xx-regs.h>
+
+/*
+ * EP93xx Physical Memory Map:
+ *
+ * The ASDO pin is sampled at system reset to select a synchronous or
+ * asynchronous boot configuration.  When ASDO is "1" (i.e. pulled-up)
+ * the synchronous boot mode is selected.  When ASDO is "0" (i.e
+ * pulled-down) the asynchronous boot mode is selected.
+ *
+ * In synchronous boot mode nSDCE3 is decoded starting at physical address
+ * 0x00000000 and nCS0 is decoded starting at 0xf0000000.  For asynchronous
+ * boot mode they are swapped with nCS0 decoded at 0x00000000 ann nSDCE3
+ * decoded at 0xf0000000.
+ *
+ * There is known errata for the EP93xx dealing with External Memory
+ * Configurations.  Please refer to "AN273: EP93xx Silicon Rev E Design
+ * Guidelines" for more information.  This document can be found at:
+ *
+ *	http://www.cirrus.com/en/pubs/appNote/AN273REV4.pdf
+ */
+
+#define EP93XX_CS0_PHYS_BASE_ASYNC	0x00000000	/* ASDO Pin = 0 */
+#define EP93XX_SDCE3_PHYS_BASE_SYNC	0x00000000	/* ASDO Pin = 1 */
+#define EP93XX_CS1_PHYS_BASE		0x10000000
+#define EP93XX_CS2_PHYS_BASE		0x20000000
+#define EP93XX_CS3_PHYS_BASE		0x30000000
+#define EP93XX_PCMCIA_PHYS_BASE		0x40000000
+#define EP93XX_CS6_PHYS_BASE		0x60000000
+#define EP93XX_CS7_PHYS_BASE		0x70000000
+#define EP93XX_SDCE0_PHYS_BASE		0xc0000000
+#define EP93XX_SDCE1_PHYS_BASE		0xd0000000
+#define EP93XX_SDCE2_PHYS_BASE		0xe0000000
+#define EP93XX_SDCE3_PHYS_BASE_ASYNC	0xf0000000	/* ASDO Pin = 0 */
+#define EP93XX_CS0_PHYS_BASE_SYNC	0xf0000000	/* ASDO Pin = 1 */
+
+/* AHB peripherals */
+#define EP93XX_DMA_BASE			EP93XX_AHB_IOMEM(0x00000000)
+
+#define EP93XX_ETHERNET_PHYS_BASE	EP93XX_AHB_PHYS(0x00010000)
+#define EP93XX_ETHERNET_BASE		EP93XX_AHB_IOMEM(0x00010000)
+
+#define EP93XX_USB_PHYS_BASE		EP93XX_AHB_PHYS(0x00020000)
+#define EP93XX_USB_BASE			EP93XX_AHB_IOMEM(0x00020000)
+
+#define EP93XX_RASTER_PHYS_BASE		EP93XX_AHB_PHYS(0x00030000)
+#define EP93XX_RASTER_BASE		EP93XX_AHB_IOMEM(0x00030000)
+
+#define EP93XX_GRAPHICS_ACCEL_BASE	EP93XX_AHB_IOMEM(0x00040000)
+
+#define EP93XX_SDRAM_CONTROLLER_BASE	EP93XX_AHB_IOMEM(0x00060000)
+
+#define EP93XX_PCMCIA_CONTROLLER_BASE	EP93XX_AHB_IOMEM(0x00080000)
+
+#define EP93XX_BOOT_ROM_BASE		EP93XX_AHB_IOMEM(0x00090000)
+
+#define EP93XX_IDE_PHYS_BASE		EP93XX_AHB_PHYS(0x000a0000)
+#define EP93XX_IDE_BASE			EP93XX_AHB_IOMEM(0x000a0000)
+
+#define EP93XX_VIC1_BASE		EP93XX_AHB_IOMEM(0x000b0000)
+
+#define EP93XX_VIC2_BASE		EP93XX_AHB_IOMEM(0x000c0000)
+
+/* APB peripherals */
+#define EP93XX_TIMER_BASE		EP93XX_APB_IOMEM(0x00010000)
+
+#define EP93XX_I2S_PHYS_BASE		EP93XX_APB_PHYS(0x00020000)
+#define EP93XX_I2S_BASE			EP93XX_APB_IOMEM(0x00020000)
+
+#define EP93XX_SECURITY_BASE		EP93XX_APB_IOMEM(0x00030000)
+
+#define EP93XX_AAC_PHYS_BASE		EP93XX_APB_PHYS(0x00080000)
+#define EP93XX_AAC_BASE			EP93XX_APB_IOMEM(0x00080000)
+
+#define EP93XX_SPI_PHYS_BASE		EP93XX_APB_PHYS(0x000a0000)
+#define EP93XX_SPI_BASE			EP93XX_APB_IOMEM(0x000a0000)
+
+#define EP93XX_IRDA_BASE		EP93XX_APB_IOMEM(0x000b0000)
+
+#define EP93XX_KEY_MATRIX_PHYS_BASE	EP93XX_APB_PHYS(0x000f0000)
+#define EP93XX_KEY_MATRIX_BASE		EP93XX_APB_IOMEM(0x000f0000)
+
+#define EP93XX_ADC_PHYS_BASE		EP93XX_APB_PHYS(0x00100000)
+#define EP93XX_ADC_BASE			EP93XX_APB_IOMEM(0x00100000)
+#define EP93XX_TOUCHSCREEN_BASE		EP93XX_APB_IOMEM(0x00100000)
+
+#define EP93XX_PWM_PHYS_BASE		EP93XX_APB_PHYS(0x00110000)
+#define EP93XX_PWM_BASE			EP93XX_APB_IOMEM(0x00110000)
+
+#define EP93XX_RTC_PHYS_BASE		EP93XX_APB_PHYS(0x00120000)
+#define EP93XX_RTC_BASE			EP93XX_APB_IOMEM(0x00120000)
+
+#define EP93XX_WATCHDOG_PHYS_BASE	EP93XX_APB_PHYS(0x00140000)
+#define EP93XX_WATCHDOG_BASE		EP93XX_APB_IOMEM(0x00140000)
+
+/* System controller */
+#define EP93XX_SYSCON_BASE		EP93XX_APB_IOMEM(0x00130000)
+#define EP93XX_SYSCON_REG(x)		(EP93XX_SYSCON_BASE + (x))
+#define EP93XX_SYSCON_POWER_STATE	EP93XX_SYSCON_REG(0x00)
+#define EP93XX_SYSCON_PWRCNT		EP93XX_SYSCON_REG(0x04)
+#define EP93XX_SYSCON_PWRCNT_FIR_EN	(1<<31)
+#define EP93XX_SYSCON_PWRCNT_UARTBAUD	(1<<29)
+#define EP93XX_SYSCON_PWRCNT_USH_EN	(1<<28)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2M1	(1<<27)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2M0	(1<<26)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2P8	(1<<25)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2P9	(1<<24)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2P6	(1<<23)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2P7	(1<<22)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2P4	(1<<21)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2P5	(1<<20)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2P2	(1<<19)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2P3	(1<<18)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2P0	(1<<17)
+#define EP93XX_SYSCON_PWRCNT_DMA_M2P1	(1<<16)
+#define EP93XX_SYSCON_HALT		EP93XX_SYSCON_REG(0x08)
+#define EP93XX_SYSCON_STANDBY		EP93XX_SYSCON_REG(0x0c)
+#define EP93XX_SYSCON_CLKSET1		EP93XX_SYSCON_REG(0x20)
+#define EP93XX_SYSCON_CLKSET1_NBYP1	(1<<23)
+#define EP93XX_SYSCON_CLKSET2		EP93XX_SYSCON_REG(0x24)
+#define EP93XX_SYSCON_CLKSET2_NBYP2	(1<<19)
+#define EP93XX_SYSCON_CLKSET2_PLL2_EN	(1<<18)
+#define EP93XX_SYSCON_DEVCFG		EP93XX_SYSCON_REG(0x80)
+#define EP93XX_SYSCON_DEVCFG_SWRST	(1<<31)
+#define EP93XX_SYSCON_DEVCFG_D1ONG	(1<<30)
+#define EP93XX_SYSCON_DEVCFG_D0ONG	(1<<29)
+#define EP93XX_SYSCON_DEVCFG_IONU2	(1<<28)
+#define EP93XX_SYSCON_DEVCFG_GONK	(1<<27)
+#define EP93XX_SYSCON_DEVCFG_TONG	(1<<26)
+#define EP93XX_SYSCON_DEVCFG_MONG	(1<<25)
+#define EP93XX_SYSCON_DEVCFG_U3EN	(1<<24)
+#define EP93XX_SYSCON_DEVCFG_CPENA	(1<<23)
+#define EP93XX_SYSCON_DEVCFG_A2ONG	(1<<22)
+#define EP93XX_SYSCON_DEVCFG_A1ONG	(1<<21)
+#define EP93XX_SYSCON_DEVCFG_U2EN	(1<<20)
+#define EP93XX_SYSCON_DEVCFG_EXVC	(1<<19)
+#define EP93XX_SYSCON_DEVCFG_U1EN	(1<<18)
+#define EP93XX_SYSCON_DEVCFG_TIN	(1<<17)
+#define EP93XX_SYSCON_DEVCFG_HC3IN	(1<<15)
+#define EP93XX_SYSCON_DEVCFG_HC3EN	(1<<14)
+#define EP93XX_SYSCON_DEVCFG_HC1IN	(1<<13)
+#define EP93XX_SYSCON_DEVCFG_HC1EN	(1<<12)
+#define EP93XX_SYSCON_DEVCFG_HONIDE	(1<<11)
+#define EP93XX_SYSCON_DEVCFG_GONIDE	(1<<10)
+#define EP93XX_SYSCON_DEVCFG_PONG	(1<<9)
+#define EP93XX_SYSCON_DEVCFG_EONIDE	(1<<8)
+#define EP93XX_SYSCON_DEVCFG_I2SONSSP	(1<<7)
+#define EP93XX_SYSCON_DEVCFG_I2SONAC97	(1<<6)
+#define EP93XX_SYSCON_DEVCFG_RASONP3	(1<<4)
+#define EP93XX_SYSCON_DEVCFG_RAS	(1<<3)
+#define EP93XX_SYSCON_DEVCFG_ADCPD	(1<<2)
+#define EP93XX_SYSCON_DEVCFG_KEYS	(1<<1)
+#define EP93XX_SYSCON_DEVCFG_SHENA	(1<<0)
+#define EP93XX_SYSCON_VIDCLKDIV		EP93XX_SYSCON_REG(0x84)
+#define EP93XX_SYSCON_CLKDIV_ENABLE	(1<<15)
+#define EP93XX_SYSCON_CLKDIV_ESEL	(1<<14)
+#define EP93XX_SYSCON_CLKDIV_PSEL	(1<<13)
+#define EP93XX_SYSCON_CLKDIV_PDIV_SHIFT	8
+#define EP93XX_SYSCON_I2SCLKDIV		EP93XX_SYSCON_REG(0x8c)
+#define EP93XX_SYSCON_I2SCLKDIV_SENA	(1<<31)
+#define EP93XX_SYSCON_I2SCLKDIV_ORIDE   (1<<29)
+#define EP93XX_SYSCON_I2SCLKDIV_SPOL	(1<<19)
+#define EP93XX_I2SCLKDIV_SDIV		(1 << 16)
+#define EP93XX_I2SCLKDIV_LRDIV32	(0 << 17)
+#define EP93XX_I2SCLKDIV_LRDIV64	(1 << 17)
+#define EP93XX_I2SCLKDIV_LRDIV128	(2 << 17)
+#define EP93XX_I2SCLKDIV_LRDIV_MASK	(3 << 17)
+#define EP93XX_SYSCON_KEYTCHCLKDIV	EP93XX_SYSCON_REG(0x90)
+#define EP93XX_SYSCON_KEYTCHCLKDIV_TSEN	(1<<31)
+#define EP93XX_SYSCON_KEYTCHCLKDIV_ADIV	(1<<16)
+#define EP93XX_SYSCON_KEYTCHCLKDIV_KEN	(1<<15)
+#define EP93XX_SYSCON_KEYTCHCLKDIV_KDIV	(1<<0)
+#define EP93XX_SYSCON_SYSCFG		EP93XX_SYSCON_REG(0x9c)
+#define EP93XX_SYSCON_SYSCFG_REV_MASK	(0xf0000000)
+#define EP93XX_SYSCON_SYSCFG_REV_SHIFT	(28)
+#define EP93XX_SYSCON_SYSCFG_SBOOT	(1<<8)
+#define EP93XX_SYSCON_SYSCFG_LCSN7	(1<<7)
+#define EP93XX_SYSCON_SYSCFG_LCSN6	(1<<6)
+#define EP93XX_SYSCON_SYSCFG_LASDO	(1<<5)
+#define EP93XX_SYSCON_SYSCFG_LEEDA	(1<<4)
+#define EP93XX_SYSCON_SYSCFG_LEECLK	(1<<3)
+#define EP93XX_SYSCON_SYSCFG_LCSN2	(1<<1)
+#define EP93XX_SYSCON_SYSCFG_LCSN1	(1<<0)
+#define EP93XX_SYSCON_SWLOCK		EP93XX_SYSCON_REG(0xc0)
+
+/* EP93xx System Controller software locked register write */
+void ep93xx_syscon_swlocked_write(unsigned int val, void __iomem *reg);
+void ep93xx_devcfg_set_clear(unsigned int set_bits, unsigned int clear_bits);
+
+static inline void ep93xx_devcfg_set_bits(unsigned int bits)
+{
+	ep93xx_devcfg_set_clear(bits, 0x00);
+}
+
+static inline void ep93xx_devcfg_clear_bits(unsigned int bits)
+{
+	ep93xx_devcfg_set_clear(0x00, bits);
+}
+
+#endif /* _EP93XX_SOC_H */
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/timer-ep93xx.c b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/timer-ep93xx.c
new file mode 100644
index 0000000..de99883
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/timer-ep93xx.c
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/sched_clock.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <asm/mach/time.h>
+#include "soc.h"
+
+/*************************************************************************
+ * Timer handling for EP93xx
+ *************************************************************************
+ * The ep93xx has four internal timers.  Timers 1, 2 (both 16 bit) and
+ * 3 (32 bit) count down at 508 kHz, are self-reloading, and can generate
+ * an interrupt on underflow.  Timer 4 (40 bit) counts down at 983.04 kHz,
+ * is free-running, and can't generate interrupts.
+ *
+ * The 508 kHz timers are ideal for use for the timer interrupt, as the
+ * most common values of HZ divide 508 kHz nicely.  We pick the 32 bit
+ * timer (timer 3) to get as long sleep intervals as possible when using
+ * CONFIG_NO_HZ.
+ *
+ * The higher clock rate of timer 4 makes it a better choice than the
+ * other timers for use as clock source and for sched_clock(), providing
+ * a stable 40 bit time base.
+ *************************************************************************
+ */
+#define EP93XX_TIMER_REG(x)		(EP93XX_TIMER_BASE + (x))
+#define EP93XX_TIMER1_LOAD		EP93XX_TIMER_REG(0x00)
+#define EP93XX_TIMER1_VALUE		EP93XX_TIMER_REG(0x04)
+#define EP93XX_TIMER1_CONTROL		EP93XX_TIMER_REG(0x08)
+#define EP93XX_TIMER123_CONTROL_ENABLE	(1 << 7)
+#define EP93XX_TIMER123_CONTROL_MODE	(1 << 6)
+#define EP93XX_TIMER123_CONTROL_CLKSEL	(1 << 3)
+#define EP93XX_TIMER1_CLEAR		EP93XX_TIMER_REG(0x0c)
+#define EP93XX_TIMER2_LOAD		EP93XX_TIMER_REG(0x20)
+#define EP93XX_TIMER2_VALUE		EP93XX_TIMER_REG(0x24)
+#define EP93XX_TIMER2_CONTROL		EP93XX_TIMER_REG(0x28)
+#define EP93XX_TIMER2_CLEAR		EP93XX_TIMER_REG(0x2c)
+#define EP93XX_TIMER4_VALUE_LOW		EP93XX_TIMER_REG(0x60)
+#define EP93XX_TIMER4_VALUE_HIGH	EP93XX_TIMER_REG(0x64)
+#define EP93XX_TIMER4_VALUE_HIGH_ENABLE	(1 << 8)
+#define EP93XX_TIMER3_LOAD		EP93XX_TIMER_REG(0x80)
+#define EP93XX_TIMER3_VALUE		EP93XX_TIMER_REG(0x84)
+#define EP93XX_TIMER3_CONTROL		EP93XX_TIMER_REG(0x88)
+#define EP93XX_TIMER3_CLEAR		EP93XX_TIMER_REG(0x8c)
+
+#define EP93XX_TIMER123_RATE		508469
+#define EP93XX_TIMER4_RATE		983040
+
+static u64 notrace ep93xx_read_sched_clock(void)
+{
+	u64 ret;
+
+	ret = readl(EP93XX_TIMER4_VALUE_LOW);
+	ret |= ((u64) (readl(EP93XX_TIMER4_VALUE_HIGH) & 0xff) << 32);
+	return ret;
+}
+
+u64 ep93xx_clocksource_read(struct clocksource *c)
+{
+	u64 ret;
+
+	ret = readl(EP93XX_TIMER4_VALUE_LOW);
+	ret |= ((u64) (readl(EP93XX_TIMER4_VALUE_HIGH) & 0xff) << 32);
+	return (u64) ret;
+}
+
+static int ep93xx_clkevt_set_next_event(unsigned long next,
+					struct clock_event_device *evt)
+{
+	/* Default mode: periodic, off, 508 kHz */
+	u32 tmode = EP93XX_TIMER123_CONTROL_MODE |
+		    EP93XX_TIMER123_CONTROL_CLKSEL;
+
+	/* Clear timer */
+	writel(tmode, EP93XX_TIMER3_CONTROL);
+
+	/* Set next event */
+	writel(next, EP93XX_TIMER3_LOAD);
+	writel(tmode | EP93XX_TIMER123_CONTROL_ENABLE,
+	       EP93XX_TIMER3_CONTROL);
+        return 0;
+}
+
+
+static int ep93xx_clkevt_shutdown(struct clock_event_device *evt)
+{
+	/* Disable timer */
+	writel(0, EP93XX_TIMER3_CONTROL);
+
+	return 0;
+}
+
+static struct clock_event_device ep93xx_clockevent = {
+	.name			= "timer1",
+	.features		= CLOCK_EVT_FEAT_ONESHOT,
+	.set_state_shutdown	= ep93xx_clkevt_shutdown,
+	.set_state_oneshot	= ep93xx_clkevt_shutdown,
+	.tick_resume		= ep93xx_clkevt_shutdown,
+	.set_next_event		= ep93xx_clkevt_set_next_event,
+	.rating			= 300,
+};
+
+static irqreturn_t ep93xx_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = dev_id;
+
+	/* Writing any value clears the timer interrupt */
+	writel(1, EP93XX_TIMER3_CLEAR);
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction ep93xx_timer_irq = {
+	.name		= "ep93xx timer",
+	.flags		= IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= ep93xx_timer_interrupt,
+	.dev_id		= &ep93xx_clockevent,
+};
+
+void __init ep93xx_timer_init(void)
+{
+	/* Enable and register clocksource and sched_clock on timer 4 */
+	writel(EP93XX_TIMER4_VALUE_HIGH_ENABLE,
+	       EP93XX_TIMER4_VALUE_HIGH);
+	clocksource_mmio_init(NULL, "timer4",
+			      EP93XX_TIMER4_RATE, 200, 40,
+			      ep93xx_clocksource_read);
+	sched_clock_register(ep93xx_read_sched_clock, 40,
+			     EP93XX_TIMER4_RATE);
+
+	/* Set up clockevent on timer 3 */
+	setup_irq(IRQ_EP93XX_TIMER3, &ep93xx_timer_irq);
+	clockevents_config_and_register(&ep93xx_clockevent,
+					EP93XX_TIMER123_RATE,
+					1,
+					0xffffffffU);
+}
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/ts72xx.c b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/ts72xx.c
new file mode 100644
index 0000000..8745162
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/ts72xx.c
@@ -0,0 +1,258 @@
+/*
+ * arch/arm/mach-ep93xx/ts72xx.c
+ * Technologic Systems TS72xx SBC support.
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/mtd/rawnand.h>
+#include <linux/mtd/partitions.h>
+
+#include <mach/hardware.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/map.h>
+#include <asm/mach/arch.h>
+
+#include "soc.h"
+#include "ts72xx.h"
+
+static struct map_desc ts72xx_io_desc[] __initdata = {
+	{
+		.virtual	= (unsigned long)TS72XX_MODEL_VIRT_BASE,
+		.pfn		= __phys_to_pfn(TS72XX_MODEL_PHYS_BASE),
+		.length		= TS72XX_MODEL_SIZE,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)TS72XX_OPTIONS_VIRT_BASE,
+		.pfn		= __phys_to_pfn(TS72XX_OPTIONS_PHYS_BASE),
+		.length		= TS72XX_OPTIONS_SIZE,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)TS72XX_OPTIONS2_VIRT_BASE,
+		.pfn		= __phys_to_pfn(TS72XX_OPTIONS2_PHYS_BASE),
+		.length		= TS72XX_OPTIONS2_SIZE,
+		.type		= MT_DEVICE,
+	}
+};
+
+static void __init ts72xx_map_io(void)
+{
+	ep93xx_map_io();
+	iotable_init(ts72xx_io_desc, ARRAY_SIZE(ts72xx_io_desc));
+}
+
+
+/*************************************************************************
+ * NAND flash
+ *************************************************************************/
+#define TS72XX_NAND_CONTROL_ADDR_LINE	22	/* 0xN0400000 */
+#define TS72XX_NAND_BUSY_ADDR_LINE	23	/* 0xN0800000 */
+
+static void ts72xx_nand_hwcontrol(struct mtd_info *mtd,
+				  int cmd, unsigned int ctrl)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+
+	if (ctrl & NAND_CTRL_CHANGE) {
+		void __iomem *addr = chip->IO_ADDR_R;
+		unsigned char bits;
+
+		addr += (1 << TS72XX_NAND_CONTROL_ADDR_LINE);
+
+		bits = __raw_readb(addr) & ~0x07;
+		bits |= (ctrl & NAND_NCE) << 2;	/* bit 0 -> bit 2 */
+		bits |= (ctrl & NAND_CLE);	/* bit 1 -> bit 1 */
+		bits |= (ctrl & NAND_ALE) >> 2;	/* bit 2 -> bit 0 */
+
+		__raw_writeb(bits, addr);
+	}
+
+	if (cmd != NAND_CMD_NONE)
+		__raw_writeb(cmd, chip->IO_ADDR_W);
+}
+
+static int ts72xx_nand_device_ready(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	void __iomem *addr = chip->IO_ADDR_R;
+
+	addr += (1 << TS72XX_NAND_BUSY_ADDR_LINE);
+
+	return !!(__raw_readb(addr) & 0x20);
+}
+
+#define TS72XX_BOOTROM_PART_SIZE	(SZ_16K)
+#define TS72XX_REDBOOT_PART_SIZE	(SZ_2M + SZ_1M)
+
+static struct mtd_partition ts72xx_nand_parts[] = {
+	{
+		.name		= "TS-BOOTROM",
+		.offset		= 0,
+		.size		= TS72XX_BOOTROM_PART_SIZE,
+		.mask_flags	= MTD_WRITEABLE,	/* force read-only */
+	}, {
+		.name		= "Linux",
+		.offset		= MTDPART_OFS_RETAIN,
+		.size		= TS72XX_REDBOOT_PART_SIZE,
+				/* leave so much for last partition */
+	}, {
+		.name		= "RedBoot",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= MTDPART_SIZ_FULL,
+		.mask_flags	= MTD_WRITEABLE,	/* force read-only */
+	},
+};
+
+static struct platform_nand_data ts72xx_nand_data = {
+	.chip = {
+		.nr_chips	= 1,
+		.chip_offset	= 0,
+		.chip_delay	= 15,
+		.partitions	= ts72xx_nand_parts,
+		.nr_partitions	= ARRAY_SIZE(ts72xx_nand_parts),
+	},
+	.ctrl = {
+		.cmd_ctrl	= ts72xx_nand_hwcontrol,
+		.dev_ready	= ts72xx_nand_device_ready,
+	},
+};
+
+static struct resource ts72xx_nand_resource[] = {
+	{
+		.start		= 0,			/* filled in later */
+		.end		= 0,			/* filled in later */
+		.flags		= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device ts72xx_nand_flash = {
+	.name			= "gen_nand",
+	.id			= -1,
+	.dev.platform_data	= &ts72xx_nand_data,
+	.resource		= ts72xx_nand_resource,
+	.num_resources		= ARRAY_SIZE(ts72xx_nand_resource),
+};
+
+
+static void __init ts72xx_register_flash(void)
+{
+	/*
+	 * TS7200 has NOR flash all other TS72xx board have NAND flash.
+	 */
+	if (board_is_ts7200()) {
+		ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_16M);
+	} else {
+		resource_size_t start;
+
+		if (is_ts9420_installed())
+			start = EP93XX_CS7_PHYS_BASE;
+		else
+			start = EP93XX_CS6_PHYS_BASE;
+
+		ts72xx_nand_resource[0].start = start;
+		ts72xx_nand_resource[0].end = start + SZ_16M - 1;
+
+		platform_device_register(&ts72xx_nand_flash);
+	}
+}
+
+/*************************************************************************
+ * RTC M48T86
+ *************************************************************************/
+#define TS72XX_RTC_INDEX_PHYS_BASE	(EP93XX_CS1_PHYS_BASE + 0x00800000)
+#define TS72XX_RTC_DATA_PHYS_BASE	(EP93XX_CS1_PHYS_BASE + 0x01700000)
+
+static struct resource ts72xx_rtc_resources[] = {
+	DEFINE_RES_MEM(TS72XX_RTC_INDEX_PHYS_BASE, 0x01),
+	DEFINE_RES_MEM(TS72XX_RTC_DATA_PHYS_BASE, 0x01),
+};
+
+static struct platform_device ts72xx_rtc_device = {
+	.name		= "rtc-m48t86",
+	.id		= -1,
+	.resource	= ts72xx_rtc_resources,
+	.num_resources 	= ARRAY_SIZE(ts72xx_rtc_resources),
+};
+
+static struct resource ts72xx_wdt_resources[] = {
+	{
+		.start	= TS72XX_WDT_CONTROL_PHYS_BASE,
+		.end	= TS72XX_WDT_CONTROL_PHYS_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= TS72XX_WDT_FEED_PHYS_BASE,
+		.end	= TS72XX_WDT_FEED_PHYS_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device ts72xx_wdt_device = {
+	.name		= "ts72xx-wdt",
+	.id		= -1,
+	.num_resources 	= ARRAY_SIZE(ts72xx_wdt_resources),
+	.resource	= ts72xx_wdt_resources,
+};
+
+static struct ep93xx_eth_data __initdata ts72xx_eth_data = {
+	.phy_id		= 1,
+};
+
+#if IS_ENABLED(CONFIG_FPGA_MGR_TS73XX)
+
+/* Relative to EP93XX_CS1_PHYS_BASE */
+#define TS73XX_FPGA_LOADER_BASE		0x03c00000
+
+static struct resource ts73xx_fpga_resources[] = {
+	{
+		.start	= EP93XX_CS1_PHYS_BASE + TS73XX_FPGA_LOADER_BASE,
+		.end	= EP93XX_CS1_PHYS_BASE + TS73XX_FPGA_LOADER_BASE + 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device ts73xx_fpga_device = {
+	.name	= "ts73xx-fpga-mgr",
+	.id	= -1,
+	.resource = ts73xx_fpga_resources,
+	.num_resources = ARRAY_SIZE(ts73xx_fpga_resources),
+};
+
+#endif
+
+static void __init ts72xx_init_machine(void)
+{
+	ep93xx_init_devices();
+	ts72xx_register_flash();
+	platform_device_register(&ts72xx_rtc_device);
+	platform_device_register(&ts72xx_wdt_device);
+
+	ep93xx_register_eth(&ts72xx_eth_data, 1);
+#if IS_ENABLED(CONFIG_FPGA_MGR_TS73XX)
+	if (board_is_ts7300())
+		platform_device_register(&ts73xx_fpga_device);
+#endif
+}
+
+MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC")
+	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
+	.atag_offset	= 0x100,
+	.map_io		= ts72xx_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.init_time	= ep93xx_timer_init,
+	.init_machine	= ts72xx_init_machine,
+	.init_late	= ep93xx_init_late,
+	.restart	= ep93xx_restart,
+MACHINE_END
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/ts72xx.h b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/ts72xx.h
new file mode 100644
index 0000000..b89850f
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/ts72xx.h
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * arch/arm/mach-ep93xx/include/mach/ts72xx.h
+ */
+
+/*
+ * TS72xx memory map:
+ *
+ * virt		phys		size
+ * febff000	22000000	4K	model number register (bits 0-2)
+ * febfe000	22400000	4K	options register
+ * febfd000	22800000	4K	options register #2
+ */
+
+#define TS72XX_MODEL_PHYS_BASE		0x22000000
+#define TS72XX_MODEL_VIRT_BASE		IOMEM(0xfebff000)
+#define TS72XX_MODEL_SIZE		0x00001000
+
+#define TS72XX_MODEL_TS7200		0x00
+#define TS72XX_MODEL_TS7250		0x01
+#define TS72XX_MODEL_TS7260		0x02
+#define TS72XX_MODEL_TS7300		0x03
+#define TS72XX_MODEL_TS7400		0x04
+#define TS72XX_MODEL_MASK		0x07
+
+
+#define TS72XX_OPTIONS_PHYS_BASE	0x22400000
+#define TS72XX_OPTIONS_VIRT_BASE	IOMEM(0xfebfe000)
+#define TS72XX_OPTIONS_SIZE		0x00001000
+
+#define TS72XX_OPTIONS_COM2_RS485	0x02
+#define TS72XX_OPTIONS_MAX197		0x01
+
+
+#define TS72XX_OPTIONS2_PHYS_BASE	0x22800000
+#define TS72XX_OPTIONS2_VIRT_BASE	IOMEM(0xfebfd000)
+#define TS72XX_OPTIONS2_SIZE		0x00001000
+
+#define TS72XX_OPTIONS2_TS9420		0x04
+#define TS72XX_OPTIONS2_TS9420_BOOT	0x02
+
+#define TS72XX_WDT_CONTROL_PHYS_BASE	0x23800000
+#define TS72XX_WDT_FEED_PHYS_BASE	0x23c00000
+
+#ifndef __ASSEMBLY__
+
+static inline int ts72xx_model(void)
+{
+	return __raw_readb(TS72XX_MODEL_VIRT_BASE) & TS72XX_MODEL_MASK;
+}
+
+static inline int board_is_ts7200(void)
+{
+	return ts72xx_model() == TS72XX_MODEL_TS7200;
+}
+
+static inline int board_is_ts7250(void)
+{
+	return ts72xx_model() == TS72XX_MODEL_TS7250;
+}
+
+static inline int board_is_ts7260(void)
+{
+	return ts72xx_model() == TS72XX_MODEL_TS7260;
+}
+
+static inline int board_is_ts7300(void)
+{
+	return ts72xx_model()  == TS72XX_MODEL_TS7300;
+}
+
+static inline int board_is_ts7400(void)
+{
+	return ts72xx_model() == TS72XX_MODEL_TS7400;
+}
+
+static inline int is_max197_installed(void)
+{
+	return !!(__raw_readb(TS72XX_OPTIONS_VIRT_BASE) &
+					TS72XX_OPTIONS_MAX197);
+}
+
+static inline int is_ts9420_installed(void)
+{
+	return !!(__raw_readb(TS72XX_OPTIONS2_VIRT_BASE) &
+					TS72XX_OPTIONS2_TS9420);
+}
+#endif
diff --git a/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/vision_ep9307.c b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/vision_ep9307.c
new file mode 100644
index 0000000..1daf944
--- /dev/null
+++ b/src/kernel/linux/v4.14/arch/arm/mach-ep93xx/vision_ep9307.c
@@ -0,0 +1,308 @@
+/*
+ * arch/arm/mach-ep93xx/vision_ep9307.c
+ * Vision Engraving Systems EP9307 SoM support.
+ *
+ * Copyright (C) 2008-2011 Vision Engraving Systems
+ * H Hartley Sweeten <hsweeten@visionengravers.com>
+ *
+ * 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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/fb.h>
+#include <linux/io.h>
+#include <linux/mtd/partitions.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
+#include <linux/platform_data/pca953x.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/mmc_spi.h>
+#include <linux/mmc/host.h>
+
+#include <sound/cs4271.h>
+
+#include <mach/hardware.h>
+#include <linux/platform_data/video-ep93xx.h>
+#include <linux/platform_data/spi-ep93xx.h>
+#include <mach/gpio-ep93xx.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/map.h>
+#include <asm/mach/arch.h>
+
+#include "soc.h"
+
+/*************************************************************************
+ * Static I/O mappings for the FPGA
+ *************************************************************************/
+#define VISION_PHYS_BASE	EP93XX_CS7_PHYS_BASE
+#define VISION_VIRT_BASE	0xfebff000
+
+static struct map_desc vision_io_desc[] __initdata = {
+	{
+		.virtual	= VISION_VIRT_BASE,
+		.pfn		= __phys_to_pfn(VISION_PHYS_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+};
+
+static void __init vision_map_io(void)
+{
+	ep93xx_map_io();
+
+	iotable_init(vision_io_desc, ARRAY_SIZE(vision_io_desc));
+}
+
+/*************************************************************************
+ * Ethernet
+ *************************************************************************/
+static struct ep93xx_eth_data vision_eth_data __initdata = {
+	.phy_id		= 1,
+};
+
+/*************************************************************************
+ * Framebuffer
+ *************************************************************************/
+#define VISION_LCD_ENABLE	EP93XX_GPIO_LINE_EGPIO1
+
+static int vision_lcd_setup(struct platform_device *pdev)
+{
+	int err;
+
+	err = gpio_request_one(VISION_LCD_ENABLE, GPIOF_INIT_HIGH,
+				dev_name(&pdev->dev));
+	if (err)
+		return err;
+
+	ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_RAS |
+				 EP93XX_SYSCON_DEVCFG_RASONP3 |
+				 EP93XX_SYSCON_DEVCFG_EXVC);
+
+	return 0;
+}
+
+static void vision_lcd_teardown(struct platform_device *pdev)
+{
+	gpio_free(VISION_LCD_ENABLE);
+}
+
+static void vision_lcd_blank(int blank_mode, struct fb_info *info)
+{
+	if (blank_mode)
+		gpio_set_value(VISION_LCD_ENABLE, 0);
+	else
+		gpio_set_value(VISION_LCD_ENABLE, 1);
+}
+
+static struct ep93xxfb_mach_info ep93xxfb_info __initdata = {
+	.flags		= EP93XXFB_USE_SDCSN0 | EP93XXFB_PCLK_FALLING,
+	.setup		= vision_lcd_setup,
+	.teardown	= vision_lcd_teardown,
+	.blank		= vision_lcd_blank,
+};
+
+
+/*************************************************************************
+ * GPIO Expanders
+ *************************************************************************/
+#define PCA9539_74_GPIO_BASE	(EP93XX_GPIO_LINE_MAX + 1)
+#define PCA9539_75_GPIO_BASE	(PCA9539_74_GPIO_BASE + 16)
+#define PCA9539_76_GPIO_BASE	(PCA9539_75_GPIO_BASE + 16)
+#define PCA9539_77_GPIO_BASE	(PCA9539_76_GPIO_BASE + 16)
+
+static struct pca953x_platform_data pca953x_74_gpio_data = {
+	.gpio_base	= PCA9539_74_GPIO_BASE,
+	.irq_base	= EP93XX_BOARD_IRQ(0),
+};
+
+static struct pca953x_platform_data pca953x_75_gpio_data = {
+	.gpio_base	= PCA9539_75_GPIO_BASE,
+	.irq_base	= -1,
+};
+
+static struct pca953x_platform_data pca953x_76_gpio_data = {
+	.gpio_base	= PCA9539_76_GPIO_BASE,
+	.irq_base	= -1,
+};
+
+static struct pca953x_platform_data pca953x_77_gpio_data = {
+	.gpio_base	= PCA9539_77_GPIO_BASE,
+	.irq_base	= -1,
+};
+
+/*************************************************************************
+ * I2C Bus
+ *************************************************************************/
+static struct i2c_gpio_platform_data vision_i2c_gpio_data __initdata = {
+	.sda_pin		= EP93XX_GPIO_LINE_EEDAT,
+	.scl_pin		= EP93XX_GPIO_LINE_EECLK,
+};
+
+static struct i2c_board_info vision_i2c_info[] __initdata = {
+	{
+		I2C_BOARD_INFO("isl1208", 0x6f),
+		.irq		= IRQ_EP93XX_EXT1,
+	}, {
+		I2C_BOARD_INFO("pca9539", 0x74),
+		.platform_data	= &pca953x_74_gpio_data,
+	}, {
+		I2C_BOARD_INFO("pca9539", 0x75),
+		.platform_data	= &pca953x_75_gpio_data,
+	}, {
+		I2C_BOARD_INFO("pca9539", 0x76),
+		.platform_data	= &pca953x_76_gpio_data,
+	}, {
+		I2C_BOARD_INFO("pca9539", 0x77),
+		.platform_data	= &pca953x_77_gpio_data,
+	},
+};
+
+/*************************************************************************
+ * SPI CS4271 Audio Codec
+ *************************************************************************/
+static struct cs4271_platform_data vision_cs4271_data = {
+	.gpio_nreset	= EP93XX_GPIO_LINE_H(2),
+};
+
+/*************************************************************************
+ * SPI Flash
+ *************************************************************************/
+static struct mtd_partition vision_spi_flash_partitions[] = {
+	{
+		.name	= "SPI bootstrap",
+		.offset	= 0,
+		.size	= SZ_4K,
+	}, {
+		.name	= "Bootstrap config",
+		.offset	= MTDPART_OFS_APPEND,
+		.size	= SZ_4K,
+	}, {
+		.name	= "System config",
+		.offset	= MTDPART_OFS_APPEND,
+		.size	= MTDPART_SIZ_FULL,
+	},
+};
+
+static struct flash_platform_data vision_spi_flash_data = {
+	.name		= "SPI Flash",
+	.parts		= vision_spi_flash_partitions,
+	.nr_parts	= ARRAY_SIZE(vision_spi_flash_partitions),
+};
+
+/*************************************************************************
+ * SPI SD/MMC host
+ *************************************************************************/
+static struct mmc_spi_platform_data vision_spi_mmc_data = {
+	.detect_delay	= 100,
+	.powerup_msecs	= 100,
+	.ocr_mask	= MMC_VDD_32_33 | MMC_VDD_33_34,
+	.flags		= MMC_SPI_USE_CD_GPIO | MMC_SPI_USE_RO_GPIO,
+	.cd_gpio	= EP93XX_GPIO_LINE_EGPIO15,
+	.cd_debounce	= 1,
+	.ro_gpio	= EP93XX_GPIO_LINE_F(0),
+	.caps2		= MMC_CAP2_RO_ACTIVE_HIGH,
+};
+
+/*************************************************************************
+ * SPI Bus
+ *************************************************************************/
+static struct spi_board_info vision_spi_board_info[] __initdata = {
+	{
+		.modalias		= "cs4271",
+		.platform_data		= &vision_cs4271_data,
+		.max_speed_hz		= 6000000,
+		.bus_num		= 0,
+		.chip_select		= 0,
+		.mode			= SPI_MODE_3,
+	}, {
+		.modalias		= "sst25l",
+		.platform_data		= &vision_spi_flash_data,
+		.max_speed_hz		= 20000000,
+		.bus_num		= 0,
+		.chip_select		= 1,
+		.mode			= SPI_MODE_3,
+	}, {
+		.modalias		= "mmc_spi",
+		.platform_data		= &vision_spi_mmc_data,
+		.max_speed_hz		= 20000000,
+		.bus_num		= 0,
+		.chip_select		= 2,
+		.mode			= SPI_MODE_3,
+	},
+};
+
+static int vision_spi_chipselects[] __initdata = {
+	EP93XX_GPIO_LINE_EGPIO6,
+	EP93XX_GPIO_LINE_EGPIO7,
+	EP93XX_GPIO_LINE_G(2),
+};
+
+static struct ep93xx_spi_info vision_spi_master __initdata = {
+	.chipselect	= vision_spi_chipselects,
+	.num_chipselect	= ARRAY_SIZE(vision_spi_chipselects),
+	.use_dma	= 1,
+};
+
+/*************************************************************************
+ * I2S Audio
+ *************************************************************************/
+static struct platform_device vision_audio_device = {
+	.name		= "edb93xx-audio",
+	.id		= -1,
+};
+
+static void __init vision_register_i2s(void)
+{
+	ep93xx_register_i2s();
+	platform_device_register(&vision_audio_device);
+}
+
+/*************************************************************************
+ * Machine Initialization
+ *************************************************************************/
+static void __init vision_init_machine(void)
+{
+	ep93xx_init_devices();
+	ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_64M);
+	ep93xx_register_eth(&vision_eth_data, 1);
+	ep93xx_register_fb(&ep93xxfb_info);
+	ep93xx_register_pwm(1, 0);
+
+	/*
+	 * Request the gpio expander's interrupt gpio line now to prevent
+	 * the kernel from doing a WARN in gpiolib:gpio_ensure_requested().
+	 */
+	if (gpio_request_one(EP93XX_GPIO_LINE_F(7), GPIOF_DIR_IN,
+				"pca9539:74"))
+		pr_warn("cannot request interrupt gpio for pca9539:74\n");
+
+	vision_i2c_info[1].irq = gpio_to_irq(EP93XX_GPIO_LINE_F(7));
+
+	ep93xx_register_i2c(&vision_i2c_gpio_data, vision_i2c_info,
+				ARRAY_SIZE(vision_i2c_info));
+	ep93xx_register_spi(&vision_spi_master, vision_spi_board_info,
+				ARRAY_SIZE(vision_spi_board_info));
+	vision_register_i2s();
+}
+
+MACHINE_START(VISION_EP9307, "Vision Engraving Systems EP9307")
+	/* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
+	.atag_offset	= 0x100,
+	.map_io		= vision_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.init_time	= ep93xx_timer_init,
+	.init_machine	= vision_init_machine,
+	.init_late	= ep93xx_init_late,
+	.restart	= ep93xx_restart,
+MACHINE_END