diff -ruw linux-4.2/arch/x86/boot/early_serial_console.c linux-4.2-fbx/arch/x86/boot/early_serial_console.c
--- linux-4.2/arch/x86/boot/early_serial_console.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/arch/x86/boot/early_serial_console.c	2015-09-15 19:18:36.522445905 +0200
@@ -24,11 +24,17 @@
 	unsigned divisor;
 
 	outb(0x3, port + LCR);	/* 8n1 */
+#ifndef CONFIG_X86_INTEL_CE
 	outb(0, port + IER);	/* no interrupt */
+#endif
 	outb(0, port + FCR);	/* no fifo */
 	outb(0x3, port + MCR);	/* DTR + RTS */
 
+#ifdef CONFIG_X86_INTEL_CE
+	divisor	= 921600 / baud;
+#else
 	divisor	= 115200 / baud;
+#endif
 	c = inb(port + LCR);
 	outb(c | DLAB, port + LCR);
 	outb(divisor & 0xff, port + DLL);
diff -ruw linux-4.2/arch/x86/include/asm/string_32.h linux-4.2-fbx/arch/x86/include/asm/string_32.h
--- linux-4.2/arch/x86/include/asm/string_32.h	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/arch/x86/include/asm/string_32.h	2013-12-04 14:33:18.555478967 +0100
@@ -178,7 +178,7 @@
 
 #ifndef CONFIG_KMEMCHECK
 
-#if (__GNUC__ >= 4)
+#if (__GNUC__ >= 4 && !defined(CONFIG_X86_INTEL_CE))
 #define memcpy(t, f, n) __builtin_memcpy(t, f, n)
 #else
 #define memcpy(t, f, n)				\
@@ -321,7 +321,7 @@
 	 : __memset_generic((s), (c), (count)))
 
 #define __HAVE_ARCH_MEMSET
-#if (__GNUC__ >= 4)
+#if (__GNUC__ >= 4 && !defined(CONFIG_X86_INTEL_CE))
 #define memset(s, c, count) __builtin_memset(s, c, count)
 #else
 #define memset(s, c, count)						\
diff -ruw linux-4.2/arch/x86/include/uapi/asm/bootparam.h linux-4.2-fbx/arch/x86/include/uapi/asm/bootparam.h
--- linux-4.2/arch/x86/include/uapi/asm/bootparam.h	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/arch/x86/include/uapi/asm/bootparam.h	2015-09-15 19:18:36.562446154 +0200
@@ -37,6 +37,17 @@
 #include <asm/ist.h>
 #include <video/edid.h>
 
+/* setup data types */
+#define SETUP_NONE			0
+#define SETUP_E820_EXT			1
+#define SETUP_DTB			2
+
+/*
+ * use a number that likely won't clash with newer extensions.
+ */
+#define SETUP_FBXSERIAL_EXT		0x42000001
+#define SETUP_FBXBOOTINFO		0x42000002
+
 /* extensible setup data list node */
 struct setup_data {
 	__u64 next;
diff -ruw linux-4.2/arch/x86/Kconfig linux-4.2-fbx/arch/x86/Kconfig
--- linux-4.2/arch/x86/Kconfig	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/arch/x86/Kconfig	2015-10-08 15:23:27.106693450 +0200
@@ -480,6 +480,11 @@
 	  This option compiles in support for the CE4100 SOC for settop
 	  boxes and media devices.
 
+config FBX6HD
+	bool "Freebox 6HD support"
+	depends on X86_INTEL_CE
+	select FBXSERIAL
+
 config X86_INTEL_MID
 	bool "Intel MID platform support"
 	depends on X86_32
diff -ruw linux-4.2/arch/x86/kernel/cpu/intel.c linux-4.2-fbx/arch/x86/kernel/cpu/intel.c
--- linux-4.2/arch/x86/kernel/cpu/intel.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/arch/x86/kernel/cpu/intel.c	2015-09-15 19:18:36.570446204 +0200
@@ -28,6 +28,7 @@
 static void early_init_intel(struct cpuinfo_x86 *c)
 {
 	u64 misc_enable;
+	bool allow_fast_string = true;
 
 	/* Unmask CPUID levels if masked: */
 	if (c->x86 > 6 || (c->x86 == 6 && c->x86_model >= 0xd)) {
@@ -126,20 +127,37 @@
 	 * Ingo Molnar reported a Pentium D (model 6) and a Xeon
 	 * (model 2) with the same problem.
 	 */
-	if (c->x86 == 15)
+	if (c->x86 == 15) {
+		allow_fast_string = false;
 		if (msr_clear_bit(MSR_IA32_MISC_ENABLE,
 				  MSR_IA32_MISC_ENABLE_FAST_STRING_BIT) > 0)
 			pr_info("kmemcheck: Disabling fast string operations\n");
+	}
 #endif
 
 	/*
-	 * If fast string is not enabled in IA32_MISC_ENABLE for any reason,
-	 * clear the fast string and enhanced fast string CPU capabilities.
+	 * If BIOS didn't enable fast string operation, try to enable
+	 * it ourselves.  If that fails, then clear the fast string
+	 * and enhanced fast string CPU capabilities.
 	 */
 	if (c->x86 > 6 || (c->x86 == 6 && c->x86_model >= 0xd)) {
 		rdmsrl(MSR_IA32_MISC_ENABLE, misc_enable);
+
+		if (allow_fast_string &&
+		    !(misc_enable & MSR_IA32_MISC_ENABLE_FAST_STRING)) {
+			misc_enable |= MSR_IA32_MISC_ENABLE_FAST_STRING;
+			wrmsrl_safe(MSR_IA32_MISC_ENABLE, misc_enable);
+
+			/* Re-read to make sure it stuck. */
+			rdmsrl(MSR_IA32_MISC_ENABLE, misc_enable);
+
+			if (misc_enable & MSR_IA32_MISC_ENABLE_FAST_STRING)
+				printk_once(KERN_INFO FW_WARN "IA32_MISC_ENABLE.FAST_STRING_ENABLE was not set\n");
+		}
+
 		if (!(misc_enable & MSR_IA32_MISC_ENABLE_FAST_STRING)) {
-			printk(KERN_INFO "Disabled fast string operations\n");
+			if (allow_fast_string)
+				printk(KERN_INFO "Failed to enable fast string operations\n");
 			setup_clear_cpu_cap(X86_FEATURE_REP_GOOD);
 			setup_clear_cpu_cap(X86_FEATURE_ERMS);
 		}
diff -ruw linux-4.2/arch/x86/kernel/early_printk.c linux-4.2-fbx/arch/x86/kernel/early_printk.c
--- linux-4.2/arch/x86/kernel/early_printk.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/arch/x86/kernel/early_printk.c	2015-09-15 19:18:36.586446304 +0200
@@ -133,7 +133,9 @@
 	unsigned char c;
 
 	serial_out(early_serial_base, LCR, 0x3);	/* 8n1 */
+#ifndef CONFIG_X86_INTEL_CE
 	serial_out(early_serial_base, IER, 0);	/* no interrupt */
+#endif
 	serial_out(early_serial_base, FCR, 0);	/* no fifo */
 	serial_out(early_serial_base, MCR, 0x3);	/* DTR + RTS */
 
@@ -182,7 +184,11 @@
 	}
 
 	/* Convert from baud to divisor value */
+#ifdef CONFIG_X86_INTEL_CE
+	divisor = 921600 / baud;
+#else
 	divisor = 115200 / baud;
+#endif
 
 	/* These will always be IO based ports */
 	serial_in = io_serial_in;
diff -ruw linux-4.2/arch/x86/kernel/head32.c linux-4.2-fbx/arch/x86/kernel/head32.c
--- linux-4.2/arch/x86/kernel/head32.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/arch/x86/kernel/head32.c	2015-09-15 19:18:36.586446304 +0200
@@ -34,6 +34,13 @@
 	cr4_init_shadow();
 	sanitize_boot_params(&boot_params);
 
+#ifdef CONFIG_FBX6HD
+	/* bootloader does not set subarch correctly, so we can't
+	 * compile generic kernels, though we may be able to detect
+	 * ce4100 at runtime */
+	boot_params.hdr.hardware_subarch = X86_SUBARCH_CE4100;
+#endif
+
 	/* Call the subarch specific early setup function */
 	switch (boot_params.hdr.hardware_subarch) {
 	case X86_SUBARCH_INTEL_MID:
diff -ruw linux-4.2/arch/x86/kernel/Makefile linux-4.2-fbx/arch/x86/kernel/Makefile
--- linux-4.2/arch/x86/kernel/Makefile	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/arch/x86/kernel/Makefile	2015-09-15 19:18:36.562446154 +0200
@@ -79,6 +79,7 @@
 obj-$(CONFIG_KGDB)		+= kgdb.o
 obj-$(CONFIG_VM86)		+= vm86_32.o
 obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
+obj-$(CONFIG_ARCH_GEN3)		+= i2c-intelce.o
 
 obj-$(CONFIG_HPET_TIMER) 	+= hpet.o
 obj-$(CONFIG_APB_TIMER)		+= apb_timer.o
@@ -110,6 +111,9 @@
 obj-$(CONFIG_IOSF_MBI)			+= iosf_mbi.o
 obj-$(CONFIG_PMC_ATOM)			+= pmc_atom.o
 
+obj-$(CONFIG_FBXSERIAL)			+= fbxserial.o
+obj-y					+= fbxbootinfo.o
+
 ###
 # 64 bit specific files
 ifeq ($(CONFIG_X86_64),y)
diff -ruw linux-4.2/arch/x86/kernel/reboot_fixups_32.c linux-4.2-fbx/arch/x86/kernel/reboot_fixups_32.c
--- linux-4.2/arch/x86/kernel/reboot_fixups_32.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/arch/x86/kernel/reboot_fixups_32.c	2015-09-15 19:18:36.594446354 +0200
@@ -8,6 +8,7 @@
  */
 
 #include <asm/delay.h>
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <asm/reboot_fixups.h>
@@ -16,6 +17,11 @@
 
 static void cs5530a_warm_reset(struct pci_dev *dev)
 {
+	if (in_interrupt()) {
+		printk("cs5530a_warm_reset(): can't reboot: can't access "
+		       "PCI config space from IRQ.\n");
+		return ;
+	}
 	/* writing 1 to the reset control register, 0x44 causes the
 	cs5530a to perform a system warm reset */
 	pci_write_config_byte(dev, 0x44, 0x1);
@@ -57,6 +63,7 @@
 	unsigned int vendor;
 	unsigned int device;
 	void (*reboot_fixup)(struct pci_dev *);
+	struct pci_dev *dev;
 };
 
 /*
@@ -64,7 +71,7 @@
  */
 #define PCI_DEVICE_ID_INTEL_CE4100	0x0708
 
-static const struct device_fixup fixups_table[] = {
+static struct device_fixup fixups_table[] = {
 { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, cs5530a_warm_reset },
 { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, cs5536_warm_reset },
 { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE, cs5530a_warm_reset },
@@ -81,22 +88,29 @@
 void mach_reboot_fixups(void)
 {
 	const struct device_fixup *cur;
-	struct pci_dev *dev;
 	int i;
 
-	/* we can be called from sysrq-B code. In such a case it is
-	 * prohibited to dig PCI */
-	if (in_interrupt())
-		return;
+	for (i = 0; i < ARRAY_SIZE(fixups_table); ++i) {
+		cur = &fixups_table[i];
+		if (cur->dev)
+			cur->reboot_fixup(cur->dev);
+	}
+}
+
+static int mach_reboot_fixups_init(void)
+{
+	struct pci_dev *dev;
+	struct device_fixup *cur;
+	int i;
 
 	for (i=0; i < ARRAY_SIZE(fixups_table); i++) {
-		cur = &(fixups_table[i]);
+		cur = &fixups_table[i];
 		dev = pci_get_device(cur->vendor, cur->device, NULL);
 		if (!dev)
 			continue;
 
-		cur->reboot_fixup(dev);
-		pci_dev_put(dev);
+		cur->dev = dev;
 	}
+	return 0;
 }
-
+module_init(mach_reboot_fixups_init);
diff -ruw linux-4.2/arch/x86/kernel/setup.c linux-4.2-fbx/arch/x86/kernel/setup.c
--- linux-4.2/arch/x86/kernel/setup.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/arch/x86/kernel/setup.c	2015-09-15 19:18:36.594446354 +0200
@@ -430,6 +430,11 @@
 	struct setup_data *data;
 	u64 pa_data, pa_next;
 
+#ifdef CONFIG_FBXSERIAL
+	extern void parse_fbxserial_ext(u64 phys_addr, u32 data_len);
+#endif
+	extern void parse_fbxbootinfo(u64 phys_addr, u32 data_len);
+
 	pa_data = boot_params.hdr.setup_data;
 	while (pa_data) {
 		u32 data_len, data_type;
@@ -450,6 +455,14 @@
 		case SETUP_EFI:
 			parse_efi_setup(pa_data, data_len);
 			break;
+#ifdef CONFIG_FBXSERIAL
+		case SETUP_FBXSERIAL_EXT:
+			parse_fbxserial_ext(pa_data, data_len);
+			break;
+#endif
+		case SETUP_FBXBOOTINFO:
+			parse_fbxbootinfo(pa_data, data_len);
+			break;
 		default:
 			break;
 		}
diff -ruw linux-4.2/arch/x86/platform/ce4100/ce4100.c linux-4.2-fbx/arch/x86/platform/ce4100/ce4100.c
--- linux-4.2/arch/x86/platform/ce4100/ce4100.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/arch/x86/platform/ce4100/ce4100.c	2015-09-15 19:18:36.622446529 +0200
@@ -16,6 +16,11 @@
 #include <linux/serial_reg.h>
 #include <linux/serial_8250.h>
 #include <linux/reboot.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pstore_ram.h>
+#include <linux/sizes.h>
 
 #include <asm/ce4100.h>
 #include <asm/prom.h>
@@ -140,10 +145,96 @@
 	x86_of_pci_init();
 }
 
+
+#ifdef CONFIG_FBX6HD
+/*
+ * reserve top of RAM - 16K for crash_zone.
+ */
+#define FBX6HD_CRASHZONE_SIZE	(SZ_16K)
+#define FBX6HD_CRASHZONE_BASE  (SZ_1G - FBX6HD_CRASHZONE_SIZE)
+
+static struct ramoops_platform_data ramoops_data = {
+        .mem_size		= FBX6HD_CRASHZONE_SIZE,
+        .mem_address		= FBX6HD_CRASHZONE_BASE,
+        .record_size		= SZ_16K,
+        .dump_oops		= 1,
+	.ecc_info = {
+		.ecc_size	= 1,
+	},
+};
+
+static struct platform_device ramoops_dev = {
+        .name = "ramoops",
+        .dev = {
+                .platform_data = &ramoops_data,
+        },
+};
+
+static void __init fbx6hd_init_ramoops(void)
+{
+	platform_device_register(&ramoops_dev);
+}
+
+static const struct of_device_id remoti_ids[] __initdata = {
+	{ .compatible = "ti,remoti" },
+	{ /* sentinel */ },
+};
+
+extern int sdv_i2c_fixup_ck505(void);
+
+static int __init fbx6hd_init(void)
+{
+	int ret;
+
+	panic_timeout = 10;
+
+	ret = of_platform_bus_probe(NULL, remoti_ids, NULL);
+	if (ret) {
+		pr_err("failed to probe remoti platform bus\n");
+		return ret;
+	}
+
+	fbx6hd_init_ramoops();
+
+	return ret;
+}
+
+arch_initcall(fbx6hd_init);
+
+static char *__init fbx6hd_memory_setup(void)
+{
+	char *who = "fbx-rammap";
+	u64 usable_mem_size;
+
+	/* BIOS does not report correct ram size */
+	usable_mem_size = 1024 << 20;
+
+	/*
+	 * acpi tables are at 0x10000
+	 * uc8051 code is running at 0x40000
+	 */
+	e820_add_region(0x10000, 0x10000, E820_ACPI);
+	e820_add_region(0x20000, 0x40000 - 0x20000, E820_RAM);
+	e820_add_region(0x50000, 0x98000 - 0x50000, E820_RAM);
+	e820_add_region(HIGH_MEMORY, usable_mem_size - HIGH_MEMORY, E820_RAM);
+
+	return who;
+}
+
+static void __init fbx6hd_fixup_ck505(void)
+{
+	sdv_i2c_fixup_ck505();
+}
+#endif
+
 /*
  * CE4100 specific x86_init function overrides and early setup
  * calls.
  */
+#ifdef CONFIG_OF_EARLY_FLATTREE
+extern void *__dtb_start;
+#endif
+
 void __init x86_ce4100_early_setup(void)
 {
 	x86_init.oem.arch_setup = sdv_arch_setup;
@@ -164,5 +255,18 @@
 	 */
 	reboot_type = BOOT_KBD;
 
+#ifdef CONFIG_FBX6HD
+	/* our crappy firmware does not pass a valid e820 map, so
+	 * fixup manually */
+	x86_init.resources.memory_setup = fbx6hd_memory_setup;
+
+	/* early fixup of clock */
+	x86_init.timers.tsc_pre_init = fbx6hd_fixup_ck505;
+#endif
+
+#ifdef CONFIG_OF_EARLY_FLATTREE
+	initial_dtb = __pa(&__dtb_start);
+#endif
+
 	pm_power_off = ce4100_power_off;
 }
diff -ruw linux-4.2/arch/x86/platform/ce4100/Makefile linux-4.2-fbx/arch/x86/platform/ce4100/Makefile
--- linux-4.2/arch/x86/platform/ce4100/Makefile	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/arch/x86/platform/ce4100/Makefile	2013-12-04 14:33:18.619478968 +0100
@@ -1 +1,8 @@
 obj-$(CONFIG_X86_INTEL_CE)	+= ce4100.o
+
+obj-$(CONFIG_FBX6HD)		+= fbx6hd.dtb.o i2c-intelce.o
+
+clean-files := *dtb.S
+
+$(obj)/%.dtb: $(src)/%.dts
+	$(call cmd,dtc)
diff -ruw linux-4.2/block/blk-core.c linux-4.2-fbx/block/blk-core.c
--- linux-4.2/block/blk-core.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/block/blk-core.c	2015-09-15 19:18:36.646446678 +0200
@@ -2175,7 +2175,7 @@
 	}
 }
 
-void blk_account_io_done(struct request *req)
+void blk_account_io_done(struct request *req, int error)
 {
 	/*
 	 * Account IO completion.  flush_rq isn't accounted as a
@@ -2191,6 +2191,8 @@
 		cpu = part_stat_lock();
 		part = req->part;
 
+		if (error < 0)
+			part_stat_inc(cpu, part, io_errors[rw]);
 		part_stat_inc(cpu, part, ios[rw]);
 		part_stat_add(cpu, part, ticks[rw], duration);
 		part_round_stats(cpu, part);
@@ -2634,7 +2636,7 @@
 	if (req->cmd_flags & REQ_DONTPREP)
 		blk_unprep_request(req);
 
-	blk_account_io_done(req);
+	blk_account_io_done(req, error);
 
 	if (req->end_io)
 		req->end_io(req, error);
diff -ruw linux-4.2/block/blk.h linux-4.2-fbx/block/blk.h
--- linux-4.2/block/blk.h	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/block/blk.h	2015-09-15 19:18:36.650446703 +0200
@@ -83,7 +83,7 @@
 
 void blk_account_io_start(struct request *req, bool new_io);
 void blk_account_io_completion(struct request *req, unsigned int bytes);
-void blk_account_io_done(struct request *req);
+void blk_account_io_done(struct request *req, int error);
 
 /*
  * Internal atomic flags for request handling
diff -ruw linux-4.2/block/blk-mq.c linux-4.2-fbx/block/blk-mq.c
--- linux-4.2/block/blk-mq.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/block/blk-mq.c	2015-09-15 19:18:36.650446703 +0200
@@ -322,7 +322,7 @@
 
 inline void __blk_mq_end_request(struct request *rq, int error)
 {
-	blk_account_io_done(rq);
+	blk_account_io_done(rq, error);
 
 	if (rq->end_io) {
 		rq->end_io(rq, error);
diff -ruw linux-4.2/block/partition-generic.c linux-4.2-fbx/block/partition-generic.c
--- linux-4.2/block/partition-generic.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/block/partition-generic.c	2015-09-15 19:18:36.654446728 +0200
@@ -120,7 +120,7 @@
 	return sprintf(buf,
 		"%8lu %8lu %8llu %8u "
 		"%8lu %8lu %8llu %8u "
-		"%8u %8u %8u"
+		"%8u %8u %8u %8lu %lu"
 		"\n",
 		part_stat_read(p, ios[READ]),
 		part_stat_read(p, merges[READ]),
@@ -132,7 +132,9 @@
 		jiffies_to_msecs(part_stat_read(p, ticks[WRITE])),
 		part_in_flight(p),
 		jiffies_to_msecs(part_stat_read(p, io_ticks)),
-		jiffies_to_msecs(part_stat_read(p, time_in_queue)));
+		jiffies_to_msecs(part_stat_read(p, time_in_queue)),
+		part_stat_read(p, io_errors[READ]),
+		part_stat_read(p, io_errors[WRITE]));
 }
 
 ssize_t part_inflight_show(struct device *dev,
diff -ruw linux-4.2/crypto/algboss.c linux-4.2-fbx/crypto/algboss.c
--- linux-4.2/crypto/algboss.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/crypto/algboss.c	2013-12-04 14:33:18.663478969 +0100
@@ -221,7 +221,9 @@
 	if (type & CRYPTO_ALG_TESTED)
 		goto skiptest;
 
+#ifdef CONFIG_CRYPTO_BUILTIN_TEST
 	err = alg_test(param->driver, param->alg, type, CRYPTO_ALG_TESTED);
+#endif
 
 skiptest:
 	crypto_alg_tested(param->driver, err);
diff -ruw linux-4.2/crypto/Kconfig linux-4.2-fbx/crypto/Kconfig
--- linux-4.2/crypto/Kconfig	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/crypto/Kconfig	2015-09-15 19:18:36.658446753 +0200
@@ -108,6 +108,10 @@
 	help
 	  Generic implementation of the RSA public key algorithm.
 
+config CRYPTO_BUILTIN_TEST
+	bool "Include builtin tests"
+	default y
+
 config CRYPTO_MANAGER
 	tristate "Cryptographic algorithm manager"
 	select CRYPTO_MANAGER2
diff -ruw linux-4.2/crypto/Makefile linux-4.2-fbx/crypto/Makefile
--- linux-4.2/crypto/Makefile	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/crypto/Makefile	2015-09-15 19:18:36.658446753 +0200
@@ -38,7 +38,10 @@
 rsa_generic-y += rsa_helper.o
 obj-$(CONFIG_CRYPTO_RSA) += rsa_generic.o
 
-cryptomgr-y := algboss.o testmgr.o
+cryptomgr-y := algboss.o
+ifeq ($(CONFIG_CRYPTO_BUILTIN_TEST),y)
+cryptomgr-y += testmgr.o
+endif
 
 obj-$(CONFIG_CRYPTO_MANAGER2) += cryptomgr.o
 obj-$(CONFIG_CRYPTO_USER) += crypto_user.o
diff -ruw linux-4.2/drivers/ata/libata-core.c linux-4.2-fbx/drivers/ata/libata-core.c
--- linux-4.2/drivers/ata/libata-core.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/ata/libata-core.c	2015-09-15 19:18:36.734447227 +0200
@@ -4180,6 +4180,8 @@
 	/* https://bugzilla.kernel.org/show_bug.cgi?id=15573 */
 	{ "C300-CTFDDAC128MAG",	"0001",		ATA_HORKAGE_NONCQ, },
 
+	{ "Boot ROM", 		NULL,		ATA_HORKAGE_NODMA  },
+
 	/* devices which puke on READ_NATIVE_MAX */
 	{ "HDS724040KLSA80",	"KFAOA20N",	ATA_HORKAGE_BROKEN_HPA, },
 	{ "WDC WD3200JD-00KLB0", "WD-WCAMR1130137", ATA_HORKAGE_BROKEN_HPA },
diff -ruw linux-4.2/drivers/ata/libata-scsi.c linux-4.2-fbx/drivers/ata/libata-scsi.c
--- linux-4.2/drivers/ata/libata-scsi.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/ata/libata-scsi.c	2015-09-15 19:18:36.734447227 +0200
@@ -3693,7 +3693,7 @@
 			goto err_add;
 
 		rc = scsi_add_host_with_dma(ap->scsi_host,
-						&ap->tdev, ap->host->dev);
+					    host->dev, host->dev);
 		if (rc)
 			goto err_add;
 	}
diff -ruw linux-4.2/drivers/base/firmware_class.c linux-4.2-fbx/drivers/base/firmware_class.c
--- linux-4.2/drivers/base/firmware_class.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/base/firmware_class.c	2015-09-15 19:18:36.766447427 +0200
@@ -280,7 +280,8 @@
 	"/lib/firmware/updates/" UTS_RELEASE,
 	"/lib/firmware/updates",
 	"/lib/firmware/" UTS_RELEASE,
-	"/lib/firmware"
+	"/lib/firmware",
+	"/usr/lib/hotplug/firmware"
 };
 
 /*
diff -ruw linux-4.2/drivers/char/Kconfig linux-4.2-fbx/drivers/char/Kconfig
--- linux-4.2/drivers/char/Kconfig	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/char/Kconfig	2015-09-15 19:18:36.814447726 +0200
@@ -24,6 +24,15 @@
 	  kind of kernel debugging operations.
 	  When in doubt, say "N".
 
+config DEVPHYSMEM
+	bool "/dev/physmem virtual device support"
+	default n
+	help
+	  Say Y here if you want to support the /dev/physmem device. The
+	  /dev/physmem device allows unprivileged access to physical memory
+	  unused by the kernel.
+	  When in doubt, say "N".
+
 config SGI_SNSC
 	bool "SGI Altix system controller communication support"
 	depends on (IA64_SGI_SN2 || IA64_GENERIC)
diff -ruw linux-4.2/drivers/char/mem.c linux-4.2-fbx/drivers/char/mem.c
--- linux-4.2/drivers/char/mem.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/char/mem.c	2015-09-15 19:18:36.826447801 +0200
@@ -27,6 +27,7 @@
 #include <linux/export.h>
 #include <linux/io.h>
 #include <linux/uio.h>
+#include <linux/bootmem.h>
 
 #include <linux/uaccess.h>
 
@@ -373,6 +374,14 @@
 	return mmap_mem(file, vma);
 }
 
+static int mmap_physmem(struct file * file, struct vm_area_struct * vma)
+{
+	if (vma->vm_pgoff < max_pfn && !capable(CAP_SYS_RAWIO))
+		return -EPERM;
+
+	return mmap_mem(file, vma);
+}
+
 /*
  * This function reads the *virtual* memory as seen by the kernel.
  */
@@ -715,6 +724,11 @@
 	return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
 }
 
+static int open_physmem(struct inode * inode, struct file * filp)
+{
+	return 0;
+}
+
 #define zero_lseek	null_lseek
 #define full_lseek      null_lseek
 #define write_zero	write_null
@@ -779,6 +793,14 @@
 	.write		= write_full,
 };
 
+static const struct file_operations __maybe_unused physmem_fops = {
+	.mmap		= mmap_physmem,
+	.open		= open_physmem,
+#ifndef CONFIG_MMU
+	.get_unmapped_area = get_unmapped_area_mem,
+#endif
+};
+
 static const struct memdev {
 	const char *name;
 	umode_t mode;
@@ -802,6 +824,9 @@
 #ifdef CONFIG_PRINTK
 	[11] = { "kmsg", 0644, &kmsg_fops, 0 },
 #endif
+#ifdef CONFIG_DEVPHYSMEM
+	[16] = { "physmem", 0, &physmem_fops, FMODE_UNSIGNED_OFFSET },
+#endif
 };
 
 static int memory_open(struct inode *inode, struct file *filp)
diff -ruw linux-4.2/drivers/hid/hid-core.c linux-4.2-fbx/drivers/hid/hid-core.c
--- linux-4.2/drivers/hid/hid-core.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/hid/hid-core.c	2015-09-15 19:18:37.322450895 +0200
@@ -2025,6 +2025,7 @@
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_RAZER, USB_DEVICE_ID_RAZER_BLADE_14) },
+	{ HID_BLUETOOTH_DEVICE(0x10eb, 0x0023) },
 	{ }
 };
 
diff -ruw linux-4.2/drivers/hid/hid-dr.c linux-4.2-fbx/drivers/hid/hid-dr.c
--- linux-4.2/drivers/hid/hid-dr.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/hid/hid-dr.c	2013-12-04 14:33:19.091478975 +0100
@@ -234,6 +234,75 @@
 	0xC0                /*  End Collection                  */
 };
 
+/* Size of the original descriptor of the PID 0x0006 joystick */
+#define PID0006_RDESC_ORIG_SIZE	101
+
+/* Fixed report descriptor for PID 0x006 joystick */
+static __u8 pid0006_rdesc_fixed[] = {
+	0x05, 0x01,         /*  Usage Page (Desktop),                   */
+	0x09, 0x04,         /*  Usage (Joystik),                        */
+	0xA1, 0x01,         /*  Collection (Application),               */
+	0xA1, 0x02,         /*      Collection (Logical),               */
+	0x75, 0x08,         /*          Report Size (8),                */
+	0x95, 0x02,         /*          Report Count (2),               */
+	0x15, 0x00,         /*          Logical Minimum (0),            */
+	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),          */
+	0x35, 0x00,         /*          Physical Minimum (0),           */
+	0x46, 0xFF, 0x00,   /*          Physical Maximum (255),         */
+	0x09, 0x30,         /*          Usage (X),                      */
+	0x09, 0x31,         /*          Usage (Y),                      */
+	0x81, 0x02,         /*          Input (Variable),               */
+
+	/* Ignore noisy input */
+	0x75, 0x08,         /*          Report Size (8),                */
+	0x95, 0x01,         /*          Report Count (1),               */
+	0x81, 0x01,         /*          Input (Constant),       */
+
+	0x75, 0x08,         /*          Report Size (8),                */
+	0x95, 0x02,         /*          Report Count (2),               */
+	0x15, 0x00,         /*          Logical Minimum (0),            */
+	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),          */
+	0x35, 0x00,         /*          Physical Minimum (0),           */
+	0x46, 0xFF, 0x00,   /*          Physical Maximum (255),         */
+	0x09, 0x30,         /*          Usage (X),                      */
+	0x09, 0x31,         /*          Usage (Y),                      */
+	0x81, 0x02,         /*          Input (Variable),               */
+
+	0x75, 0x04,         /*          Report Size (4),                */
+	0x95, 0x01,         /*          Report Count (1),               */
+	0x25, 0x07,         /*          Logical Maximum (7),            */
+	0x46, 0x3B, 0x01,   /*          Physical Maximum (315),         */
+	0x65, 0x14,         /*          Unit (Degrees),                 */
+	0x09, 0x39,         /*          Usage (Hat Switch),             */
+	0x81, 0x42,         /*          Input (Variable, Null State),   */
+	0x65, 0x00,         /*          Unit,                           */
+	0x75, 0x01,         /*          Report Size (1),                */
+	0x95, 0x0C,         /*          Report Count (12),              */
+	0x25, 0x01,         /*          Logical Maximum (1),            */
+	0x45, 0x01,         /*          Physical Maximum (1),           */
+	0x05, 0x09,         /*          Usage Page (Button),            */
+	0x19, 0x01,         /*          Usage Minimum (01h),            */
+	0x29, 0x0C,         /*          Usage Maximum (0Ch),            */
+	0x81, 0x02,         /*          Input (Variable),               */
+	0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),             */
+	0x75, 0x01,         /*          Report Size (1),                */
+	0x95, 0x08,         /*          Report Count (8),               */
+	0x25, 0x01,         /*          Logical Maximum (1),            */
+	0x45, 0x01,         /*          Physical Maximum (1),           */
+	0x09, 0x01,         /*          Usage (01h),                    */
+	0x81, 0x02,         /*          Input (Variable),               */
+	0xC0,               /*      End Collection,                     */
+	0xA1, 0x02,         /*      Collection (Logical),               */
+	0x75, 0x08,         /*          Report Size (8),                */
+	0x95, 0x07,         /*          Report Count (7),               */
+	0x46, 0xFF, 0x00,   /*          Physical Maximum (255),         */
+	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),          */
+	0x09, 0x02,         /*          Usage (02h),                    */
+	0x91, 0x02,         /*          Output (Variable),              */
+	0xC0,               /*      End Collection,                     */
+	0xC0                /*  End Collection                          */
+};
+
 static __u8 *dr_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 				unsigned int *rsize)
 {
@@ -244,6 +313,12 @@
 			*rsize = sizeof(pid0011_rdesc_fixed);
 		}
 		break;
+	case 0x0006:
+		if (*rsize == PID0006_RDESC_ORIG_SIZE) {
+			rdesc = pid0006_rdesc_fixed;
+			*rsize = sizeof(pid0006_rdesc_fixed);
+		}
+		break;
 	}
 	return rdesc;
 }
@@ -268,6 +343,7 @@
 
 	switch (hdev->product) {
 	case 0x0006:
+		strcpy(hdev->name, "Freebox Gamepad");
 		ret = drff_init(hdev);
 		if (ret) {
 			dev_err(&hdev->dev, "force feedback init failed\n");
diff -ruw linux-4.2/drivers/hid/Kconfig linux-4.2-fbx/drivers/hid/Kconfig
--- linux-4.2/drivers/hid/Kconfig	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/hid/Kconfig	2015-09-15 19:18:37.318450870 +0200
@@ -316,6 +316,10 @@
 	---help---
 	Support for Waltop tablets.
 
+config HID_FBX_REMOTE_AUDIO
+	tristate "Freebox BLE remote audio driver"
+	depends on HID && SND_PCM
+
 config HID_GYRATION
 	tristate "Gyration remote control"
 	depends on HID
diff -ruw linux-4.2/drivers/hid/Makefile linux-4.2-fbx/drivers/hid/Makefile
--- linux-4.2/drivers/hid/Makefile	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/hid/Makefile	2015-09-15 19:18:37.318450870 +0200
@@ -37,6 +37,7 @@
 obj-$(CONFIG_HID_ELO)		+= hid-elo.o
 obj-$(CONFIG_HID_EZKEY)		+= hid-ezkey.o
 obj-$(CONFIG_HID_GT683R)	+= hid-gt683r.o
+obj-$(CONFIG_HID_FBX_REMOTE_AUDIO)	+= hid-fbx-remote-audio.o
 obj-$(CONFIG_HID_GYRATION)	+= hid-gyration.o
 obj-$(CONFIG_HID_HOLTEK)	+= hid-holtek-kbd.o
 obj-$(CONFIG_HID_HOLTEK)	+= hid-holtek-mouse.o
diff -ruw linux-4.2/drivers/hwmon/adt7475.c linux-4.2-fbx/drivers/hwmon/adt7475.c
--- linux-4.2/drivers/hwmon/adt7475.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/hwmon/adt7475.c	2015-09-15 19:18:37.346451045 +0200
@@ -124,7 +124,19 @@
 
 /* Macro to read the registers */
 
-#define adt7475_read(reg) i2c_smbus_read_byte_data(client, (reg))
+static inline s32 __adt7475_read(const struct i2c_client *client, u8 cmd)
+{
+	s32 ret;
+
+	ret = i2c_smbus_read_byte_data(client, cmd);
+	if (ret < 0) {
+		printk("__adt7475_read error: %d\n", ret);
+		return 0;
+	}
+	return ret;
+}
+
+#define adt7475_read(reg) __adt7475_read(client, (reg))
 
 /* Macros to easily index the registers */
 
@@ -278,6 +290,9 @@
 {
 	u16 val;
 
+	if (need_resched())
+		yield();
+
 	val = i2c_smbus_read_byte_data(client, reg);
 	val |= (i2c_smbus_read_byte_data(client, reg + 1) << 8);
 
@@ -846,7 +861,7 @@
 
 	data->range[sattr->index] =
 		adt7475_read(TEMP_TRANGE_REG(sattr->index));
-	data->range[sattr->index] &= ~7;
+	data->range[sattr->index] &= ~0xf;
 	data->range[sattr->index] |= out;
 
 	i2c_smbus_write_byte_data(client, TEMP_TRANGE_REG(sattr->index),
diff -ruw linux-4.2/drivers/hwmon/Kconfig linux-4.2-fbx/drivers/hwmon/Kconfig
--- linux-4.2/drivers/hwmon/Kconfig	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/hwmon/Kconfig	2015-09-15 19:18:37.342451020 +0200
@@ -1736,6 +1736,10 @@
 	  This driver provides support for the Ultra45 workstation environmental
 	  sensors.
 
+config SENSORS_KIRKWOOD_CORETEMP
+	tristate "Kirkwood core temperature censor"
+	depends on ARCH_KIRKWOOD
+
 if ACPI
 
 comment "ACPI drivers"
diff -ruw linux-4.2/drivers/hwmon/lm85.c linux-4.2-fbx/drivers/hwmon/lm85.c
--- linux-4.2/drivers/hwmon/lm85.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/hwmon/lm85.c	2015-09-25 18:25:55.068110313 +0200
@@ -196,13 +196,13 @@
 #define RANGE_FROM_REG(val)	lm85_range_map[(val) & 0x0f]
 
 /* These are the PWM frequency encodings */
-static const int lm85_freq_map[8] = { /* 1 Hz */
-	10, 15, 23, 30, 38, 47, 61, 94
+static const int lm85_freq_map[11] = { /* 1 Hz */
+	10, 15, 23, 30, 38, 47, 61, 94, 94, 94, 94
 };
-static const int adm1027_freq_map[8] = { /* 1 Hz */
-	11, 15, 22, 29, 35, 44, 59, 88
+static const int adm1027_freq_map[11] = { /* 1 Hz */
+	11, 15, 22, 29, 35, 44, 59, 88, 88, 88, 25000
 };
-#define FREQ_MAP_LEN	8
+#define FREQ_MAP_LEN	11
 
 static int FREQ_TO_REG(const int *map,
 		       unsigned int map_size, unsigned long freq)
@@ -212,7 +212,7 @@
 
 static int FREQ_FROM_REG(const int *map, u8 reg)
 {
-	return map[reg & 0x07];
+	return map[reg & 0x0f];
 }
 
 /*
@@ -512,7 +512,7 @@
 			data->autofan[i].config =
 			    lm85_read_value(client, LM85_REG_AFAN_CONFIG(i));
 			val = lm85_read_value(client, LM85_REG_AFAN_RANGE(i));
-			data->pwm_freq[i] = val & 0x07;
+			data->pwm_freq[i] = val & 0x0f;
 			data->zone[i].range = val >> 4;
 			data->autofan[i].min_pwm =
 			    lm85_read_value(client, LM85_REG_AFAN_MINPWM(i));
@@ -1194,7 +1194,7 @@
 		TEMP_FROM_REG(data->zone[nr].limit));
 	lm85_write_value(client, LM85_REG_AFAN_RANGE(nr),
 		((data->zone[nr].range & 0x0f) << 4)
-		| (data->pwm_freq[nr] & 0x07));
+		| (data->pwm_freq[nr] & 0x0f));
 
 	mutex_unlock(&data->update_lock);
 	return count;
@@ -1230,7 +1230,7 @@
 		val - min);
 	lm85_write_value(client, LM85_REG_AFAN_RANGE(nr),
 		((data->zone[nr].range & 0x0f) << 4)
-		| (data->pwm_freq[nr] & 0x07));
+		| (data->pwm_freq[nr] & 0x0f));
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -1419,10 +1419,28 @@
 	.attrs = lm85_attributes_in567,
 };
 
-static void lm85_init_client(struct i2c_client *client)
+static void lm85_init_client(struct i2c_client *client, struct lm85_data *data)
 {
 	int value;
 
+	/* workaround for emc2300 (emc6d103s), when auto temp min is
+	 * the default value, pwm can never be controlled manually, so
+	 * change this */
+	if (data->type == emc6d103s) {
+		int nr;
+
+		for (nr = 0; nr < 3; nr++) {
+			data->zone[nr].limit = TEMP_TO_REG(-127000);
+			lm85_write_value(client, LM85_REG_AFAN_LIMIT(nr),
+					 data->zone[nr].limit);
+
+			/* also force high frequency */
+			data->pwm_freq[nr] = 0xa;
+			lm85_write_value(client, LM85_REG_AFAN_RANGE(nr),
+					 data->pwm_freq[nr]);
+		}
+	}
+
 	/* Start monitoring if needed */
 	value = lm85_read_value(client, LM85_REG_CONFIG);
 	if (!(value & 0x01)) {
@@ -1573,7 +1591,7 @@
 	data->vrm = vid_which_vrm();
 
 	/* Initialize the LM85 chip */
-	lm85_init_client(client);
+	lm85_init_client(client, data);
 
 	/* sysfs hooks */
 	data->groups[idx++] = &lm85_group;
diff -ruw linux-4.2/drivers/hwmon/Makefile linux-4.2-fbx/drivers/hwmon/Makefile
--- linux-4.2/drivers/hwmon/Makefile	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/hwmon/Makefile	2015-09-15 19:18:37.342451020 +0200
@@ -158,6 +158,7 @@
 obj-$(CONFIG_SENSORS_W83L786NG)	+= w83l786ng.o
 obj-$(CONFIG_SENSORS_WM831X)	+= wm831x-hwmon.o
 obj-$(CONFIG_SENSORS_WM8350)	+= wm8350-hwmon.o
+obj-$(CONFIG_SENSORS_KIRKWOOD_CORETEMP)+= kirkwood-coretemp.o
 
 obj-$(CONFIG_PMBUS)		+= pmbus/
 
diff -ruw linux-4.2/drivers/i2c/busses/i2c-pxa.c linux-4.2-fbx/drivers/i2c/busses/i2c-pxa.c
--- linux-4.2/drivers/i2c/busses/i2c-pxa.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/i2c/busses/i2c-pxa.c	2015-09-15 19:18:37.390451319 +0200
@@ -835,6 +835,16 @@
 		if (ret != I2C_RETRY)
 			goto out;
 
+		if (i == 1 &&
+		    (readl(_ISR(i2c)) & ISR_UB) &&
+		    (readl(_IBMR(i2c)) != 3)) {
+			/* last try and bus is still busy, try
+			 * reset */
+			dev_err(&i2c->adap.dev, "%s: unit still busy after "
+				"hw reset\n", __func__);
+			i2c_pxa_reset(i2c);
+		}
+
 		if (i2c_debug)
 			dev_dbg(&adap->dev, "Retrying transmission\n");
 		udelay(100);
diff -ruw linux-4.2/drivers/i2c/busses/i2c-pxa-pci.c linux-4.2-fbx/drivers/i2c/busses/i2c-pxa-pci.c
--- linux-4.2/drivers/i2c/busses/i2c-pxa-pci.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/i2c/busses/i2c-pxa-pci.c	2015-09-15 19:18:37.390451319 +0200
@@ -5,6 +5,7 @@
  */
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <linux/i2c.h>
 #include <linux/platform_device.h>
 #include <linux/i2c/pxa-i2c.h>
 #include <linux/of.h>
@@ -37,6 +38,8 @@
 	res[1].start = dev->irq;
 	res[1].end = dev->irq;
 
+	child = NULL;
+	if (dev->dev.of_node) {
 	for_each_child_of_node(dev->dev.of_node, child) {
 		const void *prop;
 		struct resource r;
@@ -65,6 +68,9 @@
 		ret = -EINVAL;
 		goto out;
 	}
+	}
+
+	pdata.class = I2C_CLASS_HWMON;
 
 	pdev = platform_device_alloc("ce4100-i2c", devnum);
 	if (!pdev) {
@@ -105,10 +111,6 @@
 	if (ret)
 		return ret;
 
-	if (!dev->dev.of_node) {
-		dev_err(&dev->dev, "Missing device tree node.\n");
-		return -EINVAL;
-	}
 	sds = kzalloc(sizeof(*sds), GFP_KERNEL);
 	if (!sds) {
 		ret = -ENOMEM;
diff -ruw linux-4.2/drivers/i2c/busses/Kconfig linux-4.2-fbx/drivers/i2c/busses/Kconfig
--- linux-4.2/drivers/i2c/busses/Kconfig	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/i2c/busses/Kconfig	2015-09-15 19:18:37.378451244 +0200
@@ -1139,6 +1139,10 @@
 	  to SLIMpro (On chip coprocessor) mailbox mechanism.
 	  If unsure, say N.
 
+config I2C_WP3
+	tristate "Wintegra WP3 I2C controll"
+	depends on WINTEGRA_WINPATH3
+
 config SCx200_ACB
 	tristate "Geode ACCESS.bus support"
 	depends on X86_32 && PCI
diff -ruw linux-4.2/drivers/i2c/busses/Makefile linux-4.2-fbx/drivers/i2c/busses/Makefile
--- linux-4.2/drivers/i2c/busses/Makefile	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/i2c/busses/Makefile	2015-09-15 19:18:37.378451244 +0200
@@ -92,6 +92,7 @@
 obj-$(CONFIG_I2C_XLR)		+= i2c-xlr.o
 obj-$(CONFIG_I2C_XLP9XX)	+= i2c-xlp9xx.o
 obj-$(CONFIG_I2C_RCAR)		+= i2c-rcar.o
+obj-$(CONFIG_I2C_WP3)		+= i2c-wp3.o
 
 # External I2C/SMBus adapter drivers
 obj-$(CONFIG_I2C_DIOLAN_U2C)	+= i2c-diolan-u2c.o
diff -ruw linux-4.2/drivers/ide/Kconfig linux-4.2-fbx/drivers/ide/Kconfig
--- linux-4.2/drivers/ide/Kconfig	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/ide/Kconfig	2015-09-15 19:18:37.398451369 +0200
@@ -684,6 +684,11 @@
        depends on BLK_DEV_IDE_AU1XXX
 endchoice
 
+config BLK_DEV_IDE_TANGO2
+	tristate "IDE for Tango2"
+	depends on TANGO2
+	select BLK_DEV_IDEDMA_SFF
+
 config BLK_DEV_IDE_TX4938
 	tristate "TX4938 internal IDE support"
 	depends on SOC_TX4938
diff -ruw linux-4.2/drivers/ide/Makefile linux-4.2-fbx/drivers/ide/Makefile
--- linux-4.2/drivers/ide/Makefile	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/ide/Makefile	2015-09-15 19:18:37.398451369 +0200
@@ -113,3 +113,4 @@
 
 obj-$(CONFIG_BLK_DEV_IDE_TX4938)	+= tx4938ide.o
 obj-$(CONFIG_BLK_DEV_IDE_TX4939)	+= tx4939ide.o
+obj-$(CONFIG_BLK_DEV_IDE_TANGO2)	+= tango2ide.o
diff -ruw linux-4.2/drivers/input/misc/Kconfig linux-4.2-fbx/drivers/input/misc/Kconfig
--- linux-4.2/drivers/input/misc/Kconfig	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/input/misc/Kconfig	2015-09-15 19:18:37.510452068 +0200
@@ -807,4 +807,9 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called drv2667-haptics.
 
+config INPUT_SMSC_CAP1066
+	tristate "SMSC CAP1066 capacitive sensor driver"
+	select I2C
+	select INPUT_POLLDEV
+
 endif
diff -ruw linux-4.2/drivers/input/misc/Makefile linux-4.2-fbx/drivers/input/misc/Makefile
--- linux-4.2/drivers/input/misc/Makefile	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/input/misc/Makefile	2015-09-15 19:18:37.510452068 +0200
@@ -76,3 +76,4 @@
 obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND)	+= xen-kbdfront.o
 obj-$(CONFIG_INPUT_YEALINK)		+= yealink.o
 obj-$(CONFIG_INPUT_IDEAPAD_SLIDEBAR)	+= ideapad_slidebar.o
+obj-$(CONFIG_INPUT_SMSC_CAP1066)	+= smsc_cap1066.o
diff -ruw linux-4.2/drivers/Kconfig linux-4.2-fbx/drivers/Kconfig
--- linux-4.2/drivers/Kconfig	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/Kconfig	2015-09-15 19:18:36.682446903 +0200
@@ -8,8 +8,12 @@
 
 source "drivers/connector/Kconfig"
 
+source "drivers/fbxprocfs/Kconfig"
+
 source "drivers/mtd/Kconfig"
 
+source "drivers/fbxmtd/Kconfig"
+
 source "drivers/of/Kconfig"
 
 source "drivers/parport/Kconfig"
@@ -64,6 +68,10 @@
 
 source "drivers/gpio/Kconfig"
 
+source "drivers/fbxgpio/Kconfig"
+
+source "drivers/fbxjtag/Kconfig"
+
 source "drivers/w1/Kconfig"
 
 source "drivers/power/Kconfig"
@@ -72,6 +80,8 @@
 
 source "drivers/thermal/Kconfig"
 
+source "drivers/fbxwatchdog/Kconfig"
+
 source "drivers/watchdog/Kconfig"
 
 source "drivers/ssb/Kconfig"
diff -ruw linux-4.2/drivers/Makefile linux-4.2-fbx/drivers/Makefile
--- linux-4.2/drivers/Makefile	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/Makefile	2015-09-15 19:18:36.682446903 +0200
@@ -14,6 +14,8 @@
 obj-y				+= pinctrl/
 obj-y				+= gpio/
 obj-y				+= pwm/
+obj-$(CONFIG_FREEBOX_GPIO)	+= fbxgpio/
+obj-$(CONFIG_FREEBOX_JTAG)	+= fbxjtag/
 obj-$(CONFIG_PCI)		+= pci/
 obj-$(CONFIG_PARISC)		+= parisc/
 obj-$(CONFIG_RAPIDIO)		+= rapidio/
@@ -84,6 +86,8 @@
 obj-$(CONFIG_VFIO)		+= vfio/
 obj-y				+= cdrom/
 obj-y				+= auxdisplay/
+
+obj-$(CONFIG_FREEBOX_MTD)	+= fbxmtd/
 obj-$(CONFIG_PCCARD)		+= pcmcia/
 obj-$(CONFIG_DIO)		+= dio/
 obj-$(CONFIG_SBUS)		+= sbus/
@@ -107,6 +111,7 @@
 obj-$(CONFIG_POWER_SUPPLY)	+= power/
 obj-$(CONFIG_HWMON)		+= hwmon/
 obj-$(CONFIG_THERMAL)		+= thermal/
+obj-$(CONFIG_FREEBOX_WATCHDOG)	+= fbxwatchdog/
 obj-$(CONFIG_WATCHDOG)		+= watchdog/
 obj-$(CONFIG_MD)		+= md/
 obj-$(CONFIG_BT)		+= bluetooth/
@@ -165,3 +170,5 @@
 obj-$(CONFIG_THUNDERBOLT)	+= thunderbolt/
 obj-$(CONFIG_CORESIGHT)		+= hwtracing/coresight/
 obj-$(CONFIG_ANDROID)		+= android/
+
+obj-$(CONFIG_FREEBOX_PROCFS)	+= fbxprocfs/
diff -ruw linux-4.2/drivers/media/dvb-core/dvb_frontend.c linux-4.2-fbx/drivers/media/dvb-core/dvb_frontend.c
--- linux-4.2/drivers/media/dvb-core/dvb_frontend.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/media/dvb-core/dvb_frontend.c	2015-09-15 19:18:37.630452816 +0200
@@ -875,6 +875,7 @@
 	if (fe->exit != DVB_FE_DEVICE_REMOVED)
 		fe->exit = DVB_FE_NORMAL_EXIT;
 	mb();
+	wake_up_all(&fepriv->events.wait_queue);
 
 	if (!fepriv->thread)
 		return;
@@ -2537,6 +2538,9 @@
 
 	poll_wait (file, &fepriv->events.wait_queue, wait);
 
+	if (fe->exit)
+		return POLLERR | POLLHUP;
+
 	if (fepriv->events.eventw != fepriv->events.eventr)
 		return (POLLIN | POLLRDNORM | POLLPRI);
 
diff -ruw linux-4.2/drivers/media/dvb-core/dvb-usb-ids.h linux-4.2-fbx/drivers/media/dvb-core/dvb-usb-ids.h
--- linux-4.2/drivers/media/dvb-core/dvb-usb-ids.h	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/media/dvb-core/dvb-usb-ids.h	2015-09-15 19:18:37.626452791 +0200
@@ -105,6 +105,7 @@
 #define USB_PID_DELOCK_USB2_DVBT			0xb803
 #define USB_PID_DIBCOM_HOOK_DEFAULT			0x0064
 #define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM		0x0065
+#define USB_PID_DIBCOM_HOOK_DEFAULT_STK7770P		0x0066
 #define USB_PID_DIBCOM_MOD3000_COLD			0x0bb8
 #define USB_PID_DIBCOM_MOD3000_WARM			0x0bb9
 #define USB_PID_DIBCOM_MOD3001_COLD			0x0bc6
diff -ruw linux-4.2/drivers/media/dvb-frontends/af9033.c linux-4.2-fbx/drivers/media/dvb-frontends/af9033.c
--- linux-4.2/drivers/media/dvb-frontends/af9033.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/media/dvb-frontends/af9033.c	2015-09-15 19:18:37.630452816 +0200
@@ -272,6 +272,22 @@
 		{ 0x800045, dev->cfg.adc_multiplier, 0xff },
 	};
 
+	/* power up tuner - for performance */
+	switch (dev->cfg.tuner) {
+	case AF9033_TUNER_IT9135_38:
+	case AF9033_TUNER_IT9135_51:
+	case AF9033_TUNER_IT9135_52:
+	case AF9033_TUNER_IT9135_60:
+	case AF9033_TUNER_IT9135_61:
+	case AF9033_TUNER_IT9135_62:
+		ret = af9033_wr_reg(dev, 0x80ec40, 0x1);
+		ret |= af9033_wr_reg(dev, 0x80fba8, 0x0);
+		ret |= af9033_wr_reg(dev, 0x80ec57, 0x0);
+		ret |= af9033_wr_reg(dev, 0x80ec58, 0x0);
+		if (ret < 0)
+			goto err;
+	}
+
 	/* program clock control */
 	clock_cw = af9033_div(dev, dev->cfg.clock, 1000000ul, 19ul);
 	buf[0] = (clock_cw >>  0) & 0xff;
@@ -450,6 +466,8 @@
 	case AF9033_TUNER_IT9135_61:
 	case AF9033_TUNER_IT9135_62:
 		ret = af9033_wr_reg(dev, 0x800000, 0x01);
+		ret |= af9033_wr_reg(dev, 0x00d827, 0x00);
+		ret |= af9033_wr_reg(dev, 0x00d829, 0x00);
 		if (ret < 0)
 			goto err;
 	}
diff -ruw linux-4.2/drivers/media/platform/Kconfig linux-4.2-fbx/drivers/media/platform/Kconfig
--- linux-4.2/drivers/media/platform/Kconfig	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/media/platform/Kconfig	2015-09-15 19:18:37.734453465 +0200
@@ -119,6 +119,7 @@
 source "drivers/media/platform/s5p-tv/Kconfig"
 source "drivers/media/platform/am437x/Kconfig"
 source "drivers/media/platform/xilinx/Kconfig"
+source "drivers/media/platform/tango2/Kconfig"
 
 endif # V4L_PLATFORM_DRIVERS
 
diff -ruw linux-4.2/drivers/media/platform/Makefile linux-4.2-fbx/drivers/media/platform/Makefile
--- linux-4.2/drivers/media/platform/Makefile	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/media/platform/Makefile	2015-09-15 19:18:37.734453465 +0200
@@ -49,6 +49,7 @@
 obj-y	+= omap/
 
 obj-$(CONFIG_VIDEO_AM437X_VPFE)		+= am437x/
+obj-$(CONFIG_DVB_TANGO2)		+= tango2/
 
 obj-$(CONFIG_VIDEO_XILINX)		+= xilinx/
 
diff -ruw linux-4.2/drivers/media/rc/ir-rc6-decoder.c linux-4.2-fbx/drivers/media/rc/ir-rc6-decoder.c
--- linux-4.2/drivers/media/rc/ir-rc6-decoder.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/media/rc/ir-rc6-decoder.c	2015-09-15 19:18:37.790453814 +0200
@@ -260,7 +260,6 @@
 				if ((scancode & RC6_6A_LCC_MASK) == RC6_6A_MCE_CC) {
 					protocol = RC_TYPE_RC6_MCE;
 					toggle = !!(scancode & RC6_6A_MCE_TOGGLE_MASK);
-					scancode &= ~RC6_6A_MCE_TOGGLE_MASK;
 				} else {
 					protocol = RC_BIT_RC6_6A_32;
 					toggle = 0;
@@ -271,6 +270,7 @@
 				goto out;
 			}
 
+			scancode &= ~RC6_6A_MCE_TOGGLE_MASK;
 			IR_dprintk(1, "RC6(6A) proto 0x%04x, scancode 0x%08x (toggle: %u)\n",
 				   protocol, scancode, toggle);
 			break;
diff -ruw linux-4.2/drivers/media/rc/keymaps/Makefile linux-4.2-fbx/drivers/media/rc/keymaps/Makefile
--- linux-4.2/drivers/media/rc/keymaps/Makefile	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/media/rc/keymaps/Makefile	2015-09-15 19:18:37.790453814 +0200
@@ -79,6 +79,7 @@
 			rc-pv951.o \
 			rc-hauppauge.o \
 			rc-rc6-mce.o \
+			rc-rc6-freebox.o \
 			rc-real-audio-220-32-keys.o \
 			rc-reddo.o \
 			rc-snapstream-firefly.o \
diff -ruw linux-4.2/drivers/media/rc/mceusb.c linux-4.2-fbx/drivers/media/rc/mceusb.c
--- linux-4.2/drivers/media/rc/mceusb.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/media/rc/mceusb.c	2015-09-15 19:18:37.798453864 +0200
@@ -200,6 +200,7 @@
 	TIVO_KIT,
 	MCE_GEN2_NO_TX,
 	HAUPPAUGE_CX_HYBRID_TV,
+	MCE_FREEBOX,
 };
 
 struct mceusb_model {
@@ -259,6 +260,11 @@
 		.mce_gen2 = 1,
 		.rc_map = RC_MAP_TIVO,
 	},
+	[MCE_FREEBOX] = {
+		.mce_gen2 = 1,
+		.no_tx = 1,
+		.rc_map = "rc-rc6-freebox",
+	}
 };
 
 static struct usb_device_id mceusb_dev_table[] = {
@@ -354,7 +360,8 @@
 	/* Formosa Industrial Computing AIM IR605/A */
 	{ USB_DEVICE(VENDOR_FORMOSA, 0xe03c) },
 	/* Formosa Industrial Computing */
-	{ USB_DEVICE(VENDOR_FORMOSA, 0xe03e) },
+	{ USB_DEVICE(VENDOR_FORMOSA, 0xe03e),
+	  .driver_info = MCE_FREEBOX },
 	/* Formosa Industrial Computing */
 	{ USB_DEVICE(VENDOR_FORMOSA, 0xe042) },
 	/* Fintek eHome Infrared Transceiver (HP branded) */
@@ -953,7 +960,7 @@
 
 	/* 2-byte return value commands */
 	case MCE_RSP_EQIRTIMEOUT:
-		ir->rc->timeout = US_TO_NS((hi << 8 | lo) * MCE_TIME_UNIT);
+		ir->rc->timeout = US_TO_NS((hi << 8 | lo) * MCE_TIME_UNIT / 1000);
 		break;
 	case MCE_RSP_EQIRNUMPORTS:
 		ir->num_txports = hi;
@@ -1231,7 +1238,7 @@
 	rc->priv = ir;
 	rc->driver_type = RC_DRIVER_IR_RAW;
 	rc->allowed_protocols = RC_BIT_ALL;
-	rc->timeout = MS_TO_NS(100);
+	rc->timeout = MS_TO_NS(50);
 	if (!ir->flags.no_tx) {
 		rc->s_tx_mask = mceusb_set_tx_mask;
 		rc->s_tx_carrier = mceusb_set_tx_carrier;
diff -ruw linux-4.2/drivers/media/tuners/it913x.c linux-4.2-fbx/drivers/media/tuners/it913x.c
--- linux-4.2/drivers/media/tuners/it913x.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/media/tuners/it913x.c	2015-09-15 19:18:37.802453889 +0200
@@ -136,18 +136,6 @@
 	if (ret)
 		goto err;
 
-	ret = regmap_write(dev->regmap, 0x80ec57, 0x00);
-	if (ret)
-		goto err;
-
-	ret = regmap_write(dev->regmap, 0x80ec58, 0x00);
-	if (ret)
-		goto err;
-
-	ret = regmap_write(dev->regmap, 0x80ec40, 0x01);
-	if (ret)
-		goto err;
-
 	dev->active = true;
 
 	return 0;
diff -ruw linux-4.2/drivers/media/usb/dvb-usb/dib0700_devices.c linux-4.2-fbx/drivers/media/usb/dvb-usb/dib0700_devices.c
--- linux-4.2/drivers/media/usb/dvb-usb/dib0700_devices.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/media/usb/dvb-usb/dib0700_devices.c	2015-09-15 19:18:37.822454014 +0200
@@ -3794,6 +3794,7 @@
 /* 80 */{ USB_DEVICE(USB_VID_ELGATO,	USB_PID_ELGATO_EYETV_DTT_2) },
 	{ USB_DEVICE(USB_VID_PCTV,      USB_PID_PCTV_2002E) },
 	{ USB_DEVICE(USB_VID_PCTV,      USB_PID_PCTV_2002E_SE) },
+	{ USB_DEVICE(USB_VID_DIBCOM,	USB_PID_DIBCOM_HOOK_DEFAULT_STK7770P) },
 	{ 0 }		/* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@@ -4521,6 +4522,35 @@
 			.change_protocol  = dib0700_change_protocol,
 		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+
+		.num_adapters = 1,
+		.adapter = {
+			{
+			.num_frontends = 1,
+			.fe = {{
+				.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+				.pid_filter_count = 32,
+				.pid_filter       = stk70x0p_pid_filter,
+				.pid_filter_ctrl  = stk70x0p_pid_filter_ctrl,
+				.frontend_attach  = stk7770p_frontend_attach,
+				.tuner_attach     = dib7770p_tuner_attach,
+
+				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+			}},
+				.size_of_priv =
+					sizeof(struct dib0700_adapter_state),
+			},
+		},
+
+		.num_device_descs = 1,
+		.devices = {
+			{   "DiBcom STK7770P reference design no IR",
+				{ &dib0700_usb_id_table[83], NULL },
+				{ NULL },
+			},
+		},
+
+	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 		.num_adapters = 1,
 		.adapter = {
 			{
diff -ruw linux-4.2/drivers/media/usb/dvb-usb/dvb-usb.h linux-4.2-fbx/drivers/media/usb/dvb-usb/dvb-usb.h
--- linux-4.2/drivers/media/usb/dvb-usb/dvb-usb.h	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/media/usb/dvb-usb/dvb-usb.h	2013-12-04 14:33:19.607478984 +0100
@@ -294,7 +294,7 @@
 	int generic_bulk_ctrl_endpoint_response;
 
 	int num_device_descs;
-	struct dvb_usb_device_description devices[12];
+	struct dvb_usb_device_description devices[32];
 };
 
 /**
diff -ruw linux-4.2/drivers/media/usb/dvb-usb-v2/af9035.c linux-4.2-fbx/drivers/media/usb/dvb-usb-v2/af9035.c
--- linux-4.2/drivers/media/usb/dvb-usb-v2/af9035.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/media/usb/dvb-usb-v2/af9035.c	2015-09-15 19:18:37.818453989 +0200
@@ -739,6 +739,8 @@
 	if (ret < 0)
 		goto err;
 
+	msleep(30);
+
 	/* firmware loaded, request boot */
 	req.cmd = CMD_FW_BOOT;
 	ret = af9035_ctrl_msg(d, &req);
@@ -758,6 +760,15 @@
 		goto err;
 	}
 
+	/* tuner RF initial */
+	if (state->chip_type == 0x9135) {
+		ret = af9035_wr_reg(d, 0x80ec4c, 0x68);
+		if (ret < 0)
+			goto err;
+
+		msleep(30);
+	}
+
 	dev_info(&d->udev->dev, "%s: firmware version=%d.%d.%d.%d",
 			KBUILD_MODNAME, rbuf[0], rbuf[1], rbuf[2], rbuf[3]);
 
diff -ruw linux-4.2/drivers/misc/Kconfig linux-4.2-fbx/drivers/misc/Kconfig
--- linux-4.2/drivers/misc/Kconfig	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/misc/Kconfig	2015-09-15 19:18:37.902454513 +0200
@@ -4,6 +4,9 @@
 
 menu "Misc devices"
 
+config WINTEGRA_MMAP
+	bool "wintegra mmap driver"
+
 config SENSORS_LIS3LV02D
 	tristate
 	depends on INPUT
@@ -418,6 +421,18 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called vmw_balloon.
 
+config INTELCE_PIC16PMU
+	tristate "PIC16 PMU, LED, hwmon support"
+	select INPUT_POLLDEV
+	select NEW_LEDS
+	select I2C
+	select HWMON
+	select ARCH_REQUIRE_GPIOLIB
+	---help---
+	  Freebox v6 HD PIC16 PMU interface support, enables
+	  control of the on-board LEDs and reports the power status,
+	  reset status and button status.
+
 config ARM_CHARLCD
 	bool "ARM Ltd. Character LCD Driver"
 	depends on PLAT_VERSATILE
@@ -527,4 +542,6 @@
 source "drivers/misc/genwqe/Kconfig"
 source "drivers/misc/echo/Kconfig"
 source "drivers/misc/cxl/Kconfig"
+source "drivers/misc/remoti/Kconfig"
+source "drivers/misc/hdmi-cec/Kconfig"
 endmenu
diff -ruw linux-4.2/drivers/misc/Makefile linux-4.2-fbx/drivers/misc/Makefile
--- linux-4.2/drivers/misc/Makefile	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/misc/Makefile	2015-09-15 19:18:37.902454513 +0200
@@ -2,6 +2,7 @@
 # Makefile for misc devices that really don't fit anywhere else.
 #
 
+obj-$(CONFIG_WINTEGRA_MMAP)	+= wintegra_mmap.o
 obj-$(CONFIG_IBM_ASM)		+= ibmasm/
 obj-$(CONFIG_AD525X_DPOT)	+= ad525x_dpot.o
 obj-$(CONFIG_AD525X_DPOT_I2C)	+= ad525x_dpot-i2c.o
@@ -25,6 +26,7 @@
 obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o
 obj-$(CONFIG_KGDB_TESTS)	+= kgdbts.o
 obj-$(CONFIG_SGI_XP)		+= sgi-xp/
+obj-$(CONFIG_INTELCE_PIC16PMU)	+= pic16-pmu.o
 obj-$(CONFIG_SGI_GRU)		+= sgi-gru/
 obj-$(CONFIG_CS5535_MFGPT)	+= cs5535-mfgpt.o
 obj-$(CONFIG_HP_ILO)		+= hpilo.o
@@ -55,3 +57,5 @@
 obj-$(CONFIG_ECHO)		+= echo/
 obj-$(CONFIG_VEXPRESS_SYSCFG)	+= vexpress-syscfg.o
 obj-$(CONFIG_CXL_BASE)		+= cxl/
+obj-y				+= remoti/
+obj-y				+= hdmi-cec/
diff -ruw linux-4.2/drivers/mtd/Kconfig linux-4.2-fbx/drivers/mtd/Kconfig
--- linux-4.2/drivers/mtd/Kconfig	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/mtd/Kconfig	2015-09-15 19:18:37.958454862 +0200
@@ -23,6 +23,9 @@
 	  WARNING: some of the tests will ERASE entire MTD device which they
 	  test. Do not use these tests unless you really know what you do.
 
+config MTD_ERASE_PRINTK
+	bool "write to kernel log when a block is erased"
+
 config MTD_REDBOOT_PARTS
 	tristate "RedBoot partition table parsing"
 	---help---
@@ -155,6 +158,17 @@
 	  This provides partitions parser for devices based on BCM47xx
 	  boards.
 
+config MTD_FBX6HD_PARTS
+	tristate "Freebox V6 HD partitioning support"
+	help
+	  Freebox V6 HD partitioning support
+
+config MTD_FBX6HD_PARTS_WRITE_ALL
+	bool "make all partitions writeable"
+	depends on MTD_FBX6HD_PARTS
+	help
+	  Freebox V6 HD partitions support
+
 comment "User Modules And Translation Layers"
 
 #
diff -ruw linux-4.2/drivers/mtd/Makefile linux-4.2-fbx/drivers/mtd/Makefile
--- linux-4.2/drivers/mtd/Makefile	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/mtd/Makefile	2015-09-15 19:18:37.958454862 +0200
@@ -13,6 +13,7 @@
 obj-$(CONFIG_MTD_AR7_PARTS)	+= ar7part.o
 obj-$(CONFIG_MTD_BCM63XX_PARTS)	+= bcm63xxpart.o
 obj-$(CONFIG_MTD_BCM47XX_PARTS)	+= bcm47xxpart.o
+obj-$(CONFIG_MTD_FBX6HD_PARTS)	+= fbx6hd-mtdparts.o
 
 # 'Users' - code which presents functionality to userspace.
 obj-$(CONFIG_MTD_BLKDEVS)	+= mtd_blkdevs.o
diff -ruw linux-4.2/drivers/mtd/mtdchar.c linux-4.2-fbx/drivers/mtd/mtdchar.c
--- linux-4.2/drivers/mtd/mtdchar.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/mtd/mtdchar.c	2015-09-15 19:18:37.970454937 +0200
@@ -186,6 +186,7 @@
 		{
 			struct mtd_oob_ops ops;
 
+			memset(&ops, 0, sizeof (ops));
 			ops.mode = MTD_OPS_RAW;
 			ops.datbuf = kbuf;
 			ops.oobbuf = NULL;
@@ -280,6 +281,7 @@
 		{
 			struct mtd_oob_ops ops;
 
+			memset(&ops, 0, sizeof (ops));
 			ops.mode = MTD_OPS_RAW;
 			ops.datbuf = kbuf;
 			ops.oobbuf = NULL;
@@ -692,6 +694,10 @@
 			erase->callback = mtdchar_erase_callback;
 			erase->priv = (unsigned long)&waitq;
 
+#ifdef CONFIG_MTD_ERASE_PRINTK
+			printk(KERN_DEBUG "mtd: %s: ERASE offset=@%08llx\n",
+			       mtd->name, erase->addr);
+#endif
 			/*
 			  FIXME: Allow INTERRUPTIBLE. Which means
 			  not having the wait_queue head on the stack.
diff -ruw linux-4.2/drivers/mtd/mtdcore.c linux-4.2-fbx/drivers/mtd/mtdcore.c
--- linux-4.2/drivers/mtd/mtdcore.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/mtd/mtdcore.c	2015-09-15 19:18:37.970454937 +0200
@@ -318,6 +318,24 @@
 }
 static DEVICE_ATTR(bbt_blocks, S_IRUGO, mtd_bbtblocks_show, NULL);
 
+static ssize_t mtd_nand_type_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct mtd_info *mtd = dev_get_drvdata(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%s\n", mtd->nand_type);
+}
+static DEVICE_ATTR(nand_type, S_IRUGO, mtd_nand_type_show, NULL);
+
+static ssize_t mtd_nand_manufacturer_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct mtd_info *mtd = dev_get_drvdata(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%s\n", mtd->nand_manufacturer);
+}
+static DEVICE_ATTR(nand_manufacturer, S_IRUGO, mtd_nand_manufacturer_show, NULL);
+
 static struct attribute *mtd_attrs[] = {
 	&dev_attr_type.attr,
 	&dev_attr_flags.attr,
@@ -335,6 +353,8 @@
 	&dev_attr_bad_blocks.attr,
 	&dev_attr_bbt_blocks.attr,
 	&dev_attr_bitflip_threshold.attr,
+	&dev_attr_nand_type.attr,
+	&dev_attr_nand_manufacturer.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(mtd);
diff -ruw linux-4.2/drivers/mtd/mtdpart.c linux-4.2-fbx/drivers/mtd/mtdpart.c
--- linux-4.2/drivers/mtd/mtdpart.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/mtd/mtdpart.c	2015-09-15 19:18:37.970454937 +0200
@@ -376,6 +376,8 @@
 	slave->mtd.oobsize = master->oobsize;
 	slave->mtd.oobavail = master->oobavail;
 	slave->mtd.subpage_sft = master->subpage_sft;
+	slave->mtd.nand_type = master->nand_type;
+	slave->mtd.nand_manufacturer = master->nand_manufacturer;
 
 	slave->mtd.name = name;
 	slave->mtd.owner = master->owner;
diff -ruw linux-4.2/drivers/mtd/nand/Kconfig linux-4.2-fbx/drivers/mtd/nand/Kconfig
--- linux-4.2/drivers/mtd/nand/Kconfig	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/mtd/nand/Kconfig	2015-09-15 19:18:37.970454937 +0200
@@ -41,6 +41,15 @@
 	tristate
 	default n
 
+config MTD_FORCE_BAD_BLOCK_ERASE
+	bool "Force erase on bad blocks (useful for bootloader parts)"
+	depends on MTD_NAND
+	default n
+	help
+	  Enable this option only when you need to force an erase on
+	  blocks being marked as "bad" by Linux (i.e: other ECC/bad block
+	  marker layout).
+
 config MTD_NAND_DENALI
         tristate "Support Denali NAND controller"
         depends on HAS_DMA
@@ -538,4 +547,9 @@
 	help
 	  Enables support for NAND controller on Hisilicon SoC Hip04.
 
+config MTD_NAND_DENALI_FBX
+	tristate "NAND Denali controller support"
+	depends on MTD_NAND && PCI
+	default n
+
 endif # MTD_NAND
diff -ruw linux-4.2/drivers/mtd/nand/Makefile linux-4.2-fbx/drivers/mtd/nand/Makefile
--- linux-4.2/drivers/mtd/nand/Makefile	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/mtd/nand/Makefile	2015-09-15 19:18:37.970454937 +0200
@@ -53,5 +53,6 @@
 obj-$(CONFIG_MTD_NAND_SUNXI)		+= sunxi_nand.o
 obj-$(CONFIG_MTD_NAND_HISI504)	        += hisi504_nand.o
 obj-$(CONFIG_MTD_NAND_BRCMNAND)		+= brcmnand/
+obj-$(CONFIG_MTD_NAND_DENALI_FBX)	+= denali_nand.o
 
 nand-objs := nand_base.o nand_bbt.o nand_timings.o
diff -ruw linux-4.2/drivers/mtd/nand/nand_base.c linux-4.2-fbx/drivers/mtd/nand/nand_base.c
--- linux-4.2/drivers/mtd/nand/nand_base.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/mtd/nand/nand_base.c	2015-09-15 19:18:37.982455012 +0200
@@ -2771,6 +2771,7 @@
 
 	while (len) {
 		/* Check if we have a bad block, we do not erase bad blocks! */
+#ifndef CONFIG_MTD_FORCE_BAD_BLOCK_ERASE
 		if (nand_block_checkbad(mtd, ((loff_t) page) <<
 					chip->page_shift, 0, allowbbt)) {
 			pr_warn("%s: attempt to erase a bad block at page 0x%08x\n",
@@ -2778,6 +2779,7 @@
 			instr->state = MTD_ERASE_FAILED;
 			goto erase_exit;
 		}
+#endif
 
 		/*
 		 * Invalidate the page cache, if we erase the block which
@@ -3641,6 +3643,7 @@
 	int busw;
 	int i, maf_idx;
 	u8 id_data[8];
+	int ret;
 
 	/* Select the device */
 	chip->select_chip(mtd, 0);
@@ -3775,6 +3778,17 @@
 	if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
 		chip->cmdfunc = nand_command_lp;
 
+	mtd->nand_type = kstrdup(type->name, GFP_KERNEL);
+	if (!mtd->nand_type)
+		return ERR_PTR(-ENOMEM);
+
+	mtd->nand_manufacturer = kstrdup(nand_manuf_ids[maf_idx].name,
+					 GFP_KERNEL);
+	if (!mtd->nand_manufacturer) {
+		ret = -ENOMEM;
+		goto out_nand_type;
+	}
+
 	pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n",
 		*maf_id, *dev_id);
 
@@ -3792,6 +3806,11 @@
 		(int)(chip->chipsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC",
 		mtd->erasesize >> 10, mtd->writesize, mtd->oobsize);
 	return type;
+
+out_nand_type:
+	kfree(mtd->nand_type);
+
+	return ERR_PTR(ret);
 }
 
 static int nand_dt_init(struct mtd_info *mtd, struct nand_chip *chip,
@@ -3844,6 +3863,7 @@
 	int i, nand_maf_id, nand_dev_id;
 	struct nand_chip *chip = mtd->priv;
 	struct nand_flash_dev *type;
+	int err;
 	int ret;
 
 	if (chip->dn) {
@@ -3863,7 +3883,8 @@
 		if (!(chip->options & NAND_SCAN_SILENT_NODEV))
 			pr_warn("No NAND device found\n");
 		chip->select_chip(mtd, -1);
-		return PTR_ERR(type);
+		err = PTR_ERR(type);
+		goto out_error;
 	}
 
 	chip->select_chip(mtd, -1);
@@ -3891,6 +3912,14 @@
 	mtd->size = i * chip->chipsize;
 
 	return 0;
+
+out_error:
+	if (mtd->nand_type)
+		kfree(mtd->nand_type);
+	if (mtd->nand_manufacturer)
+		kfree(mtd->nand_manufacturer);
+
+	return err;
 }
 EXPORT_SYMBOL(nand_scan_ident);
 
@@ -4066,9 +4095,13 @@
 		ecc->read_page = nand_read_page_swecc;
 		ecc->read_subpage = nand_read_subpage;
 		ecc->write_page = nand_write_page_swecc;
+		if (!ecc->read_page_raw)
 		ecc->read_page_raw = nand_read_page_raw;
+		if (!ecc->write_page_raw)
 		ecc->write_page_raw = nand_write_page_raw;
+		if (!ecc->read_oob)
 		ecc->read_oob = nand_read_oob_std;
+		if (!ecc->write_oob)
 		ecc->write_oob = nand_write_oob_std;
 		if (!ecc->size)
 			ecc->size = 256;
@@ -4101,6 +4134,7 @@
 		}
 
 		/* See nand_bch_init() for details. */
+		if (!ecc->bytes)
 		ecc->bytes = DIV_ROUND_UP(
 				ecc->strength * fls(8 * ecc->size), 8);
 		ecc->priv = nand_bch_init(mtd, ecc->size, ecc->bytes,
@@ -4186,7 +4220,7 @@
 	switch (ecc->mode) {
 	case NAND_ECC_SOFT:
 	case NAND_ECC_SOFT_BCH:
-		if (chip->page_shift > 9)
+		if (chip->page_shift > 9 && !(chip->options & NAND_NO_RNDOUT))
 			chip->options |= NAND_SUBPAGE_READ;
 		break;
 
diff -ruw linux-4.2/drivers/net/ethernet/intel/e1000/e1000.h linux-4.2-fbx/drivers/net/ethernet/intel/e1000/e1000.h
--- linux-4.2/drivers/net/ethernet/intel/e1000/e1000.h	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/net/ethernet/intel/e1000/e1000.h	2015-09-15 19:18:38.146456035 +0200
@@ -236,6 +236,7 @@
 	u16 link_speed;
 	u16 link_duplex;
 	spinlock_t stats_lock;
+	spinlock_t phy_lock;
 	unsigned int total_tx_bytes;
 	unsigned int total_tx_packets;
 	unsigned int total_rx_bytes;
@@ -323,6 +324,11 @@
 	struct delayed_work watchdog_task;
 	struct delayed_work fifo_stall_task;
 	struct delayed_work phy_info_task;
+
+#ifdef CONFIG_FBX6HD
+	int last_phy_gpio;
+	bool last_link_active;
+#endif
 };
 
 enum e1000_state_t {
diff -ruw linux-4.2/drivers/net/ethernet/intel/e1000/e1000_main.c linux-4.2-fbx/drivers/net/ethernet/intel/e1000/e1000_main.c
--- linux-4.2/drivers/net/ethernet/intel/e1000/e1000_main.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/net/ethernet/intel/e1000/e1000_main.c	2015-09-15 19:18:38.150456060 +0200
@@ -32,6 +32,12 @@
 #include <linux/prefetch.h>
 #include <linux/bitops.h>
 #include <linux/if_vlan.h>
+#include <linux/fbxserial.h>
+
+#ifdef CONFIG_FBX6HD
+#include <linux/gpio.h>
+#define GPIO_PHY_LED2 20
+#endif
 
 char e1000_driver_name[] = "e1000";
 static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
@@ -1099,6 +1105,14 @@
 
 	e1000_reset_hw(hw);
 
+#ifdef CONFIG_FBX6HD
+	memcpy(hw->mac_addr, fbxserialinfo_get_mac_addr(0), 6);
+	printk("e1000: using mac address %02x:%02x:%02x:%02x:%02x:%02x "
+	       "(fbxserial)\n",
+	       hw->mac_addr[0], hw->mac_addr[1], hw->mac_addr[2],
+	       hw->mac_addr[3], hw->mac_addr[4], hw->mac_addr[5]);
+	(void)e1000_validate_eeprom_checksum;
+#else
 	/* make sure the EEPROM is good */
 	if (e1000_validate_eeprom_checksum(hw) < 0) {
 		e_err(probe, "The EEPROM Checksum Is Not Valid\n");
@@ -1116,6 +1130,8 @@
 		if (e1000_read_mac_addr(hw))
 			e_err(probe, "EEPROM Read Error\n");
 	}
+#endif
+
 	/* don't block initialization here due to bad MAC address */
 	memcpy(netdev->dev_addr, hw->mac_addr, netdev->addr_len);
 
@@ -1206,6 +1222,13 @@
 			} else
 				break;
 		}
+
+#ifdef CONFIG_FBX6HD
+		/* request gpio use to read link change from PHY */
+		gpio_request(GPIO_PHY_LED2, "phy_leds2");
+		gpio_direction_input(GPIO_PHY_LED2);
+		adapter->last_phy_gpio = -1;
+#endif
 	}
 
 	/* reset the hardware with the new settings */
@@ -2398,6 +2421,26 @@
 	 */
 	switch (hw->media_type) {
 	case e1000_media_type_copper:
+#ifdef CONFIG_FBX6HD
+	{
+		int val;
+
+		val = gpio_get_value(GPIO_PHY_LED2);
+		if (val != adapter->last_phy_gpio)
+			hw->get_link_status = 1;
+		adapter->last_phy_gpio = val;
+
+		if (hw->get_link_status) {
+			e1000_check_for_link(hw);
+			link_active = !hw->get_link_status;
+			hw->get_link_status = 0;
+		} else {
+			link_active = adapter->last_link_active;
+		}
+		adapter->last_link_active = link_active;
+		break;
+	}
+#else
 		if (hw->mac_type == e1000_ce4100)
 			hw->get_link_status = 1;
 		if (hw->get_link_status) {
@@ -2407,6 +2450,7 @@
 			link_active = true;
 		}
 		break;
+#endif
 	case e1000_media_type_fiber:
 		e1000_check_for_link(hw);
 		link_active = !!(er32(STATUS) & E1000_STATUS_LU);
@@ -3727,11 +3771,13 @@
 
 	/* Phy Stats */
 	if (hw->media_type == e1000_media_type_copper) {
+#ifndef CONFIG_FBX6HD
 		if ((adapter->link_speed == SPEED_1000) &&
 		   (!e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp))) {
 			phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK;
 			adapter->phy_stats.idle_errors += phy_tmp;
 		}
+#endif
 
 		if ((hw->mac_type <= e1000_82546) &&
 		   (hw->phy_type == e1000_phy_m88) &&
diff -ruw linux-4.2/drivers/net/ethernet/Kconfig linux-4.2-fbx/drivers/net/ethernet/Kconfig
--- linux-4.2/drivers/net/ethernet/Kconfig	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/net/ethernet/Kconfig	2015-09-15 19:18:38.026455286 +0200
@@ -160,6 +160,7 @@
 source "drivers/net/ethernet/rocker/Kconfig"
 source "drivers/net/ethernet/samsung/Kconfig"
 source "drivers/net/ethernet/seeq/Kconfig"
+source "drivers/net/ethernet/sigma/Kconfig"
 source "drivers/net/ethernet/silan/Kconfig"
 source "drivers/net/ethernet/sis/Kconfig"
 source "drivers/net/ethernet/sfc/Kconfig"
@@ -174,6 +175,7 @@
 source "drivers/net/ethernet/tundra/Kconfig"
 source "drivers/net/ethernet/via/Kconfig"
 source "drivers/net/ethernet/wiznet/Kconfig"
+source "drivers/net/ethernet/wintegra/Kconfig"
 source "drivers/net/ethernet/xilinx/Kconfig"
 source "drivers/net/ethernet/xircom/Kconfig"
 
diff -ruw linux-4.2/drivers/net/ethernet/Makefile linux-4.2-fbx/drivers/net/ethernet/Makefile
--- linux-4.2/drivers/net/ethernet/Makefile	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/net/ethernet/Makefile	2015-09-15 19:18:38.026455286 +0200
@@ -71,6 +71,7 @@
 obj-$(CONFIG_NET_VENDOR_SAMSUNG) += samsung/
 obj-$(CONFIG_NET_VENDOR_SEEQ) += seeq/
 obj-$(CONFIG_NET_VENDOR_SILAN) += silan/
+obj-$(CONFIG_NET_VENDOR_SIGMA) += sigma/
 obj-$(CONFIG_NET_VENDOR_SIS) += sis/
 obj-$(CONFIG_SFC) += sfc/
 obj-$(CONFIG_NET_VENDOR_SGI) += sgi/
@@ -84,5 +85,6 @@
 obj-$(CONFIG_NET_VENDOR_TUNDRA) += tundra/
 obj-$(CONFIG_NET_VENDOR_VIA) += via/
 obj-$(CONFIG_NET_VENDOR_WIZNET) += wiznet/
+obj-$(CONFIG_NET_VENDOR_WINTEGRA) += wintegra/
 obj-$(CONFIG_NET_VENDOR_XILINX) += xilinx/
 obj-$(CONFIG_NET_VENDOR_XIRCOM) += xircom/
diff -ruw linux-4.2/drivers/net/ethernet/marvell/Kconfig linux-4.2-fbx/drivers/net/ethernet/marvell/Kconfig
--- linux-4.2/drivers/net/ethernet/marvell/Kconfig	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/net/ethernet/marvell/Kconfig	2015-10-01 20:02:09.152673918 +0200
@@ -21,6 +21,7 @@
 	depends on (MV64X60 || PPC32 || PLAT_ORION) && INET
 	select PHYLIB
 	select MVMDIO
+	select MII
 	---help---
 	  This driver supports the gigabit ethernet MACs in the
 	  Marvell Discovery PPC/MIPS chipset family (MV643XX) and
@@ -29,6 +30,10 @@
 	  Some boards that use the Discovery chipset are the Momenco
 	  Ocelot C and Jaguar ATX and Pegasos II.
 
+config MV643XX_ETH_FBX_FF
+	bool "fast forward mode for fbxgwrx"
+	depends on MV643XX_ETH
+
 config MVMDIO
 	tristate "Marvell MDIO interface support"
 	depends on HAS_IOMEM
diff -ruw linux-4.2/drivers/net/Kconfig linux-4.2-fbx/drivers/net/Kconfig
--- linux-4.2/drivers/net/Kconfig	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/net/Kconfig	2015-09-15 19:18:37.998455112 +0200
@@ -409,4 +409,14 @@
 
 source "drivers/net/hyperv/Kconfig"
 
+config TANGO2_ENET
+	tristate "SMP863x Builtin Ethernet support"
+	depends on NET_ETHERNET && TANGO2
+	select MII
+	select CRC32
+	help
+	 This option adds support for the SMP863x integrated Ethernet
+	 controller.  This driver uses NAPI and generic Linux MII
+	 support.
+
 endif # NETDEVICES
diff -ruw linux-4.2/drivers/net/Makefile linux-4.2-fbx/drivers/net/Makefile
--- linux-4.2/drivers/net/Makefile	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/net/Makefile	2015-09-15 19:18:37.998455112 +0200
@@ -67,3 +67,4 @@
 
 obj-$(CONFIG_HYPERV_NET) += hyperv/
 obj-$(CONFIG_NTB_NETDEV) += ntb_netdev.o
+
diff -ruw linux-4.2/drivers/net/wireless/ath/Kconfig linux-4.2-fbx/drivers/net/wireless/ath/Kconfig
--- linux-4.2/drivers/net/wireless/ath/Kconfig	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/net/wireless/ath/Kconfig	2015-10-02 18:50:14.325093036 +0200
@@ -33,6 +33,9 @@
          This option enables tracepoints for atheros wireless drivers.
 	 Currently, ath9k makes use of this facility.
 
+config ATH_REG_IGNORE
+	bool "ignore all eeprom regulation"
+
 config ATH_REG_DYNAMIC_USER_REG_HINTS
 	bool "Atheros dynamic user regulatory hints"
 	depends on CFG80211_CERTIFICATION_ONUS
diff -ruw linux-4.2/drivers/of/of_net.c linux-4.2-fbx/drivers/of/of_net.c
--- linux-4.2/drivers/of/of_net.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/of/of_net.c	2015-09-15 19:18:38.554458580 +0200
@@ -10,6 +10,7 @@
 #include <linux/of_net.h>
 #include <linux/phy.h>
 #include <linux/export.h>
+#include <linux/fbxserial.h>
 
 /**
  * of_get_phy_mode - Get phy mode for given device_node
@@ -68,6 +69,13 @@
 const void *of_get_mac_address(struct device_node *np)
 {
 	const void *addr;
+#ifdef CONFIG_FBXSERIAL
+	struct property *pp;
+
+	pp = of_find_property(np, "fbxserial-mac-address", NULL);
+	if (pp && pp->length == 4)
+		return fbxserialinfo_get_mac_addr(be32_to_cpu(*(u32*)pp->value));
+#endif
 
 	addr = of_get_mac_addr(np, "mac-address");
 	if (addr)
diff -ruw linux-4.2/drivers/of/platform.c linux-4.2-fbx/drivers/of/platform.c
--- linux-4.2/drivers/of/platform.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/of/platform.c	2015-09-15 19:18:38.558458605 +0200
@@ -74,6 +74,13 @@
 	struct device_node *node = dev->of_node;
 	const __be32 *reg;
 	u64 addr;
+	const char *legacy_name = NULL;
+
+	if (of_property_read_string(node, "fbx,legacy-device-name",
+				    &legacy_name) == 0) {
+		dev_set_name(dev, "%s", legacy_name);
+		return ;
+	}
 
 	/* Construct the name, using parent nodes if necessary to ensure uniqueness */
 	while (node->parent) {
diff -ruw linux-4.2/drivers/pci/probe.c linux-4.2-fbx/drivers/pci/probe.c
--- linux-4.2/drivers/pci/probe.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/pci/probe.c	2015-09-15 19:18:38.578458730 +0200
@@ -1652,7 +1652,7 @@
 		return 0;
 	if (pci_pcie_type(parent) == PCI_EXP_TYPE_ROOT_PORT)
 		return 1;
-	if (parent->has_secondary_link &&
+	if (pci_pcie_type(parent) == PCI_EXP_TYPE_DOWNSTREAM &&
 	    !pci_has_flag(PCI_SCAN_ALL_PCIE_DEVS))
 		return 1;
 	return 0;
diff -ruw linux-4.2/drivers/pci/quirks.c linux-4.2-fbx/drivers/pci/quirks.c
--- linux-4.2/drivers/pci/quirks.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/pci/quirks.c	2015-09-15 19:18:38.578458730 +0200
@@ -2690,6 +2690,8 @@
 }
 
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_HINT, 0x0020, quirk_hotplug_bridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PI7C9X20303SL,
+			 quirk_hotplug_bridge);
 
 /*
  * This is a quirk for the Ricoh MMC controller found as a part of
diff -ruw linux-4.2/drivers/pci/vc.c linux-4.2-fbx/drivers/pci/vc.c
--- linux-4.2/drivers/pci/vc.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/pci/vc.c	2015-09-15 19:18:38.582458755 +0200
@@ -108,7 +108,8 @@
 	struct pci_dev *link = NULL;
 
 	/* Enable VCs from the downstream device */
-	if (!dev->has_secondary_link)
+	if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT ||
+	    pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM)
 		return;
 
 	ctrl_pos = pos + PCI_VC_RES_CTRL + (res * PCI_CAP_VC_PER_VC_SIZEOF);
diff -ruw linux-4.2/drivers/platform/Kconfig linux-4.2-fbx/drivers/platform/Kconfig
--- linux-4.2/drivers/platform/Kconfig	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/platform/Kconfig	2015-09-15 19:18:38.626459029 +0200
@@ -9,3 +9,11 @@
 endif
 
 source "drivers/platform/chrome/Kconfig"
+
+if X86_INTEL_CE
+source "drivers/platform/intelce/Kconfig"
+endif
+
+if TANGO2
+source "drivers/platform/tango2/Kconfig"
+endif
diff -ruw linux-4.2/drivers/platform/Makefile linux-4.2-fbx/drivers/platform/Makefile
--- linux-4.2/drivers/platform/Makefile	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/platform/Makefile	2015-09-15 19:18:38.626459029 +0200
@@ -7,3 +7,5 @@
 obj-$(CONFIG_OLPC)		+= olpc/
 obj-$(CONFIG_GOLDFISH)		+= goldfish/
 obj-$(CONFIG_CHROME_PLATFORMS)	+= chrome/
+obj-$(CONFIG_X86_INTEL_CE)	+= intelce/
+obj-$(CONFIG_TANGO2)		+= tango2/
diff -ruw linux-4.2/drivers/spi/Kconfig linux-4.2-fbx/drivers/spi/Kconfig
--- linux-4.2/drivers/spi/Kconfig	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/spi/Kconfig	2015-09-15 19:18:38.858460476 +0200
@@ -399,6 +399,12 @@
 	def_bool y
 	depends on SPI_PXA2XX
 
+config SPI_TDM_ORION
+	tristate "Orion TDM SPI master"
+	depends on PLAT_ORION
+	help
+	  This enables using the TDM SPI master controller on the Orion chips.
+
 config SPI_PXA2XX
 	tristate "PXA2xx SSP SPI master"
 	depends on (ARCH_PXA || PCI || ACPI)
diff -ruw linux-4.2/drivers/spi/Makefile linux-4.2-fbx/drivers/spi/Makefile
--- linux-4.2/drivers/spi/Makefile	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/spi/Makefile	2015-09-15 19:18:38.858460476 +0200
@@ -57,6 +57,7 @@
 obj-$(CONFIG_SPI_OMAP24XX)		+= spi-omap2-mcspi.o
 obj-$(CONFIG_SPI_TI_QSPI)		+= spi-ti-qspi.o
 obj-$(CONFIG_SPI_ORION)			+= spi-orion.o
+obj-$(CONFIG_SPI_TDM_ORION)		+= orion_tdm_spi.o
 obj-$(CONFIG_SPI_PL022)			+= spi-pl022.o
 obj-$(CONFIG_SPI_PPC4xx)		+= spi-ppc4xx.o
 spi-pxa2xx-platform-objs		:= spi-pxa2xx.o
diff -ruw linux-4.2/drivers/tty/serial/8250/8250_core.c linux-4.2-fbx/drivers/tty/serial/8250/8250_core.c
--- linux-4.2/drivers/tty/serial/8250/8250_core.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/tty/serial/8250/8250_core.c	2015-09-15 19:18:39.138462223 +0200
@@ -42,6 +42,12 @@
 #include <linux/sunserialcore.h>
 #endif
 
+#ifdef CONFIG_TANGO2
+#include <asm/mach-tango2/tango2_gbus.h>
+
+extern unsigned long em8xxx_sys_frequency;
+#endif
+
 #include <asm/io.h>
 #include <asm/irq.h>
 
@@ -328,20 +334,30 @@
 	},
 };
 
+
 /* Uart divisor latch read */
 static int default_serial_dl_read(struct uart_8250_port *up)
 {
+#ifndef CONFIG_TANGO2
 	return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8;
+#else
+	BUG();
+	return 0;
+#endif
 }
 
 /* Uart divisor latch write */
 static void default_serial_dl_write(struct uart_8250_port *up, int value)
 {
+#ifndef CONFIG_TANGO2
 	serial_out(up, UART_DLL, value & 0xff);
 	serial_out(up, UART_DLM, value >> 8 & 0xff);
+#else
+	BUG();
+#endif
 }
 
-#if defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_SERIAL_8250_RT288X)
+#if defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_SERIAL_8250_RT288X) || defined(CONFIG_WINTEGRA_WINPATH3)
 
 /* Au1x00/RT288x UART hardware has a weird register layout */
 static const s8 au_io_in_map[8] = {
@@ -415,14 +431,44 @@
 
 static unsigned int mem_serial_in(struct uart_port *p, int offset)
 {
+#ifdef CONFIG_TANGO2
+	unsigned long v;
+
+	/* no EFR on tango2 */
+	if (offset == UART_EFR)
+		v = 0;
+	else
+		v = gbus_readl((unsigned long)p->membase +
+			       (offset << p->regshift));
+	return v;
+#else
 	offset = offset << p->regshift;
 	return readb(p->membase + offset);
+#endif
 }
 
 static void mem_serial_out(struct uart_port *p, int offset, int value)
 {
+#ifdef CONFIG_TANGO2
+	/*
+	 * we add a special case for UART_DL register, since
+	 * register content has a different meaning for us.
+	 */
+	if (offset == UART_DL) {
+		/* select right clock source */
+		value = (em8xxx_sys_frequency / p->uartclk);
+	}
+
+	/* no EFR on tango2 */
+	if (offset != UART_EFR) {
+		offset = offset << p->regshift;
+		gbus_writel((unsigned long)p->membase + offset,
+			    value);
+	}
+#else
 	offset = offset << p->regshift;
 	writeb(value, p->membase + offset);
+#endif
 }
 
 static void mem32_serial_out(struct uart_port *p, int offset, int value)
@@ -492,7 +538,7 @@
 		p->serial_out = mem32be_serial_out;
 		break;
 
-#if defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_SERIAL_8250_RT288X)
+#if defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_SERIAL_8250_RT288X) || defined(CONFIG_WINTEGRA_WINPATH3)
 	case UPIO_AU:
 		p->serial_in = au_serial_in;
 		p->serial_out = au_serial_out;
@@ -734,7 +780,11 @@
 static int size_fifo(struct uart_8250_port *up)
 {
 	unsigned char old_fcr, old_mcr, old_lcr;
+#ifdef CONFIG_TANGO2
+	unsigned short old_dll, old_dlm;
+#else
 	unsigned short old_dl;
+#endif
 	int count;
 
 	old_lcr = serial_in(up, UART_LCR);
@@ -745,8 +795,14 @@
 		    UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
 	serial_out(up, UART_MCR, UART_MCR_LOOP);
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
+#ifdef CONFIG_TANGO2
+	old_dll = serial_in(up, UART_DL) & 0xff;
+	old_dlm = serial_in(up, UART_DL) >> 8;
+	serial_out(up, UART_DL, 0x01);
+#else
 	old_dl = serial_dl_read(up);
 	serial_dl_write(up, 0x0001);
+#endif
 	serial_out(up, UART_LCR, 0x03);
 	for (count = 0; count < 256; count++)
 		serial_out(up, UART_TX, count);
@@ -757,7 +813,11 @@
 	serial_out(up, UART_FCR, old_fcr);
 	serial_out(up, UART_MCR, old_mcr);
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
+#ifdef CONFIG_TANGO2
+	serial_out(up, UART_DL, (old_dlm << 8) | old_dll);
+#else
 	serial_dl_write(up, old_dl);
+#endif
 	serial_out(up, UART_LCR, old_lcr);
 
 	return count;
@@ -776,6 +836,16 @@
 	old_lcr = serial_in(p, UART_LCR);
 	serial_out(p, UART_LCR, UART_LCR_CONF_MODE_A);
 
+#ifdef CONFIG_TANGO2
+	old_dll = serial_in(p, UART_DL) & 0xff;
+	old_dlm = serial_in(p, UART_DL) >> 8;
+
+	serial_out(p, UART_DL, 0);
+
+	id = serial_in(p, UART_DL);
+
+	serial_out(p, UART_DL, (old_dlm << 8) | old_dll);
+#else
 	old_dll = serial_in(p, UART_DLL);
 	old_dlm = serial_in(p, UART_DLM);
 
@@ -786,6 +856,7 @@
 
 	serial_out(p, UART_DLL, old_dll);
 	serial_out(p, UART_DLM, old_dlm);
+#endif
 	serial_out(p, UART_LCR, old_lcr);
 
 	return id;
@@ -1018,11 +1089,19 @@
 
 			serial_out(up, UART_LCR, 0xE0);
 
+#ifdef CONFIG_TANGO2
+			quot = serial_in(up, UART_DL);
+#else
 			quot = serial_dl_read(up);
+#endif
 			quot <<= 3;
 
 			if (ns16550a_goto_highspeed(up))
+#ifdef CONFIG_TANGO2
+				serial_out(up, UART_DL, quot);
+#else
 				serial_dl_write(up, quot);
+#endif
 
 			serial_out(up, UART_LCR, 0);
 
@@ -2531,7 +2610,11 @@
 	else
 		serial_port_out(port, UART_LCR, up->lcr | UART_LCR_DLAB);
 
+#ifdef CONFIG_TANGO2
+	serial_out(up, UART_DL, quot);
+#else
 	serial_dl_write(up, quot);
+#endif
 
 	/* XR17V35x UARTs have an extra fractional divisor register (DLD) */
 	if (up->port.type == PORT_XR17V35X)
@@ -2653,6 +2736,11 @@
 	}
 
 	serial8250_set_divisor(port, baud, quot, frac);
+#ifdef CONFIG_TANGO2
+	serial_out(up, UART_DL, quot);
+#else
+	serial_dl_write(up, quot);
+#endif
 
 	/*
 	 * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
@@ -3427,8 +3515,13 @@
 
 	lcr = serial_port_in(port, UART_LCR);
 	serial_port_out(port, UART_LCR, lcr | UART_LCR_DLAB);
+#ifdef CONFIG_TANGO2
+	dll = serial_port_in(port, UART_DL) & 0xff;
+	dlm = serial_port_in(port, UART_DL) >> 8;
+#else
 	dll = serial_port_in(port, UART_DLL);
 	dlm = serial_port_in(port, UART_DLM);
+#endif
 	serial_port_out(port, UART_LCR, lcr);
 
 	quot = (dlm << 8) | dll;
diff -ruw linux-4.2/drivers/tty/serial/8250/8250_early.c linux-4.2-fbx/drivers/tty/serial/8250/8250_early.c
--- linux-4.2/drivers/tty/serial/8250/8250_early.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/tty/serial/8250/8250_early.c	2015-09-15 19:18:39.138462223 +0200
@@ -126,8 +126,12 @@
 	divisor = DIV_ROUND_CLOSEST(port->uartclk, 16 * device->baud);
 	c = serial8250_early_in(port, UART_LCR);
 	serial8250_early_out(port, UART_LCR, c | UART_LCR_DLAB);
+#ifdef CONFIG_TANGO2
+	serial8250_early_out(port, UART_DL, divisor & 0xffff);
+#else
 	serial8250_early_out(port, UART_DLL, divisor & 0xff);
 	serial8250_early_out(port, UART_DLM, (divisor >> 8) & 0xff);
+#endif
 	serial8250_early_out(port, UART_LCR, c & ~UART_LCR_DLAB);
 }
 
diff -ruw linux-4.2/drivers/usb/host/ehci-hcd.c linux-4.2-fbx/drivers/usb/host/ehci-hcd.c
--- linux-4.2/drivers/usb/host/ehci-hcd.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/usb/host/ehci-hcd.c	2015-09-15 19:18:39.222462747 +0200
@@ -1296,6 +1296,11 @@
 #define	PLATFORM_DRIVER		ehci_hcd_sead3_driver
 #endif
 
+#ifdef CONFIG_TANGO2
+#include "ehci-tango2.c"
+#define	PLATFORM_DRIVER		ehci_hcd_tango2_driver
+#endif
+
 static int __init ehci_hcd_init(void)
 {
 	int retval = 0;
diff -ruw linux-4.2/drivers/usb/storage/usb.c linux-4.2-fbx/drivers/usb/storage/usb.c
--- linux-4.2/drivers/usb/storage/usb.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/usb/storage/usb.c	2015-09-15 19:18:39.286463146 +0200
@@ -83,7 +83,7 @@
 MODULE_DESCRIPTION("USB Mass Storage driver for Linux");
 MODULE_LICENSE("GPL");
 
-static unsigned int delay_use = 1;
+static unsigned int delay_use = 5;
 module_param(delay_use, uint, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device");
 
diff -ruw linux-4.2/drivers/video/Kconfig linux-4.2-fbx/drivers/video/Kconfig
--- linux-4.2/drivers/video/Kconfig	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/video/Kconfig	2015-09-15 19:18:39.294463196 +0200
@@ -52,4 +52,15 @@
 endif
 
 
+config FB_SSD1327
+	tristate "SSD1327 OLED driver"
+	depends on FB
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	select FB_SYS_FOPS
+	select FB_BACKLIGHT
+	select SPI
+	default n
+
 endmenu
diff -ruw linux-4.2/drivers/video/Makefile linux-4.2-fbx/drivers/video/Makefile
--- linux-4.2/drivers/video/Makefile	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/drivers/video/Makefile	2015-09-15 19:18:39.294463196 +0200
@@ -11,3 +11,5 @@
 ifeq ($(CONFIG_OF),y)
 obj-$(CONFIG_VIDEOMODE_HELPERS) += of_display_timing.o of_videomode.o
 endif
+
+obj-$(CONFIG_FB_SSD1327)          += ssd1327.o
diff -ruw linux-4.2/firmware/Makefile linux-4.2-fbx/firmware/Makefile
--- linux-4.2/firmware/Makefile	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/firmware/Makefile	2015-09-15 19:18:39.466464269 +0200
@@ -136,6 +136,10 @@
 fw-shipped-$(CONFIG_VIDEO_CPIA2) += cpia2/stv0672_vp4.bin
 fw-shipped-$(CONFIG_YAM) += yam/1200.bin yam/9600.bin
 
+fw-shipped-$(CONFIG_MWL8K) += mwl8k/helper_8366.fw mwl8k/fmimage_8764_ap-1.fw \
+                               mwl8k/fmimage_8366_ap-3.fw
+
+
 fw-shipped-all := $(fw-shipped-y) $(fw-shipped-m) $(fw-shipped-)
 
 quiet_cmd_ihex  = IHEX    $@
@@ -235,3 +239,10 @@
 obj- := dummy
 
 hostprogs-y := ihex2fw
+
+# hack for 'make mrproper' and mwl8k .fw files being removed.
+quiet_cmd_shipped = SHIPPED $@
+cmd_shipped = cat $< > $@
+
+%.fw: %.fw_shipped
+	$(call cmd,shipped)
diff -ruw linux-4.2/fs/exec.c linux-4.2-fbx/fs/exec.c
--- linux-4.2/fs/exec.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/fs/exec.c	2015-09-15 19:18:39.538464718 +0200
@@ -1490,6 +1490,23 @@
 		return PTR_ERR(filename);
 
 	/*
+	 * handle current->exec_mode:
+	 * - if unlimited, then nothing to do.
+	 * - if once, then set it to denied and continue (next execve
+	 *   after this one will fail).
+	 * - if denied, then effectively fail the execve call with EPERM.
+	 */
+	switch (current->exec_mode) {
+	case EXEC_MODE_UNLIMITED:
+		break;
+	case EXEC_MODE_ONCE:
+		current->exec_mode = EXEC_MODE_DENIED;
+		break;
+	case EXEC_MODE_DENIED:
+		return -EPERM;
+	}
+
+	/*
 	 * We move the actual failure in case of RLIMIT_NPROC excess from
 	 * set*uid() to execve() because too many poorly written programs
 	 * don't check setuid() return code.  Here we additionally recheck
diff -ruw linux-4.2/fs/Kconfig linux-4.2-fbx/fs/Kconfig
--- linux-4.2/fs/Kconfig	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/fs/Kconfig	2015-09-15 19:18:39.470464294 +0200
@@ -99,6 +99,7 @@
 
 source "fs/fat/Kconfig"
 source "fs/ntfs/Kconfig"
+source "fs/exfat/Kconfig"
 
 endmenu
 endif # BLOCK
diff -ruw linux-4.2/fs/Makefile linux-4.2-fbx/fs/Makefile
--- linux-4.2/fs/Makefile	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/fs/Makefile	2015-09-15 19:18:39.470464294 +0200
@@ -126,3 +126,4 @@
 obj-$(CONFIG_CEPH_FS)		+= ceph/
 obj-$(CONFIG_PSTORE)		+= pstore/
 obj-$(CONFIG_EFIVAR_FS)		+= efivarfs/
+obj-$(CONFIG_EXFAT_FS)		+= exfat/
diff -ruw linux-4.2/fs/proc/array.c linux-4.2-fbx/fs/proc/array.c
--- linux-4.2/fs/proc/array.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/fs/proc/array.c	2015-09-15 19:18:39.670465541 +0200
@@ -139,6 +139,21 @@
 	return task_state_array[fls(state)];
 }
 
+static const char *const task_exec_mode_array[] = {
+	"0 (Denied)",
+	"1 (Once)",
+	"2 (Unlimited)",
+};
+
+static inline const char *get_task_exec_mode(struct task_struct *tsk)
+{
+	unsigned int exec_mode = tsk->exec_mode;
+
+	if (exec_mode > EXEC_MODE_UNLIMITED)
+		return "? (Invalid)";
+	return task_exec_mode_array[exec_mode];
+}
+
 static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
 				struct pid *pid, struct task_struct *p)
 {
@@ -340,6 +355,12 @@
 			p->nivcsw);
 }
 
+static inline void task_exec_mode(struct seq_file *m,
+				  struct task_struct *p)
+{
+	seq_printf(m, "Exec mode: %s\n", get_task_exec_mode(p));
+}
+
 static void task_cpus_allowed(struct seq_file *m, struct task_struct *task)
 {
 	seq_printf(m, "Cpus_allowed:\t%*pb\n",
@@ -366,6 +387,7 @@
 	task_cpus_allowed(m, task);
 	cpuset_task_status_allowed(m, task);
 	task_context_switch_counts(m, task);
+	task_exec_mode(m, task);
 	return 0;
 }
 
diff -ruw linux-4.2/fs/pstore/ram.c linux-4.2-fbx/fs/pstore/ram.c
--- linux-4.2/fs/pstore/ram.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/fs/pstore/ram.c	2015-09-15 19:18:39.674465566 +0200
@@ -319,6 +319,8 @@
 
 	prz = cxt->przs[cxt->dump_write_cnt];
 
+	persistent_ram_zap(prz);
+
 	hlen = ramoops_write_kmsg_hdr(prz, compressed);
 	if (size + hlen > prz->buffer_size)
 		size = prz->buffer_size - hlen;
diff -ruw linux-4.2/fs/xfs/xfs_buf.c linux-4.2-fbx/fs/xfs/xfs_buf.c
--- linux-4.2/fs/xfs/xfs_buf.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/fs/xfs/xfs_buf.c	2015-09-15 19:18:39.718465840 +0200
@@ -377,6 +377,37 @@
 	return error;
 }
 
+#ifdef CONFIG_MIPS
+static void cache_flush_buf_page(xfs_buf_t *bp, int page_id)
+{
+	struct page *page;
+	void *vmaddr, *addr;
+
+	if (!xfs_buf_is_vmapped(bp))
+		return;
+
+	page = bp->b_pages[page_id];
+	vmaddr = bp->b_addr - bp->b_offset + (page_id * PAGE_CACHE_SIZE);
+	addr = page_address(page);
+
+	if (pages_do_alias((unsigned long)addr, (unsigned long)vmaddr)) {
+		local_flush_data_cache_page(vmaddr);
+		local_flush_data_cache_page(addr);
+	}
+}
+
+static void cache_flush_buf(xfs_buf_t *bp)
+{
+	unsigned int i;
+
+	for (i = 0; i < bp->b_page_count; i++)
+		cache_flush_buf_page(bp, i);
+}
+#else
+static inline void cache_flush_buf_page(xfs_buf_t *bp, int page_id) { }
+static inline void cache_flush_buf(xfs_buf_t *bp) { }
+#endif
+
 /*
  *	Map buffer into kernel address-space if necessary.
  */
@@ -416,6 +447,7 @@
 		if (!bp->b_addr)
 			return -ENOMEM;
 		bp->b_addr += bp->b_offset;
+		cache_flush_buf(bp);
 	}
 
 	return 0;
@@ -1173,6 +1205,7 @@
 		if (nbytes > size)
 			nbytes = size;
 
+		cache_flush_buf_page(bp, page_index);
 		rbytes = bio_add_page(bio, bp->b_pages[page_index], nbytes,
 				      offset);
 		if (rbytes < nbytes)
diff -ruw linux-4.2/include/linux/genhd.h linux-4.2-fbx/include/linux/genhd.h
--- linux-4.2/include/linux/genhd.h	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/include/linux/genhd.h	2015-09-15 19:18:39.838466589 +0200
@@ -85,6 +85,7 @@
 	unsigned long ticks[2];
 	unsigned long io_ticks;
 	unsigned long time_in_queue;
+	unsigned long io_errors[2];
 };
 
 #define PARTITION_META_INFO_VOLNAMELTH	64
diff -ruw linux-4.2/include/linux/if_vlan.h linux-4.2-fbx/include/linux/if_vlan.h
--- linux-4.2/include/linux/if_vlan.h	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/include/linux/if_vlan.h	2015-09-15 19:18:39.842466614 +0200
@@ -17,6 +17,7 @@
 #include <linux/rtnetlink.h>
 #include <linux/bug.h>
 #include <uapi/linux/if_vlan.h>
+#include <uapi/linux/pkt_sched.h>
 
 #define VLAN_HLEN	4		/* The additional bytes required by VLAN
 					 * (in addition to the Ethernet header)
@@ -109,6 +110,7 @@
 extern struct net_device *__vlan_find_dev_deep_rcu(struct net_device *real_dev,
 					       __be16 vlan_proto, u16 vlan_id);
 extern struct net_device *vlan_dev_real_dev(const struct net_device *dev);
+extern struct net_device *vlan_dev_upper_dev(const struct net_device *dev);
 extern u16 vlan_dev_vlan_id(const struct net_device *dev);
 extern __be16 vlan_dev_vlan_proto(const struct net_device *dev);
 
@@ -176,7 +178,7 @@
 
 	mp = vlan_dev_priv(dev)->egress_priority_map[(skprio & 0xF)];
 	while (mp) {
-		if (mp->priority == skprio) {
+		if (mp->priority == (skprio & TC_H_MIN_MASK)) {
 			return mp->vlan_qos; /* This should already be shifted
 					      * to mask correctly with the
 					      * VLAN's TCI */
@@ -215,6 +217,12 @@
 {
 	BUG();
 	return NULL;
+}
+
+static inline struct net_device *vlan_dev_upper_dev(const struct net_device *dev)
+{
+	BUG();
+	return NULL;
 }
 
 static inline u16 vlan_dev_vlan_id(const struct net_device *dev)
diff -ruw linux-4.2/include/linux/in.h linux-4.2-fbx/include/linux/in.h
--- linux-4.2/include/linux/in.h	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/include/linux/in.h	2013-12-04 14:33:24.415479060 +0100
@@ -34,6 +34,9 @@
 		return 0;
 	case IPPROTO_AH:	/* SPI */
 		return 4;
+	case IPPROTO_IPV6:
+		/* third byte of ipv6 destination address */
+		return 36;
 	default:
 		return -EINVAL;
 	}
diff -ruw linux-4.2/include/linux/init_task.h linux-4.2-fbx/include/linux/init_task.h
--- linux-4.2/include/linux/init_task.h	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/include/linux/init_task.h	2015-09-15 19:18:39.846466639 +0200
@@ -183,6 +183,7 @@
 	.stack		= &init_thread_info,				\
 	.usage		= ATOMIC_INIT(2),				\
 	.flags		= PF_KTHREAD,					\
+	.exec_mode	= EXEC_MODE_UNLIMITED,				\
 	.prio		= MAX_PRIO-20,					\
 	.static_prio	= MAX_PRIO-20,					\
 	.normal_prio	= MAX_PRIO-20,					\
diff -ruw linux-4.2/include/linux/mtd/mtd.h linux-4.2-fbx/include/linux/mtd/mtd.h
--- linux-4.2/include/linux/mtd/mtd.h	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/include/linux/mtd/mtd.h	2015-09-15 19:18:39.874466814 +0200
@@ -163,6 +163,10 @@
 	 */
 	unsigned int bitflip_threshold;
 
+	/* NAND related attributes */
+	const char *nand_type;
+	const char *nand_manufacturer;
+
 	// Kernel-only stuff starts here.
 	const char *name;
 	int index;
diff -ruw linux-4.2/include/linux/mtd/nand.h linux-4.2-fbx/include/linux/mtd/nand.h
--- linux-4.2/include/linux/mtd/nand.h	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/include/linux/mtd/nand.h	2015-09-15 19:18:39.874466814 +0200
@@ -190,6 +190,9 @@
  */
 #define NAND_USE_BOUNCE_BUFFER	0x00100000
 
+/* NAND controller does not want RNDOUT commands, even in NAND_ECC_SOFT */
+#define NAND_NO_RNDOUT		0x00800000
+
 /* Options set by nand scan */
 /* Nand scan has allocated controller struct */
 #define NAND_CONTROLLER_ALLOC	0x80000000
diff -ruw linux-4.2/include/linux/netdevice.h linux-4.2-fbx/include/linux/netdevice.h
--- linux-4.2/include/linux/netdevice.h	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/include/linux/netdevice.h	2015-09-15 19:18:39.878466838 +0200
@@ -1735,6 +1735,12 @@
 	struct garp_port __rcu	*garp_port;
 	struct mrp_port __rcu	*mrp_port;
 
+#ifdef CONFIG_FBXBRIDGE
+	struct fbxbridge	*fbx_bridge;
+	struct fbxbridge	*fbx_bridge_port;
+	int			fbx_bridge_maybe_port;
+#endif
+
 	struct device	dev;
 	const struct attribute_group *sysfs_groups[4];
 	const struct attribute_group *sysfs_rx_queue_group;
diff -ruw linux-4.2/include/linux/netfilter/nf_conntrack_tcp.h linux-4.2-fbx/include/linux/netfilter/nf_conntrack_tcp.h
--- linux-4.2/include/linux/netfilter/nf_conntrack_tcp.h	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/include/linux/netfilter/nf_conntrack_tcp.h	2015-10-01 20:02:09.156673942 +0200
@@ -27,6 +27,7 @@
 	/* For SYN packets while we may be out-of-sync */
 	u_int8_t	last_wscale;	/* Last window scaling factor seen */
 	u_int8_t	last_flags;	/* Last flags set */
+	u_int32_t	no_window_track;
 };
 
 #endif /* _NF_CONNTRACK_TCP_H */
diff -ruw linux-4.2/include/linux/pci_ids.h linux-4.2-fbx/include/linux/pci_ids.h
--- linux-4.2/include/linux/pci_ids.h	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/include/linux/pci_ids.h	2015-09-15 19:18:39.886466888 +0200
@@ -2995,4 +2995,7 @@
 
 #define PCI_VENDOR_ID_OCZ		0x1b85
 
+#define PCI_VENDOR_ID_PERICOM		0x12d8
+#define PCI_DEVICE_ID_PI7C9X20303SL	0xa303
+
 #endif /* _LINUX_PCI_IDS_H */
diff -ruw linux-4.2/include/linux/phy.h linux-4.2-fbx/include/linux/phy.h
--- linux-4.2/include/linux/phy.h	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/include/linux/phy.h	2015-09-15 19:18:39.890466913 +0200
@@ -211,7 +211,7 @@
 struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr);
 int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum);
 int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val);
-
+struct mii_bus *mdio_find_bus(const char *name);
 
 #define PHY_INTERRUPT_DISABLED	0x0
 #define PHY_INTERRUPT_ENABLED	0x80000000
diff -ruw linux-4.2/include/linux/ppp_channel.h linux-4.2-fbx/include/linux/ppp_channel.h
--- linux-4.2/include/linux/ppp_channel.h	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/include/linux/ppp_channel.h	2013-12-04 14:33:24.811479066 +0100
@@ -49,6 +49,9 @@
 /* Called by the channel when it can send some more data. */
 extern void ppp_output_wakeup(struct ppp_channel *);
 
+/* Called by the channel when it want to prevent further transmit on it */
+extern void ppp_output_stop(struct ppp_channel *);
+
 /* Called by the channel to process a received PPP packet.
    The packet should have just the 2-byte PPP protocol header. */
 extern void ppp_input(struct ppp_channel *, struct sk_buff *);
diff -ruw linux-4.2/include/linux/sched.h linux-4.2-fbx/include/linux/sched.h
--- linux-4.2/include/linux/sched.h	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/include/linux/sched.h	2015-09-15 19:18:39.906467013 +0200
@@ -1341,6 +1341,12 @@
 	perf_nr_task_contexts,
 };
 
+enum task_exec_mode {
+	EXEC_MODE_DENIED,
+	EXEC_MODE_ONCE,
+	EXEC_MODE_UNLIMITED,
+};
+
 struct task_struct {
 	volatile long state;	/* -1 unrunnable, 0 runnable, >0 stopped */
 	void *stack;
@@ -1348,6 +1354,8 @@
 	unsigned int flags;	/* per process flags, defined below */
 	unsigned int ptrace;
 
+	enum task_exec_mode exec_mode;
+
 #ifdef CONFIG_SMP
 	struct llist_node wake_entry;
 	int on_cpu;
diff -ruw linux-4.2/include/linux/skbuff.h linux-4.2-fbx/include/linux/skbuff.h
--- linux-4.2/include/linux/skbuff.h	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/include/linux/skbuff.h	2015-09-15 19:18:39.910467038 +0200
@@ -456,6 +456,13 @@
 }
 
 
+enum {
+	FFN_STATE_INIT = 0,
+	FFN_STATE_FORWARDABLE,
+	FFN_STATE_FAST_FORWARDED,
+	FFN_STATE_INCOMPATIBLE,
+};
+
 /** 
  *	struct sk_buff - socket buffer
  *	@next: Next buffer in list
@@ -557,14 +564,27 @@
 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
 	struct nf_conntrack	*nfct;
 #endif
+#ifdef CONFIG_IP_FFN
+	int			ffn_state;
+	int			ffn_orig_tos;
+#endif
 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
 	struct nf_bridge_info	*nf_bridge;
 #endif
+
+#ifdef CONFIG_FBXBRIDGE
+	int			fbxbridge_state;
+#endif
+
 	unsigned int		len,
 				data_len;
 	__u16			mac_len,
 				hdr_len;
 
+#ifdef CONFIG_NETRXTHREAD
+	int			rxthread_prio;
+#endif
+
 	/* Following fields are _not_ copied in __copy_skb_header()
 	 * Note that queue_mapping is here mostly to fill a hole.
 	 */
@@ -2038,6 +2058,10 @@
  * get_rps_cpus() for example only access one 64 bytes aligned block :
  * NET_IP_ALIGN(2) + ethernet_header(14) + IP_header(20/40) + ports(8)
  */
+#ifdef CONFIG_NETSKBPAD
+#define NET_SKB_PAD	CONFIG_NETSKBPAD
+#endif
+
 #ifndef NET_SKB_PAD
 #define NET_SKB_PAD	max(32, L1_CACHE_BYTES)
 #endif
diff -ruw linux-4.2/include/net/ip6_tunnel.h linux-4.2-fbx/include/net/ip6_tunnel.h
--- linux-4.2/include/net/ip6_tunnel.h	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/include/net/ip6_tunnel.h	2015-10-02 18:50:14.333093085 +0200
@@ -15,6 +15,18 @@
 /* determine capability on a per-packet basis */
 #define IP6_TNL_F_CAP_PER_PACKET 0x40000
 
+/* IPv6 tunnel FMR */
+struct __ip6_tnl_fmr {
+	struct __ip6_tnl_fmr *next; /* next fmr in list */
+	struct in6_addr ip6_prefix;
+	struct in_addr ip4_prefix;
+
+	__u8 ip6_prefix_len;
+	__u8 ip4_prefix_len;
+	__u8 ea_len;
+	__u8 offset;
+};
+
 struct __ip6_tnl_parm {
 	char name[IFNAMSIZ];	/* name of tunnel device */
 	int link;		/* ifindex of underlying L2 interface */
@@ -25,6 +37,7 @@
 	__u32 flags;		/* tunnel flags */
 	struct in6_addr laddr;	/* local tunnel end-point address */
 	struct in6_addr raddr;	/* remote tunnel end-point address */
+	struct __ip6_tnl_fmr *fmrs;	/* FMRs */
 
 	__be16			i_flags;
 	__be16			o_flags;
diff -ruw linux-4.2/include/net/ip.h linux-4.2-fbx/include/net/ip.h
--- linux-4.2/include/net/ip.h	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/include/net/ip.h	2015-09-15 19:18:39.942467238 +0200
@@ -518,6 +518,20 @@
 int ip_frag_mem(struct net *net);
 
 /*
+ *     Functions provided by ip_ffn.c
+ */
+
+enum {
+	IP_FFN_FINISH_OUT,
+	IP_FFN_LOCAL_IN,
+};
+
+extern void ip_ffn_init(void);
+extern int ip_ffn_process(struct sk_buff *skb);
+extern void ip_ffn_add(struct sk_buff *skb, int when);
+extern void ip_ffn_flush_all(void);
+
+/*
  *	Functions provided by ip_forward.c
  */
  
diff -ruw linux-4.2/include/net/sock.h linux-4.2-fbx/include/net/sock.h
--- linux-4.2/include/net/sock.h	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/include/net/sock.h	2015-09-15 19:18:39.958467337 +0200
@@ -185,6 +185,7 @@
 	unsigned char		skc_reuseport:1;
 	unsigned char		skc_ipv6only:1;
 	unsigned char		skc_net_refcnt:1;
+	unsigned char		skc_reuse_conflict;
 	int			skc_bound_dev_if;
 	union {
 		struct hlist_node	skc_bind_node;
@@ -324,6 +325,7 @@
 #define sk_reuseport		__sk_common.skc_reuseport
 #define sk_ipv6only		__sk_common.skc_ipv6only
 #define sk_net_refcnt		__sk_common.skc_net_refcnt
+#define sk_reuse_conflict	__sk_common.skc_reuse_conflict
 #define sk_bound_dev_if		__sk_common.skc_bound_dev_if
 #define sk_bind_node		__sk_common.skc_bind_node
 #define sk_prot			__sk_common.skc_prot
@@ -720,6 +722,7 @@
 		     */
 	SOCK_FILTER_LOCKED, /* Filter cannot be changed anymore */
 	SOCK_SELECT_ERR_QUEUE, /* Wake select on error queue */
+	SOCK_UDP_DUP_UNICAST,
 };
 
 static inline void sock_copy_flags(struct sock *nsk, struct sock *osk)
diff -ruw linux-4.2/include/uapi/asm-generic/socket.h linux-4.2-fbx/include/uapi/asm-generic/socket.h
--- linux-4.2/include/uapi/asm-generic/socket.h	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/include/uapi/asm-generic/socket.h	2015-09-15 19:18:39.978467462 +0200
@@ -87,4 +87,6 @@
 #define SO_ATTACH_BPF		50
 #define SO_DETACH_BPF		SO_DETACH_FILTER
 
+#define SO_UDP_DUP_UNICAST	51
+
 #endif /* __ASM_GENERIC_SOCKET_H */
diff -ruw linux-4.2/include/uapi/linux/if_tunnel.h linux-4.2-fbx/include/uapi/linux/if_tunnel.h
--- linux-4.2/include/uapi/linux/if_tunnel.h	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/include/uapi/linux/if_tunnel.h	2015-10-02 18:50:14.333093085 +0200
@@ -57,10 +57,23 @@
 	IFLA_IPTUN_ENCAP_FLAGS,
 	IFLA_IPTUN_ENCAP_SPORT,
 	IFLA_IPTUN_ENCAP_DPORT,
+	IFLA_IPTUN_FMRS,
 	__IFLA_IPTUN_MAX,
 };
 #define IFLA_IPTUN_MAX	(__IFLA_IPTUN_MAX - 1)
 
+enum {
+	IFLA_IPTUN_FMR_UNSPEC,
+	IFLA_IPTUN_FMR_IP6_PREFIX,
+	IFLA_IPTUN_FMR_IP4_PREFIX,
+	IFLA_IPTUN_FMR_IP6_PREFIX_LEN,
+	IFLA_IPTUN_FMR_IP4_PREFIX_LEN,
+	IFLA_IPTUN_FMR_EA_LEN,
+	IFLA_IPTUN_FMR_OFFSET,
+	__IFLA_IPTUN_FMR_MAX,
+};
+#define IFLA_IPTUN_FMR_MAX (__IFLA_IPTUN_FMR_MAX - 1)
+
 enum tunnel_encap_types {
 	TUNNEL_ENCAP_NONE,
 	TUNNEL_ENCAP_FOU,
diff -ruw linux-4.2/include/uapi/linux/Kbuild linux-4.2-fbx/include/uapi/linux/Kbuild
--- linux-4.2/include/uapi/linux/Kbuild	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/include/uapi/linux/Kbuild	2015-09-17 19:19:40.392808329 +0200
@@ -115,11 +115,14 @@
 header-y += errqueue.h
 header-y += ethtool.h
 header-y += eventpoll.h
+header-y += exfat_user.h
 header-y += fadvise.h
 header-y += falloc.h
 header-y += fanotify.h
 header-y += fb.h
 header-y += fcntl.h
+header-y += fbxatm.h
+header-y += fbxmtd_map_ioctl.h
 header-y += fd.h
 header-y += fdreg.h
 header-y += fib_rules.h
@@ -332,6 +335,7 @@
 header-y += ppp-ioctl.h
 header-y += pps.h
 header-y += prctl.h
+header-y += prctl-private.h
 header-y += psci.h
 header-y += ptp_clock.h
 header-y += ptrace.h
@@ -455,3 +459,10 @@
 header-y += xilinx-v4l2-controls.h
 header-y += zorro.h
 header-y += zorro_ids.h
+
+header-y += fbxatm.h
+header-y += fbxbridge.h
+header-y += fbxjtag.h
+
+header-y += remoti/
+header-y += hdmi-cec/
diff -ruw linux-4.2/include/uapi/linux/libc-compat.h linux-4.2-fbx/include/uapi/linux/libc-compat.h
--- linux-4.2/include/uapi/linux/libc-compat.h	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/include/uapi/linux/libc-compat.h	2015-09-17 19:19:40.392808329 +0200
@@ -48,13 +48,13 @@
 #ifndef _UAPI_LIBC_COMPAT_H
 #define _UAPI_LIBC_COMPAT_H
 
-/* We have included glibc headers... */
-#if defined(__GLIBC__)
+/* We have included libc headers... */
+#if !defined(__KERNEL__)
 
-/* Coordinate with glibc netinet/in.h header. */
+/* Coordinate with libc netinet/in.h header. */
 #if defined(_NETINET_IN_H)
 
-/* GLIBC headers included first so don't define anything
+/* LIBC headers included first so don't define anything
  * that would already be defined. */
 #define __UAPI_DEF_IN_ADDR		0
 #define __UAPI_DEF_IN_IPPROTO		0
@@ -68,7 +68,7 @@
  * if the glibc code didn't define them. This guard matches
  * the guard in glibc/inet/netinet/in.h which defines the
  * additional in6_addr macros e.g. s6_addr16, and s6_addr32. */
-#if defined(__USE_MISC) || defined (__USE_GNU)
+#if !defined(__GLIBC__) || defined(__USE_MISC) || defined (__USE_GNU)
 #define __UAPI_DEF_IN6_ADDR_ALT		0
 #else
 #define __UAPI_DEF_IN6_ADDR_ALT		1
@@ -83,7 +83,7 @@
 #else
 
 /* Linux headers included first, and we must define everything
- * we need. The expectation is that glibc will check the
+ * we need. The expectation is that the libc will check the
  * __UAPI_DEF_* defines and adjust appropriately. */
 #define __UAPI_DEF_IN_ADDR		1
 #define __UAPI_DEF_IN_IPPROTO		1
@@ -93,7 +93,7 @@
 #define __UAPI_DEF_IN_CLASS		1
 
 #define __UAPI_DEF_IN6_ADDR		1
-/* We unconditionally define the in6_addr macros and glibc must
+/* We unconditionally define the in6_addr macros and the libc must
  * coordinate. */
 #define __UAPI_DEF_IN6_ADDR_ALT		1
 #define __UAPI_DEF_SOCKADDR_IN6		1
@@ -115,7 +115,7 @@
 /* If we did not see any headers from any supported C libraries,
  * or we are being included in the kernel, then define everything
  * that we need. */
-#else /* !defined(__GLIBC__) */
+#else /* defined(__KERNEL__) */
 
 /* Definitions for in.h */
 #define __UAPI_DEF_IN_ADDR		1
@@ -138,6 +138,6 @@
 /* Definitions for xattr.h */
 #define __UAPI_DEF_XATTR		1
 
-#endif /* __GLIBC__ */
+#endif /* __KERNEL__ */
 
 #endif /* _UAPI_LIBC_COMPAT_H */
diff -ruw linux-4.2/include/uapi/linux/netlink.h linux-4.2-fbx/include/uapi/linux/netlink.h
--- linux-4.2/include/uapi/linux/netlink.h	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/include/uapi/linux/netlink.h	2015-09-15 19:18:39.994467562 +0200
@@ -1,7 +1,7 @@
 #ifndef _UAPI__LINUX_NETLINK_H
 #define _UAPI__LINUX_NETLINK_H
 
-#include <linux/kernel.h>
+//#include <linux/kernel.h>
 #include <linux/socket.h> /* for __kernel_sa_family_t */
 #include <linux/types.h>
 
diff -ruw linux-4.2/include/uapi/linux/serial_reg.h linux-4.2-fbx/include/uapi/linux/serial_reg.h
--- linux-4.2/include/uapi/linux/serial_reg.h	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/include/uapi/linux/serial_reg.h	2015-09-15 19:18:40.002467612 +0200
@@ -18,9 +18,18 @@
  * DLAB=0
  */
 #define UART_RX		0	/* In:  Receive buffer */
+#ifdef CONFIG_TANGO2
+#define UART_TX		1	/* Out: Transmit buffer */
+#else
 #define UART_TX		0	/* Out: Transmit buffer */
+#endif
 
+#ifdef CONFIG_TANGO2
+#define UART_IER	2	/* Out: Interrupt Enable Register */
+#else
 #define UART_IER	1	/* Out: Interrupt Enable Register */
+#endif
+
 #define UART_IER_MSI		0x08 /* Enable Modem status interrupt */
 #define UART_IER_RLSI		0x04 /* Enable receiver line status interrupt */
 #define UART_IER_THRI		0x02 /* Enable Transmitter holding register int. */
@@ -30,7 +39,12 @@
  */
 #define UART_IERX_SLEEP		0x10 /* Enable sleep mode */
 
+#ifdef CONFIG_TANGO2
+#define UART_IIR	3	/* In:  Interrupt ID Register */
+#else
 #define UART_IIR	2	/* In:  Interrupt ID Register */
+#endif
+
 #define UART_IIR_NO_INT		0x01 /* No interrupts pending */
 #define UART_IIR_ID		0x0e /* Mask for the interrupt ID */
 #define UART_IIR_MSI		0x00 /* Modem status interrupt */
@@ -44,7 +58,12 @@
 #define UART_IIR_XOFF		0x10 /* OMAP XOFF/Special Character */
 #define UART_IIR_CTS_RTS_DSR	0x20 /* OMAP CTS/RTS/DSR Change */
 
+#ifdef CONFIG_TANGO2
+#define UART_FCR	4	/* Out: FIFO Control Register */
+#else
 #define UART_FCR	2	/* Out: FIFO Control Register */
+#endif
+
 #define UART_FCR_ENABLE_FIFO	0x01 /* Enable the FIFO */
 #define UART_FCR_CLEAR_RCVR	0x02 /* Clear the RCVR FIFO */
 #define UART_FCR_CLEAR_XMIT	0x04 /* Clear the XMIT FIFO */
@@ -94,7 +113,12 @@
 	(((x) & UART_FCR_TRIGGER_MASK) >> UART_FCR_R_TRIG_SHIFT)
 #define UART_FCR_R_TRIG_MAX_STATE	4
 
+#ifdef CONFIG_TANGO2
+#define UART_LCR	5	/* Out: Line Control Register */
+#else
 #define UART_LCR	3	/* Out: Line Control Register */
+#endif
+
 /*
  * Note: if the word length is 5 bits (UART_LCR_WLEN5), then setting 
  * UART_LCR_STOP will select 1.5 stop bits, not 2 stop bits.
@@ -117,7 +141,11 @@
 #define UART_LCR_CONF_MODE_A	UART_LCR_DLAB	/* Configutation mode A */
 #define UART_LCR_CONF_MODE_B	0xBF		/* Configutation mode B */
 
+#ifdef CONFIG_TANGO2
+#define UART_MCR	6	/* Out: Modem Control Register */
+#else
 #define UART_MCR	4	/* Out: Modem Control Register */
+#endif
 #define UART_MCR_CLKSEL		0x80 /* Divide clock by 4 (TI16C752, EFR[4]=1) */
 #define UART_MCR_TCRTLR		0x40 /* Access TCR/TLR (TI16C752, EFR[4]=1) */
 #define UART_MCR_XONANY		0x20 /* Enable Xon Any (TI16C752, EFR[4]=1) */
@@ -128,8 +156,14 @@
 #define UART_MCR_RTS		0x02 /* RTS complement */
 #define UART_MCR_DTR		0x01 /* DTR complement */
 
+#ifdef CONFIG_TANGO2
+#define UART_LSR	7	/* In:  Line Status Register */
+#else
 #define UART_LSR	5	/* In:  Line Status Register */
+#endif
+
 #define UART_LSR_FIFOE		0x80 /* Fifo error */
+
 #define UART_LSR_TEMT		0x40 /* Transmitter empty */
 #define UART_LSR_THRE		0x20 /* Transmit-hold-register empty */
 #define UART_LSR_BI		0x10 /* Break interrupt indicator */
@@ -139,7 +173,11 @@
 #define UART_LSR_DR		0x01 /* Receiver data ready */
 #define UART_LSR_BRK_ERROR_BITS	0x1E /* BI, FE, PE, OE bits */
 
+#ifdef CONFIG_TANGO2
+#define UART_MSR	8	/* In:  Modem Status Register */
+#else
 #define UART_MSR	6	/* In:  Modem Status Register */
+#endif
 #define UART_MSR_DCD		0x80 /* Data Carrier Detect */
 #define UART_MSR_RI		0x40 /* Ring Indicator */
 #define UART_MSR_DSR		0x20 /* Data Set Ready */
@@ -150,18 +188,37 @@
 #define UART_MSR_DCTS		0x01 /* Delta CTS */
 #define UART_MSR_ANY_DELTA	0x0F /* Any of the delta bits! */
 
+#ifdef CONFIG_TANGO2
+#define UART_SCR	9	/* I/O: Scratch Register */
+#else
 #define UART_SCR	7	/* I/O: Scratch Register */
+#endif
 
 /*
  * DLAB=1
  */
+#ifdef CONFIG_TANGO2
+/*
+ * smp863x has DLM and DLM in one register
+ */
+#define UART_DL		10
+#define UART_CLKSEL     11      /* Clock selection */
+#else
 #define UART_DLL	0	/* Out: Divisor Latch Low */
 #define UART_DLM	1	/* Out: Divisor Latch High */
+#endif
 
 /*
  * LCR=0xBF (or DLAB=1 for 16C660)
  */
+#ifdef CONFIG_TANGO2
+/* EFR does not exist on TANGO2, we use a magic to catch accesses and
+ * make them nop */
+#define UART_EFR	42
+#else
 #define UART_EFR	2	/* I/O: Extended Features Register */
+#endif
+
 #define UART_XR_EFR	9	/* I/O: Extended Features Register (XR17D15x) */
 #define UART_EFR_CTS		0x80 /* CTS flow control */
 #define UART_EFR_RTS		0x40 /* RTS flow control */
diff -ruw linux-4.2/include/uapi/linux/sockios.h linux-4.2-fbx/include/uapi/linux/sockios.h
--- linux-4.2/include/uapi/linux/sockios.h	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/include/uapi/linux/sockios.h	2015-09-15 19:18:40.002467612 +0200
@@ -128,6 +128,14 @@
 #define SIOCSHWTSTAMP	0x89b0		/* set and get config		*/
 #define SIOCGHWTSTAMP	0x89b1		/* get config			*/
 
+/* fbxdiverter call */
+#define SIOCGFBXDIVERT  0x89c0		/* fbxdiverter support          */
+#define SIOCSFBXDIVERT  0x89c1		/* Set fbxdiverter options      */
+
+/* fbxbridge call */
+#define SIOCGFBXBRIDGE	0x89b2		/* fbxbridge support          */
+#define SIOCSFBXBRIDGE	0x89b3		/* Set fbxbridge options      */
+
 /* Device private ioctl calls */
 
 /*
diff -ruw linux-4.2/include/uapi/linux/tty.h linux-4.2-fbx/include/uapi/linux/tty.h
--- linux-4.2/include/uapi/linux/tty.h	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/include/uapi/linux/tty.h	2015-09-15 19:18:40.002467612 +0200
@@ -35,5 +35,6 @@
 #define N_TRACESINK	23	/* Trace data routing for MIPI P1149.7 */
 #define N_TRACEROUTER	24	/* Trace data routing for MIPI P1149.7 */
 #define N_NCI		25	/* NFC NCI UART */
+#define N_REMOTI	26	/* RemoTI over UART */
 
 #endif /* _UAPI_LINUX_TTY_H */
diff -ruw linux-4.2/init/Kconfig linux-4.2-fbx/init/Kconfig
--- linux-4.2/init/Kconfig	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/init/Kconfig	2015-09-15 19:18:40.014467687 +0200
@@ -874,6 +874,15 @@
 		     13 =>   8 KB for each CPU
 		     12 =>   4 KB for each CPU
 
+config FBX_DECRYPT_INITRD
+	bool "Decrypt initrd at boot"
+	depends on BLK_DEV_RAM
+	default n
+
+config FBX_DECRYPT_INITRD_KEY
+	string "Decryption key"
+	depends on FBX_DECRYPT_INITRD
+
 #
 # Architectures with an unreliable sched_clock() should select this:
 #
@@ -1338,7 +1347,6 @@
 menuconfig EXPERT
 	bool "Configure standard kernel features (expert users)"
 	# Unhide debug options, to make the on-by-default options visible
-	select DEBUG_KERNEL
 	help
 	  This option allows certain base kernel options and settings
           to be disabled or tweaked. This is for specialized
diff -ruw linux-4.2/init/Makefile linux-4.2-fbx/init/Makefile
--- linux-4.2/init/Makefile	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/init/Makefile	2013-12-04 14:33:26.239479089 +0100
@@ -13,6 +13,7 @@
 ifneq ($(CONFIG_ARCH_INIT_TASK),y)
 obj-y                          += init_task.o
 endif
+obj-$(CONFIG_FBX_DECRYPT_INITRD)+= fbx_decrypt_initrd.o rc4.o
 
 mounts-y			:= do_mounts.o
 mounts-$(CONFIG_BLK_DEV_RAM)	+= do_mounts_rd.o
diff -ruw linux-4.2/kernel/fork.c linux-4.2-fbx/kernel/fork.c
--- linux-4.2/kernel/fork.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/kernel/fork.c	2015-09-15 19:18:40.030467787 +0200
@@ -382,6 +382,11 @@
 
 	account_kernel_stack(ti, 1);
 
+	/*
+	 * inherit parent exec_mode.
+	 */
+	tsk->exec_mode = orig->exec_mode;
+
 	return tsk;
 
 free_ti:
diff -ruw linux-4.2/kernel/pid.c linux-4.2-fbx/kernel/pid.c
--- linux-4.2/kernel/pid.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/kernel/pid.c	2015-09-15 19:18:40.042467861 +0200
@@ -84,7 +84,7 @@
 	.ns.ops = &pidns_operations,
 #endif
 };
-EXPORT_SYMBOL_GPL(init_pid_ns);
+EXPORT_SYMBOL(init_pid_ns);
 
 /*
  * Note: disable interrupts while the pidmap_lock is held as an
diff -ruw linux-4.2/kernel/printk/printk.c linux-4.2-fbx/kernel/printk/printk.c
--- linux-4.2/kernel/printk/printk.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/kernel/printk/printk.c	2015-09-15 19:18:40.050467911 +0200
@@ -55,6 +55,10 @@
 #include "console_cmdline.h"
 #include "braille.h"
 
+#ifdef CONFIG_DEBUG_LL
+extern void printascii(char *);
+#endif
+
 int console_printk[4] = {
 	CONSOLE_LOGLEVEL_DEFAULT,	/* console_loglevel */
 	MESSAGE_LOGLEVEL_DEFAULT,	/* default_message_loglevel */
@@ -1720,6 +1724,10 @@
 	 */
 	text_len = vscnprintf(text, sizeof(textbuf), fmt, args);
 
+#ifdef CONFIG_DEBUG_LL
+	printascii(text);
+#endif
+
 	/* mark and strip a trailing newline */
 	if (text_len && text[text_len-1] == '\n') {
 		text_len--;
diff -ruw linux-4.2/kernel/resource.c linux-4.2-fbx/kernel/resource.c
--- linux-4.2/kernel/resource.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/kernel/resource.c	2015-09-15 19:18:40.054467936 +0200
@@ -358,15 +358,14 @@
 	read_lock(&resource_lock);
 
 	for (p = iomem_resource.child; p; p = next_resource(p, sibling_only)) {
-		if (p->flags != res->flags)
-			continue;
-		if (name && strcmp(p->name, name))
-			continue;
 		if (p->start > end) {
 			p = NULL;
 			break;
 		}
-		if ((p->end >= start) && (p->start < end))
+		if (p->flags != res->flags)
+			continue;
+		if ((p->end >= start) && (p->start < end) &&
+		    (name == NULL || !strcmp(p->name, name)))
 			break;
 	}
 
diff -ruw linux-4.2/kernel/sys.c linux-4.2-fbx/kernel/sys.c
--- linux-4.2/kernel/sys.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/kernel/sys.c	2015-09-17 19:19:40.392808329 +0200
@@ -10,6 +10,7 @@
 #include <linux/mman.h>
 #include <linux/reboot.h>
 #include <linux/prctl.h>
+#include <linux/prctl-private.h>
 #include <linux/highuid.h>
 #include <linux/fs.h>
 #include <linux/kmod.h>
@@ -2267,6 +2268,18 @@
 	case PR_GET_FP_MODE:
 		error = GET_FP_MODE(me);
 		break;
+	case PR_SET_EXEC_MODE:
+		if (arg2 != EXEC_MODE_UNLIMITED &&
+		    arg2 != EXEC_MODE_ONCE &&
+		    arg2 != EXEC_MODE_DENIED)
+			return -EINVAL;
+
+		if (arg2 > current->exec_mode)
+			return -EPERM;
+		current->exec_mode = arg2;
+		return 0;
+	case PR_GET_EXEC_MODE:
+		return current->exec_mode;
 	default:
 		error = -EINVAL;
 		break;
diff -ruw linux-4.2/lib/Kconfig linux-4.2-fbx/lib/Kconfig
--- linux-4.2/lib/Kconfig	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/lib/Kconfig	2015-09-15 19:18:40.082468111 +0200
@@ -531,4 +531,8 @@
 config ARCH_HAS_PMEM_API
 	bool
 
+config FBXSERIAL
+	bool
+	select CRC32
+
 endmenu
diff -ruw linux-4.2/lib/Makefile linux-4.2-fbx/lib/Makefile
--- linux-4.2/lib/Makefile	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/lib/Makefile	2015-09-15 19:18:40.086468136 +0200
@@ -205,3 +205,6 @@
 clean-files	+= oid_registry_data.c
 
 obj-$(CONFIG_UCS2_STRING) += ucs2_string.o
+
+obj-$(CONFIG_FBXSERIAL) += fbxserial.o
+
diff -ruw linux-4.2/net/8021q/vlan.c linux-4.2-fbx/net/8021q/vlan.c
--- linux-4.2/net/8021q/vlan.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/net/8021q/vlan.c	2015-09-15 19:18:40.130468410 +0200
@@ -208,7 +208,7 @@
 /*  Attach a VLAN device to a mac address (ie Ethernet Card).
  *  Returns 0 if the device was created or a negative error code otherwise.
  */
-static int register_vlan_device(struct net_device *real_dev, u16 vlan_id)
+int register_vlan_device(struct net_device *real_dev, u16 vlan_id)
 {
 	struct net_device *new_dev;
 	struct vlan_dev_priv *vlan;
diff -ruw linux-4.2/net/8021q/vlan_core.c linux-4.2-fbx/net/8021q/vlan_core.c
--- linux-4.2/net/8021q/vlan_core.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/net/8021q/vlan_core.c	2015-09-15 19:18:40.130468410 +0200
@@ -89,6 +89,12 @@
 }
 EXPORT_SYMBOL(__vlan_find_dev_deep_rcu);
 
+struct net_device *vlan_dev_upper_dev(const struct net_device *dev)
+{
+	return vlan_dev_priv(dev)->real_dev;
+}
+EXPORT_SYMBOL(vlan_dev_upper_dev);
+
 struct net_device *vlan_dev_real_dev(const struct net_device *dev)
 {
 	struct net_device *ret = vlan_dev_priv(dev)->real_dev;
diff -ruw linux-4.2/net/core/dev.c linux-4.2-fbx/net/core/dev.c
--- linux-4.2/net/core/dev.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/net/core/dev.c	2015-09-15 19:18:40.166468635 +0200
@@ -136,6 +136,7 @@
 #include <linux/errqueue.h>
 #include <linux/hrtimer.h>
 #include <linux/netfilter_ingress.h>
+#include <linux/kthread.h>
 
 #include "net-sysfs.h"
 
@@ -156,6 +157,19 @@
 					 struct net_device *dev,
 					 struct netdev_notifier_info *info);
 
+#ifdef CONFIG_NETRXTHREAD
+
+#define RXTHREAD_MAX_PROCESS    CONFIG_NETRXTHREAD_MAX_PROCESS
+#define RXTHREAD_MAX_PKTS       128
+
+static struct task_struct *krxd;
+static struct sk_buff_head krxd_pkt_queue[CONFIG_NETRXTHREAD_RX_QUEUE];
+unsigned int krxd_stats_pkts[CONFIG_NETRXTHREAD_RX_QUEUE];
+unsigned int krxd_stats_dropped[CONFIG_NETRXTHREAD_RX_QUEUE];
+static wait_queue_head_t krxd_wq;
+static unsigned int krxd_pkts_count;
+#endif
+
 /*
  * The @dev_base_head list is protected by @dev_base_lock and the rtnl
  * semaphore.
@@ -3515,6 +3529,23 @@
 	return ret;
 }
 
+/* Start Freebox added code */
+#if defined(CONFIG_FREEBOX_DIVERTER) || defined(CONFIG_FREEBOX_DIVERTER_MODULE)
+int (*fbxdiverter_hook)(struct sk_buff *);
+
+static int handle_fbxdiverter(struct sk_buff *skb)
+{
+	/* try_module_get is missing here, so there is a race on
+	 * fbxdiverter module deletion */
+	if (!fbxdiverter_hook)
+		return 0;
+	return fbxdiverter_hook(skb);
+}
+
+EXPORT_SYMBOL(fbxdiverter_hook);
+#endif
+
+
 /**
  *	netif_rx	-	post buffer to the network code
  *	@skb: buffer to post
@@ -3623,6 +3654,36 @@
 EXPORT_SYMBOL_GPL(br_fdb_test_addr_hook);
 #endif
 
+#ifdef CONFIG_FBXBRIDGE
+struct sk_buff *(*fbxbridge_handle_frame_hook)(struct fbxbridge *p, struct sk_buff *skb);
+
+struct fbxbridge;
+
+static inline struct sk_buff *handle_fbxbridge(struct sk_buff *skb,
+					       struct packet_type **pt_prev, int *ret,
+					       struct net_device *orig_dev)
+{
+	struct fbxbridge *fbxbr;
+
+	if (skb->pkt_type == PACKET_LOOPBACK ||
+	    (fbxbr = skb->dev->fbx_bridge_port) == NULL)
+		return skb;
+
+	if (skb->protocol != __constant_htons(ETH_P_IP) &&
+	    skb->protocol != __constant_htons(ETH_P_ARP))
+		return skb;
+
+	if (*pt_prev) {
+		*ret = deliver_skb(skb, *pt_prev, orig_dev);
+		*pt_prev = NULL;
+	}
+
+	return fbxbridge_handle_frame_hook(fbxbr, skb);
+}
+#else
+#define handle_fbxbridge(skb, pt_prev, ret, orig_dev)   (skb)
+#endif
+
 static inline struct sk_buff *handle_ing(struct sk_buff *skb,
 					 struct packet_type **pt_prev,
 					 int *ret, struct net_device *orig_dev)
@@ -3761,17 +3822,7 @@
 	int ret = NET_RX_DROP;
 	__be16 type;
 
-	net_timestamp_check(!netdev_tstamp_prequeue, skb);
-
-	trace_netif_receive_skb(skb);
-
 	orig_dev = skb->dev;
-
-	skb_reset_network_header(skb);
-	if (!skb_transport_header_was_set(skb))
-		skb_reset_transport_header(skb);
-	skb_reset_mac_len(skb);
-
 	pt_prev = NULL;
 
 another_round:
@@ -3809,6 +3860,9 @@
 	}
 
 skip_taps:
+	skb = handle_fbxbridge(skb, &pt_prev, &ret, orig_dev);
+	if (!skb)
+		goto out;
 #ifdef CONFIG_NET_INGRESS
 	if (static_key_false(&ingress_needed)) {
 		skb = handle_ing(skb, &pt_prev, &ret, orig_dev);
@@ -3904,7 +3958,9 @@
 	return ret;
 }
 
-static int __netif_receive_skb(struct sk_buff *skb)
+static int __netif_receive_skb(struct sk_buff *skb);
+
+static int __netif_receive_skb_end(struct sk_buff *skb)
 {
 	int ret;
 
@@ -3957,6 +4013,97 @@
 	return ret;
 }
 
+#ifdef CONFIG_NETRXTHREAD
+
+
+static int krxd_action(void *unused)
+{
+	struct sk_buff *skb;
+
+	set_user_nice(current, -5);
+	current->flags |= PF_NOFREEZE;
+	__set_current_state(TASK_RUNNING);
+
+	local_bh_disable();
+	while (1) {
+		unsigned int i, queue, count;
+
+		count = CONFIG_NETRXTHREAD_RX_QUEUE;
+		for (i = 0; i < count; i++) {
+			queue = count - i - 1;
+			skb = skb_dequeue(&krxd_pkt_queue[queue]);
+			if (!skb)
+				continue;
+			krxd_pkts_count--;
+			break;
+		}
+
+		if (!skb) {
+			local_bh_enable();
+			wait_event_interruptible(krxd_wq,
+						 krxd_pkts_count != 0);
+			set_current_state(TASK_RUNNING);
+			local_bh_disable();
+			continue;
+		}
+
+		__netif_receive_skb_end(skb);
+
+		/* only schedule when working on lowest prio queue */
+		if (queue == 0) {
+			if (need_resched()) {
+				local_bh_enable();
+				schedule();
+				local_bh_disable();
+			}
+		}
+	}
+	return 0;
+}
+#endif /* RXTHREAD */
+
+static int __netif_receive_skb(struct sk_buff *skb)
+{
+#ifdef CONFIG_NETRXTHREAD
+	unsigned int len, queue;
+#endif
+	net_timestamp_check(!netdev_tstamp_prequeue, skb);
+
+	trace_netif_receive_skb(skb);
+
+	skb_reset_network_header(skb);
+	if (!skb_transport_header_was_set(skb))
+		skb_reset_transport_header(skb);
+	skb_reset_mac_len(skb);
+
+#if defined(CONFIG_FREEBOX_DIVERTER) || defined(CONFIG_FREEBOX_DIVERTER_MODULE)
+	if (handle_fbxdiverter(skb))
+		return NET_RX_SUCCESS;
+#endif
+
+#ifndef CONFIG_NETRXTHREAD
+	return __netif_receive_skb_end(skb);
+#else
+	queue = skb->rxthread_prio & 1;
+
+	/* queue the packet to the rx thread */
+	local_bh_disable();
+	len = skb_queue_len(&krxd_pkt_queue[queue]);
+	if (len < RXTHREAD_MAX_PKTS) {
+		__skb_queue_tail(&krxd_pkt_queue[queue], skb);
+		krxd_pkts_count++;
+		krxd_stats_pkts[queue]++;
+		if (!len)
+			wake_up(&krxd_wq);
+	} else {
+		krxd_stats_dropped[queue]++;
+		dev_kfree_skb(skb);
+	}
+	local_bh_enable();
+	return NET_RX_SUCCESS;
+#endif
+}
+
 /**
  *	netif_receive_skb - process receive buffer from network
  *	@skb: buffer to process
@@ -6706,7 +6853,7 @@
 			rebroadcast_time = jiffies;
 		}
 
-		msleep(250);
+		msleep(1);
 
 		refcnt = netdev_refcnt_read(dev);
 
@@ -7638,6 +7785,19 @@
 	open_softirq(NET_TX_SOFTIRQ, net_tx_action);
 	open_softirq(NET_RX_SOFTIRQ, net_rx_action);
 
+#ifdef CONFIG_NETRXTHREAD
+	for (i = 0; i < CONFIG_NETRXTHREAD_RX_QUEUE; i++)
+		skb_queue_head_init(&krxd_pkt_queue[i]);
+	krxd_pkts_count = 0;
+	init_waitqueue_head(&krxd_wq);
+	krxd = kthread_create(krxd_action, NULL, "krxthread");
+	if (IS_ERR(krxd)) {
+		printk(KERN_ERR "unable to create krxd\n");
+		return -ENOMEM;
+	}
+	wake_up_process(krxd);
+#endif
+
 	hotcpu_notifier(dev_cpu_callback, 0);
 	dst_init();
 	rc = 0;
@@ -7646,3 +7806,7 @@
 }
 
 subsys_initcall(net_dev_init);
+
+#if defined(CONFIG_FBXBRIDGE_MODULE)
+EXPORT_SYMBOL(fbxbridge_handle_frame_hook);
+#endif
diff -ruw linux-4.2/net/core/net-procfs.c linux-4.2-fbx/net/core/net-procfs.c
--- linux-4.2/net/core/net-procfs.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/net/core/net-procfs.c	2013-12-04 14:33:29.559479142 +0100
@@ -311,6 +311,86 @@
 	.release = seq_release_net,
 };
 
+#ifdef CONFIG_NETRXTHREAD
+extern unsigned int krxd_stats_pkts[CONFIG_NETRXTHREAD_RX_QUEUE];
+extern unsigned int krxd_stats_dropped[CONFIG_NETRXTHREAD_RX_QUEUE];
+
+/*
+ *	This is invoked by the /proc filesystem handler to display a device
+ *	in detail.
+ */
+static void *krxthread_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	int *queue;
+
+	if (*pos > CONFIG_NETRXTHREAD_RX_QUEUE)
+		return NULL;
+
+	queue = kmalloc(sizeof(*queue), GFP_KERNEL);
+	if (!queue)
+		return NULL;
+	*queue = ((int)*pos - 1);
+
+	return queue;
+}
+
+static void *krxthread_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	int *queue = v;
+
+	if (*pos == CONFIG_NETRXTHREAD_RX_QUEUE)
+		return NULL;
+
+	++*queue;
+	*pos = *queue + 1;
+	return queue;
+}
+
+static void krxthread_seq_stop(struct seq_file *seq, void *v)
+{
+	kfree(v);
+}
+
+static void krxthread_seq_printf_stats(struct seq_file *seq, int queue)
+{
+	seq_printf(seq, "%8u %12u %12u\n",
+		   queue,
+		   krxd_stats_pkts[queue],
+		   krxd_stats_dropped[queue]);
+}
+
+static int krxthread_seq_show(struct seq_file *seq, void *v)
+{
+	int *queue = v;
+
+	if (*queue == -1)
+		seq_printf(seq, "%8s %12s %12s\n",
+			   "queue", "packets", "drops");
+	else
+		krxthread_seq_printf_stats(seq, *queue);
+	return 0;
+}
+
+static const struct seq_operations krxthread_seq_ops = {
+	.start = krxthread_seq_start,
+	.next  = krxthread_seq_next,
+	.stop  = krxthread_seq_stop,
+	.show  = krxthread_seq_show,
+};
+
+static int krxthread_seq_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &krxthread_seq_ops);
+}
+
+static const struct file_operations krxthread_seq_fops = {
+	.owner	 = THIS_MODULE,
+	.open    = krxthread_seq_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = seq_release,
+};
+#endif /* KRXTHREAD */
 
 static int __net_init dev_proc_net_init(struct net *net)
 {
@@ -323,9 +403,13 @@
 		goto out_dev;
 	if (!proc_create("ptype", S_IRUGO, net->proc_net, &ptype_seq_fops))
 		goto out_softnet;
-
 	if (wext_proc_init(net))
 		goto out_ptype;
+#ifdef CONFIG_NETRXTHREAD
+	if (!proc_create("krxthread", S_IRUGO, net->proc_net,
+			 &krxthread_seq_fops))
+		goto out_ptype;
+#endif
 	rc = 0;
 out:
 	return rc;
diff -ruw linux-4.2/net/core/skbuff.c linux-4.2-fbx/net/core/skbuff.c
--- linux-4.2/net/core/skbuff.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/net/core/skbuff.c	2015-09-15 19:18:40.174468685 +0200
@@ -774,6 +774,10 @@
 	memcpy(&new->headers_start, &old->headers_start,
 	       offsetof(struct sk_buff, headers_end) -
 	       offsetof(struct sk_buff, headers_start));
+
+#ifdef CONFIG_IP_FFN
+	new->ffn_state		= FFN_STATE_INIT;
+#endif
 	CHECK_SKB_FIELD(protocol);
 	CHECK_SKB_FIELD(csum);
 	CHECK_SKB_FIELD(hash);
@@ -824,6 +828,9 @@
 	C(mac_len);
 	n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len;
 	n->cloned = 1;
+#ifdef CONFIG_FBXBRIDGE
+	n->fbxbridge_state = 0;
+#endif
 	n->nohdr = 0;
 	n->destructor = NULL;
 	C(tail);
@@ -1181,6 +1188,9 @@
 	skb->cloned   = 0;
 	skb->hdr_len  = 0;
 	skb->nohdr    = 0;
+#ifdef CONFIG_FBXBRIDGE
+	skb->fbxbridge_state = 0;
+#endif
 	atomic_set(&skb_shinfo(skb)->dataref, 1);
 	return 0;
 
@@ -1636,6 +1646,10 @@
 	skb->tail     += delta;
 	skb->data_len -= delta;
 
+#ifdef CONFIG_FBXBRIDGE
+	skb->fbxbridge_state = 0;
+#endif
+
 	return skb_tail_pointer(skb);
 }
 EXPORT_SYMBOL(__pskb_pull_tail);
diff -ruw linux-4.2/net/core/sock.c linux-4.2-fbx/net/core/sock.c
--- linux-4.2/net/core/sock.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/net/core/sock.c	2015-09-15 19:18:40.174468685 +0200
@@ -988,6 +988,10 @@
 					 sk->sk_max_pacing_rate);
 		break;
 
+	case SO_UDP_DUP_UNICAST:
+		sock_valbool_flag(sk, SOCK_UDP_DUP_UNICAST, valbool);
+		break;
+
 	default:
 		ret = -ENOPROTOOPT;
 		break;
@@ -1248,6 +1252,10 @@
 		v.val = sk->sk_incoming_cpu;
 		break;
 
+	case SO_UDP_DUP_UNICAST:
+		v.val = sock_flag(sk, SOCK_UDP_DUP_UNICAST);
+		break;
+
 	default:
 		/* We implement the SO_SNDLOWAT etc to not be settable
 		 * (1003.1g 7).
diff -ruw linux-4.2/net/ipv4/ipconfig.c linux-4.2-fbx/net/ipv4/ipconfig.c
--- linux-4.2/net/ipv4/ipconfig.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/net/ipv4/ipconfig.c	2015-09-15 19:18:40.198468835 +0200
@@ -189,15 +189,61 @@
 static struct ic_device *ic_first_dev __initdata;	/* List of open device */
 static struct net_device *ic_dev __initdata;		/* Selected device */
 
-static bool __init ic_is_init_dev(struct net_device *dev)
+static bool __init ic_is_init_dev(struct net_device *dev, bool partial)
 {
+	char *p = NULL;
+	bool ret;
+
 	if (dev->flags & IFF_LOOPBACK)
 		return false;
-	return user_dev_name[0] ? !strcmp(dev->name, user_dev_name) :
+
+	if (partial) {
+		p = strchr(user_dev_name, '.');
+		if (p)
+			*p = 0;
+	}
+
+	ret = false;
+	if (user_dev_name[0] ? !strcmp(dev->name, user_dev_name) :
 	    (!(dev->flags & IFF_LOOPBACK) &&
 	     (dev->flags & (IFF_POINTOPOINT|IFF_BROADCAST)) &&
-	     strncmp(dev->name, "dummy", 5));
+	     strncmp(dev->name, "dummy", 5)))
+		ret = true;
+	if (p)
+		*p = '.';
+	return ret;
+}
+
+#ifdef CONFIG_VLAN_8021Q
+int register_vlan_device(struct net_device *real_dev, u16 vlan_id);
+
+static void __init prepare_vlan(void)
+{
+	unsigned short oflags;
+	struct net_device *dev;
+	char *p;
+	u16 vid;
+
+	if (!strchr(user_dev_name, '.'))
+		return;
+
+	p = strchr(user_dev_name, '.');
+	*p = 0;
+	vid = simple_strtoul(p + 1, NULL, 10);
+	dev = __dev_get_by_name(&init_net, user_dev_name);
+	if (!dev)
+		goto fail;
+
+	oflags = dev->flags;
+	if (dev_change_flags(dev, oflags | IFF_UP) < 0)
+		goto fail;
+
+	register_vlan_device(dev, vid);
+
+fail:
+	*p = '.';
 }
+#endif
 
 static int __init ic_open_devs(void)
 {
@@ -217,8 +263,13 @@
 			pr_err("IP-Config: Failed to open %s\n", dev->name);
 	}
 
+#ifdef CONFIG_VLAN_8021Q
+	/* register vlan device if needed */
+	prepare_vlan();
+#endif
+
 	for_each_netdev(&init_net, dev) {
-		if (ic_is_init_dev(dev)) {
+		if (ic_is_init_dev(dev, false)) {
 			int able = 0;
 			if (dev->mtu >= 364)
 				able |= IC_BOOTP;
@@ -267,7 +318,7 @@
 		int wait, elapsed;
 
 		for_each_netdev(&init_net, dev)
-			if (ic_is_init_dev(dev) && netif_carrier_ok(dev))
+			if (ic_is_init_dev(dev, false) && netif_carrier_ok(dev))
 				goto have_carrier;
 
 		msleep(1);
@@ -720,8 +771,10 @@
 			e += len;
 		}
 		if (*vendor_class_identifier) {
+#ifdef IPCONFIG_DEBUG
 			pr_info("DHCP: sending class identifier \"%s\"\n",
 				vendor_class_identifier);
+#endif
 			*e++ = 60;	/* Class-identifier */
 			len = strlen(vendor_class_identifier);
 			*e++ = len;
@@ -1379,7 +1432,7 @@
 
 		rtnl_lock();
 		for_each_netdev(&init_net, dev) {
-			if (ic_is_init_dev(dev)) {
+			if (ic_is_init_dev(dev, true)) {
 				found = 1;
 				break;
 			}
diff -ruw linux-4.2/net/ipv4/ip_input.c linux-4.2-fbx/net/ipv4/ip_input.c
--- linux-4.2/net/ipv4/ip_input.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/net/ipv4/ip_input.c	2015-09-15 19:18:40.194468810 +0200
@@ -187,10 +187,15 @@
 	return false;
 }
 
-static int ip_local_deliver_finish(struct sock *sk, struct sk_buff *skb)
+int ip_local_deliver_finish(struct sock *sk, struct sk_buff *skb)
 {
 	struct net *net = dev_net(skb->dev);
 
+#ifdef CONFIG_IP_FFN
+	if (skb->ffn_state == FFN_STATE_FORWARDABLE)
+		ip_ffn_add(skb, IP_FFN_LOCAL_IN);
+#endif
+
 	__skb_pull(skb, skb_network_header_len(skb));
 
 	rcu_read_lock();
@@ -452,6 +457,11 @@
 	/* Must drop socket now because of tproxy. */
 	skb_orphan(skb);
 
+#ifdef CONFIG_IP_FFN
+	if (!ip_ffn_process(skb))
+		return NET_RX_SUCCESS;
+#endif
+
 	return NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, NULL, skb,
 		       dev, NULL,
 		       ip_rcv_finish);
diff -ruw linux-4.2/net/ipv4/ip_output.c linux-4.2-fbx/net/ipv4/ip_output.c
--- linux-4.2/net/ipv4/ip_output.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/net/ipv4/ip_output.c	2015-09-15 19:18:40.194468810 +0200
@@ -201,6 +201,11 @@
 		skb = skb2;
 	}
 
+#ifdef CONFIG_IP_FFN
+	if (skb->ffn_state == FFN_STATE_FORWARDABLE)
+		ip_ffn_add(skb, IP_FFN_FINISH_OUT);
+#endif
+
 	rcu_read_lock_bh();
 	nexthop = (__force u32) rt_nexthop(rt, ip_hdr(skb)->daddr);
 	neigh = __ipv4_neigh_lookup_noref(dev, nexthop);
@@ -208,7 +213,6 @@
 		neigh = __neigh_create(&arp_tbl, &nexthop, dev, false);
 	if (!IS_ERR(neigh)) {
 		int res = dst_neigh_output(dst, neigh, skb);
-
 		rcu_read_unlock_bh();
 		return res;
 	}
@@ -353,6 +357,11 @@
 	skb->dev = dev;
 	skb->protocol = htons(ETH_P_IP);
 
+#ifdef CONFIG_IP_FFN
+	if (skb->ffn_state == FFN_STATE_FAST_FORWARDED)
+		return ip_finish_output(sk, skb);
+#endif
+
 	return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, sk, skb,
 			    NULL, dev,
 			    ip_finish_output,
@@ -1606,4 +1615,7 @@
 #if defined(CONFIG_IP_MULTICAST)
 	igmp_mc_init();
 #endif
+#ifdef CONFIG_IP_FFN
+	ip_ffn_init();
+#endif
 }
diff -ruw linux-4.2/net/ipv4/ip_tunnel_core.c linux-4.2-fbx/net/ipv4/ip_tunnel_core.c
--- linux-4.2/net/ipv4/ip_tunnel_core.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/net/ipv4/ip_tunnel_core.c	2015-09-15 19:18:40.194468810 +0200
@@ -45,6 +45,9 @@
 #include <net/net_namespace.h>
 #include <net/netns/generic.h>
 #include <net/rtnetlink.h>
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+#include <net/netfilter/nf_conntrack.h>
+#endif
 
 int iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
 		  __be32 src, __be32 dst, __u8 proto,
@@ -57,6 +60,13 @@
 	skb_scrub_packet(skb, xnet);
 
 	skb_clear_hash(skb);
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+	if (proto == IPPROTO_IPV6) {
+		skb->nfct = &nf_ct_untracked_get()->ct_general;
+		skb->nfctinfo = IP_CT_NEW;
+		nf_conntrack_get(skb->nfct);
+	}
+#endif
 	skb_dst_set(skb, &rt->dst);
 	memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
 
diff -ruw linux-4.2/net/ipv4/Kconfig linux-4.2-fbx/net/ipv4/Kconfig
--- linux-4.2/net/ipv4/Kconfig	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/net/ipv4/Kconfig	2015-09-15 19:18:40.186468760 +0200
@@ -391,6 +391,11 @@
 	tristate
 	default n
 
+config INET_XFRM_GC_THRESH
+	int "IP: xfrm garbage collect threshold"
+	depends on XFRM
+	default 32768
+
 config INET_XFRM_MODE_TRANSPORT
 	tristate "IP: IPsec transport mode"
 	default y
diff -ruw linux-4.2/net/ipv4/Makefile linux-4.2-fbx/net/ipv4/Makefile
--- linux-4.2/net/ipv4/Makefile	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/net/ipv4/Makefile	2015-09-15 19:18:40.186468760 +0200
@@ -15,6 +15,8 @@
 
 obj-$(CONFIG_NET_IP_TUNNEL) += ip_tunnel.o
 obj-$(CONFIG_SYSCTL) += sysctl_net_ipv4.o
+
+obj-$(CONFIG_IP_FFN) += ip_ffn.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_IP_MULTIPLE_TABLES) += fib_rules.o
 obj-$(CONFIG_IP_MROUTE) += ipmr.o
diff -ruw linux-4.2/net/ipv4/netfilter/ip_tables.c linux-4.2-fbx/net/ipv4/netfilter/ip_tables.c
--- linux-4.2/net/ipv4/netfilter/ip_tables.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/net/ipv4/netfilter/ip_tables.c	2015-09-15 19:18:40.198468835 +0200
@@ -30,6 +30,9 @@
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <net/netfilter/nf_log.h>
 #include "../../netfilter/xt_repldata.h"
+#ifdef CONFIG_FBXBRIDGE
+#include <linux/fbxbridge.h>
+#endif
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
@@ -1287,6 +1290,14 @@
 			   tmp.num_counters, tmp.counters);
 	if (ret)
 		goto free_newinfo_untrans;
+
+#ifdef CONFIG_IP_FFN
+	ip_ffn_flush_all();
+#endif
+
+#if defined(CONFIG_FBXBRIDGE) || defined(CONFIG_FBXBRIDGE_MODULE)
+	fbxbridge_fp_flush_all();
+#endif
 	return 0;
 
  free_newinfo_untrans:
diff -ruw linux-4.2/net/ipv4/netfilter/Kconfig linux-4.2-fbx/net/ipv4/netfilter/Kconfig
--- linux-4.2/net/ipv4/netfilter/Kconfig	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/net/ipv4/netfilter/Kconfig	2015-09-15 19:18:40.198468835 +0200
@@ -5,6 +5,13 @@
 menu "IP: Netfilter Configuration"
 	depends on INET && NETFILTER
 
+config IP_FFN
+	bool "IP: Fast forwarding and NAT"
+
+config IP_FFN_PROCFS
+	bool "IP: Fast forwarding and NAT /proc/net entries"
+	depends on IP_FFN
+
 config NF_DEFRAG_IPV4
 	tristate
 	default n
diff -ruw linux-4.2/net/ipv4/udp.c linux-4.2-fbx/net/ipv4/udp.c
--- linux-4.2/net/ipv4/udp.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/net/ipv4/udp.c	2015-09-15 19:18:40.214468934 +0200
@@ -211,6 +211,8 @@
 				       const struct sock *sk2),
 		     unsigned int hash2_nulladdr)
 {
+	struct sock *sk2;
+	struct hlist_nulls_node *node;
 	struct udp_hslot *hslot, *hslot2;
 	struct udp_table *udptable = sk->sk_prot->h.udp_table;
 	int    error = 1;
@@ -290,6 +292,48 @@
 	inet_sk(sk)->inet_num = snum;
 	udp_sk(sk)->udp_port_hash = snum;
 	udp_sk(sk)->udp_portaddr_hash ^= snum;
+
+	/* resolve udp reuse conflict */
+	if (sk->sk_reuse) {
+		bool found;
+
+		found = false;
+		sk_nulls_for_each(sk2, node, &hslot->head) {
+			if (!net_eq(sock_net(sk2), net) ||
+			    sk2 == sk ||
+			    (udp_sk(sk2)->udp_port_hash != snum))
+				continue;
+
+			if (sk2->sk_bound_dev_if &&
+			    sk->sk_bound_dev_if &&
+			    sk2->sk_bound_dev_if != sk->sk_bound_dev_if)
+				continue;
+
+			if (!(*saddr_comp)(sk, sk2))
+				continue;
+
+			found = true;
+			break;
+		}
+
+		sk_nulls_for_each(sk2, node, &hslot->head) {
+			if (!net_eq(sock_net(sk2), net) ||
+			    sk2 == sk ||
+			    (udp_sk(sk2)->udp_port_hash != snum))
+				continue;
+
+			if (sk2->sk_bound_dev_if &&
+			    sk->sk_bound_dev_if &&
+			    sk2->sk_bound_dev_if != sk->sk_bound_dev_if)
+				continue;
+
+			if (!(*saddr_comp)(sk, sk2))
+				continue;
+
+			sk->sk_reuse_conflict = found;
+		}
+	}
+
 	if (sk_unhashed(sk)) {
 		sk_nulls_add_node_rcu(sk, &hslot->head);
 		hslot->count++;
@@ -1712,6 +1756,56 @@
 	return 0;
 }
 
+/*
+ *	Unicast goes to one listener and all sockets with dup flag
+ *
+ *	Note: called only from the BH handler context.
+ */
+static int __udp4_lib_uc_conflict_deliver(struct net *net, struct sk_buff *skb,
+					  struct udphdr  *uh,
+					  __be32 saddr, __be32 daddr,
+					  struct udp_table *udptable)
+{
+	struct sock *sk, *stack[256 / sizeof(struct sock *)];
+	struct udp_hslot *hslot = udp_hashslot(udptable, net, ntohs(uh->dest));
+	struct hlist_nulls_node *node;
+	int dif;
+	unsigned int count = 0, non_dup_count = 0;
+
+	spin_lock(&hslot->lock);
+	sk = sk_nulls_head(&hslot->head);
+	dif = skb->dev->ifindex;
+	sk_nulls_for_each(sk, node, &hslot->head) {
+		if (!sock_flag(sk, SOCK_UDP_DUP_UNICAST)) {
+			if (!non_dup_count) {
+				stack[count++] = sk;
+				sock_hold(sk);
+			}
+			non_dup_count = 1;
+		} else {
+			stack[count++] = sk;
+			sock_hold(sk);
+		}
+
+		if (unlikely(count == ARRAY_SIZE(stack))) {
+			flush_stack(stack, count, skb, ~0);
+			count = 0;
+		}
+	}
+
+	spin_unlock(&hslot->lock);
+
+	/*
+	 * do the slow work with no lock held
+	 */
+	if (count) {
+		flush_stack(stack, count, skb, count - 1);
+	} else {
+		kfree_skb(skb);
+	}
+	return 0;
+}
+
 /* Initialize UDP checksum. If exited with zero value (success),
  * CHECKSUM_UNNECESSARY means, that no more checks are required.
  * Otherwise, csum completion requires chacksumming packet body,
@@ -1781,6 +1875,13 @@
 		if (unlikely(sk->sk_rx_dst != dst))
 			udp_sk_rx_dst_set(sk, dst);
 
+		if (sk->sk_reuse_conflict) {
+			sock_put(sk);
+			return __udp4_lib_uc_conflict_deliver(net, skb, uh,
+							      saddr, daddr,
+							      udptable);
+		}
+
 		ret = udp_queue_rcv_skb(sk, skb);
 		sock_put(sk);
 		/* a return value > 0 means to resubmit the input, but
diff -ruw linux-4.2/net/ipv4/xfrm4_policy.c linux-4.2-fbx/net/ipv4/xfrm4_policy.c
--- linux-4.2/net/ipv4/xfrm4_policy.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/net/ipv4/xfrm4_policy.c	2015-09-15 19:18:40.214468934 +0200
@@ -239,7 +239,7 @@
 	.destroy =		xfrm4_dst_destroy,
 	.ifdown =		xfrm4_dst_ifdown,
 	.local_out =		__ip_local_out,
-	.gc_thresh =		32768,
+	.gc_thresh =		CONFIG_INET_XFRM_GC_THRESH,
 };
 
 static struct xfrm_policy_afinfo xfrm4_policy_afinfo = {
diff -ruw linux-4.2/net/ipv6/udp.c linux-4.2-fbx/net/ipv6/udp.c
--- linux-4.2/net/ipv6/udp.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/net/ipv6/udp.c	2015-09-15 19:18:40.226469009 +0200
@@ -841,6 +841,52 @@
 	return 0;
 }
 
+/*
+ * Note: called only from the BH handler context,
+ * so we don't need to lock the hashes.
+ */
+static int __udp6_lib_uc_conflict_deliver(struct net *net, struct sk_buff *skb,
+		const struct in6_addr *saddr, const struct in6_addr *daddr,
+		struct udp_table *udptable)
+{
+	struct sock *sk, *stack[256 / sizeof(struct sock *)];
+	const struct udphdr *uh = udp_hdr(skb);
+	struct udp_hslot *hslot = udp_hashslot(udptable, net, ntohs(uh->dest));
+	struct hlist_nulls_node *node;
+	int dif;
+	unsigned int count = 0, non_dup_count = 0;
+
+	spin_lock(&hslot->lock);
+	sk = sk_nulls_head(&hslot->head);
+	dif = inet6_iif(skb);
+	sk_nulls_for_each (sk, node, &hslot->head) {
+		if (!sock_flag(sk, SOCK_UDP_DUP_UNICAST)) {
+			if (!non_dup_count) {
+				stack[count++] = sk;
+				sock_hold(sk);
+			}
+			non_dup_count = 1;
+		} else {
+			stack[count++] = sk;
+			sock_hold(sk);
+		}
+
+		if (unlikely(count == ARRAY_SIZE(stack))) {
+			flush_stack(stack, count, skb, ~0);
+			count = 0;
+		}
+	}
+
+	spin_unlock(&hslot->lock);
+
+	if (count) {
+		flush_stack(stack, count, skb, count - 1);
+	} else {
+		kfree_skb(skb);
+	}
+	return 0;
+}
+
 int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
 		   int proto)
 {
@@ -909,6 +955,12 @@
 		if (inet_get_convert_csum(sk) && uh->check && !IS_UDPLITE(sk))
 			skb_checksum_try_convert(skb, IPPROTO_UDP, uh->check,
 						 ip6_compute_pseudo);
+		if (sk->sk_reuse_conflict) {
+			sock_put(sk);
+			return __udp6_lib_uc_conflict_deliver(net, skb,
+							      saddr, daddr,
+							      udptable);
+		}
 
 		ret = udpv6_queue_rcv_skb(sk, skb);
 		sock_put(sk);
diff -ruw linux-4.2/net/Kconfig linux-4.2-fbx/net/Kconfig
--- linux-4.2/net/Kconfig	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/net/Kconfig	2015-09-15 19:18:40.134468435 +0200
@@ -50,6 +50,18 @@
 
 menu "Networking options"
 
+config NETSKBPAD
+	int "Size reserved by dev_alloc_skb"
+	default 16
+
+config NETRXTHREAD
+	bool "Do rx network processing in kernel thread"
+
+config NETRXTHREAD_RX_QUEUE
+	int "Number of rx queues"
+	default 1
+	depends on NETRXTHREAD
+
 source "net/packet/Kconfig"
 source "net/unix/Kconfig"
 source "net/xfrm/Kconfig"
@@ -208,6 +220,8 @@
 source "net/tipc/Kconfig"
 source "net/atm/Kconfig"
 source "net/l2tp/Kconfig"
+source "net/fbxatm/Kconfig"
+source "net/fbxbridge/Kconfig"
 source "net/802/Kconfig"
 source "net/bridge/Kconfig"
 source "net/dsa/Kconfig"
diff -ruw linux-4.2/net/Makefile linux-4.2-fbx/net/Makefile
--- linux-4.2/net/Makefile	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/net/Makefile	2015-09-15 19:18:40.134468435 +0200
@@ -36,6 +36,12 @@
 obj-$(CONFIG_AF_RXRPC)		+= rxrpc/
 obj-$(CONFIG_ATM)		+= atm/
 obj-$(CONFIG_L2TP)		+= l2tp/
+ifneq ($(CONFIG_FBXATM),)
+obj-y				+= fbxatm/
+endif
+ifneq ($(CONFIG_FBXBRIDGE),)
+obj-y				+= fbxbridge/
+endif
 obj-$(CONFIG_DECNET)		+= decnet/
 obj-$(CONFIG_PHONET)		+= phonet/
 ifneq ($(CONFIG_VLAN_8021Q),)
diff -ruw linux-4.2/net/netfilter/core.c linux-4.2-fbx/net/netfilter/core.c
--- linux-4.2/net/netfilter/core.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/net/netfilter/core.c	2015-09-15 19:18:40.262469234 +0200
@@ -183,7 +183,7 @@
 	}
 	return NF_ACCEPT;
 }
-
+EXPORT_SYMBOL(nf_iterate);
 
 /* Returns 1 if okfn() needs to be executed by the caller,
  * -EPERM for NF_DROP, 0 otherwise. */
diff -ruw linux-4.2/net/netfilter/nf_conntrack_core.c linux-4.2-fbx/net/netfilter/nf_conntrack_core.c
--- linux-4.2/net/netfilter/nf_conntrack_core.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/net/netfilter/nf_conntrack_core.c	2015-09-15 19:18:40.270469284 +0200
@@ -327,6 +327,10 @@
 	kfree(tmpl);
 }
 
+#ifdef CONFIG_IP_FFN
+extern void ip_ffn_ct_destroy(struct nf_conn *ct);
+#endif
+
 static void
 destroy_conntrack(struct nf_conntrack *nfct)
 {
@@ -338,6 +342,10 @@
 	NF_CT_ASSERT(atomic_read(&nfct->use) == 0);
 	NF_CT_ASSERT(!timer_pending(&ct->timeout));
 
+#ifdef CONFIG_IP_FFN
+	ip_ffn_ct_destroy(ct);
+#endif
+
 	if (unlikely(nf_ct_is_template(ct))) {
 		nf_ct_tmpl_free(ct);
 		return;
diff -ruw linux-4.2/net/netfilter/nf_conntrack_proto_tcp.c linux-4.2-fbx/net/netfilter/nf_conntrack_proto_tcp.c
--- linux-4.2/net/netfilter/nf_conntrack_proto_tcp.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/net/netfilter/nf_conntrack_proto_tcp.c	2015-10-01 20:02:09.156673942 +0200
@@ -1033,7 +1033,8 @@
 		break;
 	}
 
-	if (!tcp_in_window(ct, &ct->proto.tcp, dir, index,
+	if (!ct->proto.tcp.no_window_track &&
+	    !tcp_in_window(ct, &ct->proto.tcp, dir, index,
 			   skb, dataoff, th, pf)) {
 		spin_unlock_bh(&ct->lock);
 		return -NF_ACCEPT;
@@ -1099,6 +1100,18 @@
 	return NF_ACCEPT;
 }
 
+#ifdef CONFIG_IP_FFN
+int external_tcpv4_packet(struct nf_conn *ct,
+			  const struct sk_buff *skb,
+			  unsigned int dataoff,
+			  enum ip_conntrack_info ctinfo)
+{
+	return tcp_packet(ct, skb, dataoff, ctinfo, AF_INET, 0,
+			  tcp_get_timeouts(nf_ct_net(ct)));
+}
+#endif
+
+
 /* Called when a new connection for this protocol found. */
 static bool tcp_new(struct nf_conn *ct, const struct sk_buff *skb,
 		    unsigned int dataoff, unsigned int *timeouts)
diff -ruw linux-4.2/net/netfilter/nf_conntrack_proto_udp.c linux-4.2-fbx/net/netfilter/nf_conntrack_proto_udp.c
--- linux-4.2/net/netfilter/nf_conntrack_proto_udp.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/net/netfilter/nf_conntrack_proto_udp.c	2015-09-15 19:18:40.274469309 +0200
@@ -100,6 +100,17 @@
 	return NF_ACCEPT;
 }
 
+#ifdef CONFIG_IP_FFN
+int external_udpv4_packet(struct nf_conn *ct,
+			  const struct sk_buff *skb,
+			  unsigned int dataoff,
+			  enum ip_conntrack_info ctinfo)
+{
+	return udp_packet(ct, skb, dataoff, ctinfo, AF_INET, 0,
+			  udp_get_timeouts(nf_ct_net(ct)));
+}
+#endif
+
 /* Called when a new connection for this protocol found. */
 static bool udp_new(struct nf_conn *ct, const struct sk_buff *skb,
 		    unsigned int dataoff, unsigned int *timeouts)
diff -ruw linux-4.2/net/netfilter/xt_owner.c linux-4.2-fbx/net/netfilter/xt_owner.c
--- linux-4.2/net/netfilter/xt_owner.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/net/netfilter/xt_owner.c	2015-09-15 19:18:40.282469358 +0200
@@ -28,6 +28,61 @@
 	return 0;
 }
 
+static int __owner_match_simple_gid(kgid_t gid, kgid_t gid_min, kgid_t gid_max)
+{
+	return gid_gte(gid, gid_min) && gid_lte(gid, gid_max);
+}
+
+/*
+ * see kernel/groups.c:groups_to_user() function, which inspired the
+ * content of this function.
+ */
+static int __owner_match_gid_groupinfo(const struct group_info *group_info,
+				       kgid_t gid_min, kgid_t gid_max)
+{
+	unsigned int count = group_info->ngroups;
+	unsigned int block;
+
+	for (block = 0; block < group_info->nblocks; ++block) {
+		unsigned int cp_count = min(NGROUPS_PER_BLOCK, count);
+		unsigned int i;
+
+		for (i = 0; i < cp_count; ++i) {
+			if (__owner_match_simple_gid(
+					     group_info->blocks[block][i],
+					     gid_min, gid_max)) {
+				return 1;
+			}
+			count -= cp_count;
+		}
+	}
+	return 0;
+}
+
+static int owner_match_gid(const struct file *filp,
+			   const struct xt_owner_match_info *info)
+{
+	kgid_t gid_min = make_kgid(&init_user_ns, info->gid_min);
+	kgid_t gid_max = make_kgid(&init_user_ns, info->gid_max);
+
+	/*
+	 * direct match, this is the simple and only case handled by
+	 * the old code, file fsgid matches info gid range.
+	 */
+	if (__owner_match_simple_gid(filp->f_cred->fsgid, gid_min, gid_max))
+		return 1;
+
+	/*
+	 * otherwise we need to have a look to the group list available
+	 * in f_cred->group_info.
+	 */
+	if (__owner_match_gid_groupinfo(filp->f_cred->group_info,
+					gid_min, gid_max))
+		return 1;
+
+	return 0;
+}
+
 static bool
 owner_mt(const struct sk_buff *skb, struct xt_action_param *par)
 {
@@ -58,10 +113,7 @@
 	}
 
 	if (info->match & XT_OWNER_GID) {
-		kgid_t gid_min = make_kgid(&init_user_ns, info->gid_min);
-		kgid_t gid_max = make_kgid(&init_user_ns, info->gid_max);
-		if ((gid_gte(filp->f_cred->fsgid, gid_min) &&
-		     gid_lte(filp->f_cred->fsgid, gid_max)) ^
+		if (owner_match_gid(filp, info) ^
 		    !(info->invert & XT_OWNER_GID))
 			return false;
 	}
diff -ruw linux-4.2/net/socket.c linux-4.2-fbx/net/socket.c
--- linux-4.2/net/socket.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/net/socket.c	2015-09-15 19:18:40.322469608 +0200
@@ -877,6 +877,31 @@
 	return err;
 }
 
+static DEFINE_MUTEX(fbxdiverter_ioctl_mutex);
+static int (*fbxdiverter_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg) = NULL;
+
+void fbxdiverter_ioctl_set(int (*hook) (struct net *, unsigned int,
+					void __user *))
+{
+	mutex_lock(&fbxdiverter_ioctl_mutex);
+	fbxdiverter_ioctl_hook = hook;
+	mutex_unlock(&fbxdiverter_ioctl_mutex);
+}
+
+EXPORT_SYMBOL(fbxdiverter_ioctl_set);
+
+static DEFINE_MUTEX(fbxbridge_ioctl_mutex);
+static int (*fbxbridge_ioctl_hook)(struct net *, unsigned int cmd, void __user *arg) = NULL;
+
+void fbxbridge_set(int (*hook)(struct net *, unsigned int, void __user *))
+{
+	mutex_lock(&fbxbridge_ioctl_mutex);
+	fbxbridge_ioctl_hook = hook;
+	mutex_unlock(&fbxbridge_ioctl_mutex);
+}
+
+EXPORT_SYMBOL(fbxbridge_set);
+
 /*
  *	With an ioctl, arg may well be a user mode pointer, but we don't know
  *	what to do with it - that's up to the protocol still.
@@ -950,6 +975,28 @@
 				err = dlci_ioctl_hook(cmd, argp);
 			mutex_unlock(&dlci_ioctl_mutex);
 			break;
+		case SIOCGFBXDIVERT:
+		case SIOCSFBXDIVERT:
+			err = -ENOPKG;
+			if (!fbxdiverter_ioctl_hook)
+				request_module("fbxdiverter");
+
+			mutex_lock(&fbxdiverter_ioctl_mutex);
+			if (fbxdiverter_ioctl_hook)
+				err = fbxdiverter_ioctl_hook(net, cmd, argp);
+			mutex_unlock(&fbxdiverter_ioctl_mutex);
+			break;
+		case SIOCGFBXBRIDGE:
+		case SIOCSFBXBRIDGE:
+			err = -ENOPKG;
+			if (!fbxbridge_ioctl_hook)
+				request_module("fbxbridge");
+
+			mutex_lock(&fbxbridge_ioctl_mutex);
+			if (fbxbridge_ioctl_hook)
+				err = fbxbridge_ioctl_hook(net, cmd, argp);
+			mutex_unlock(&fbxbridge_ioctl_mutex);
+			break;
 		default:
 			err = sock_do_ioctl(net, sock, cmd, arg);
 			break;
diff -ruw linux-4.2/net/unix/af_unix.c linux-4.2-fbx/net/unix/af_unix.c
--- linux-4.2/net/unix/af_unix.c	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/net/unix/af_unix.c	2015-09-15 19:18:40.338469708 +0200
@@ -279,8 +279,10 @@
 	sk_for_each(s, &unix_socket_table[hash ^ type]) {
 		struct unix_sock *u = unix_sk(s);
 
+#ifdef UNIX_ABSTRACT_IGNORE_NETNS
 		if (!net_eq(sock_net(s), net))
 			continue;
+#endif
 
 		if (u->addr->len == len &&
 		    !memcmp(u->addr->name, sunname, len))
diff -ruw linux-4.2/net/unix/Kconfig linux-4.2-fbx/net/unix/Kconfig
--- linux-4.2/net/unix/Kconfig	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/net/unix/Kconfig	2014-05-09 14:12:54.468546162 +0200
@@ -19,6 +19,9 @@
 
 	  Say Y unless you know what you are doing.
 
+config UNIX_ABSTRACT_IGNORE_NETNS
+	bool "make abstract namespace global to all network namespaces"
+
 config UNIX_DIAG
 	tristate "UNIX: socket monitoring interface"
 	depends on UNIX
diff -ruw linux-4.2/sound/soc/kirkwood/Kconfig linux-4.2-fbx/sound/soc/kirkwood/Kconfig
--- linux-4.2/sound/soc/kirkwood/Kconfig	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/sound/soc/kirkwood/Kconfig	2015-09-15 19:18:40.690471903 +0200
@@ -15,3 +15,8 @@
 	  Say Y if you want to add support for SoC audio on
 	  the Armada 370 Development Board.
 
+config SND_KIRKWOOD_SOC_FBXGW2R
+	tristate "Soc Audio support for fbxgw2r"
+	depends on SND_KIRKWOOD_SOC && MACH_FBXGW2R && I2C
+	select SND_KIRKWOOD_SOC_I2S
+	select SND_SOC_CS42L52
diff -ruw linux-4.2/sound/soc/kirkwood/Makefile linux-4.2-fbx/sound/soc/kirkwood/Makefile
--- linux-4.2/sound/soc/kirkwood/Makefile	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/sound/soc/kirkwood/Makefile	2015-09-15 19:18:40.690471903 +0200
@@ -5,3 +5,6 @@
 snd-soc-armada-370-db-objs := armada-370-db.o
 
 obj-$(CONFIG_SND_KIRKWOOD_SOC_ARMADA370_DB) += snd-soc-armada-370-db.o
+
+snd-soc-fbxgw2r-objs := kirkwood-fbxgw2r.o
+obj-$(CONFIG_SND_KIRKWOOD_SOC_FBXGW2R) += snd-soc-fbxgw2r.o
diff -ruw linux-4.2/usr/Makefile linux-4.2-fbx/usr/Makefile
--- linux-4.2/usr/Makefile	2015-08-30 20:34:09.000000000 +0200
+++ linux-4.2-fbx/usr/Makefile	2015-09-15 19:18:40.854472926 +0200
@@ -49,8 +49,10 @@
 # in initramfs and to detect if any files are added/removed.
 # Removed files are identified by directory timestamp being updated
 # The dependency list is generated by gen_initramfs.sh -l
-ifneq ($(wildcard $(obj)/.initramfs_data.cpio.d),)
-	include $(obj)/.initramfs_data.cpio.d
+ifneq ($(wildcard $(obj)/.initramfs_data.cpio$(suffix_y).d),)
+	include $(obj)/.initramfs_data.cpio$(suffix_y).d
+else
+	deps_initramfs := FORCE
 endif
 
 quiet_cmd_initfs = GEN     $@
@@ -70,5 +72,5 @@
 # 3) If gen_init_cpio are newer than initramfs_data.cpio
 # 4) arguments to gen_initramfs.sh changes
 $(obj)/initramfs_data.cpio$(suffix_y): $(obj)/gen_init_cpio $(deps_initramfs) klibcdirs
-	$(Q)$(initramfs) -l $(ramfs-input) > $(obj)/.initramfs_data.cpio.d
+	$(Q)$(initramfs) -l $(ramfs-input) > $(obj)/.initramfs_data.cpio$(suffix_y).d
 	$(call if_changed,initfs)
--- /dev/null	2015-07-31 18:17:35.952031993 +0200
+++ linux-4.2-fbx/arch/x86/kernel/fbxbootinfo.c	2013-12-17 18:03:42.371570846 +0100
@@ -0,0 +1,46 @@
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/fbxbootinfo.h>
+#include <linux/init.h>
+
+#include <asm/bootparam.h>
+
+static struct fbx_bootinfo fbx_bootinfo;
+
+u32 loader_bank_number;
+EXPORT_SYMBOL(loader_bank_number);
+
+char loader_version_str[128];
+EXPORT_SYMBOL(loader_version_str);
+
+u32 loader_bank0_forced;
+EXPORT_SYMBOL(loader_bank0_forced);
+
+char cefdk_version_str[256];
+EXPORT_SYMBOL(cefdk_version_str);
+
+void __init parse_fbxbootinfo(u64 phys_addr, u32 data_len)
+{
+	struct setup_data *data;
+
+	data = early_memremap(phys_addr, data_len);
+	if (data->len != sizeof (fbx_bootinfo)) {
+		printk(KERN_ERR "%s: invalid length: "
+		       "have %i, want %i\n", __func__, data->len,
+			sizeof (fbx_bootinfo));
+	}
+	memcpy(&fbx_bootinfo, data->data, data->len);
+	early_iounmap(data, data_len);
+
+	loader_bank_number = fbx_bootinfo.bank_number;
+	memcpy(&loader_version_str, &fbx_bootinfo.uboot_version_str,
+				sizeof(loader_version_str));
+	loader_bank0_forced = fbx_bootinfo.bank0_forced;
+	memcpy(&cefdk_version_str, &fbx_bootinfo.cefdk_version_str,
+				sizeof(cefdk_version_str));
+}
+
+const struct fbx_bootinfo *arch_get_fbxbootinfo(void)
+{
+	return &fbx_bootinfo;
+}
--- /dev/null	2015-07-31 18:17:35.952031993 +0200
+++ linux-4.2-fbx/arch/x86/kernel/fbxserial.c	2013-12-17 18:03:42.371570846 +0100
@@ -0,0 +1,56 @@
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fbxserial.h>
+#include <linux/init.h>
+#include <linux/random.h>
+
+#include <asm/bootparam.h>
+
+static struct fbx_serial serial_info;
+static int parse_done;
+
+void __init parse_fbxserial_ext(u64 phys_addr, u32 data_len)
+{
+	struct setup_data *data;
+
+	data = early_memremap(phys_addr, data_len);
+	if (data->len != sizeof (serial_info)) {
+		printk(KERN_ERR "parse_fbxserial_ext: invalid length: "
+		       "have %i, want %i\n", data->len, sizeof (serial_info));
+	}
+	fbxserialinfo_read(data->data, &serial_info);
+	early_iounmap(data, data_len);
+	add_device_randomness(&serial_info, sizeof (serial_info));
+	parse_done = 1;
+}
+
+static int __init fbxserial_parse_check(void)
+{
+	if (!parse_done) {
+		/*
+		 * just setup magic and crc with bogus values.
+		 */
+		u32 bad_serial[sizeof (struct fbx_serial) / sizeof (u32)] =
+			{ 0xaa55aa55, 0xaa55aa55 };
+
+		/*
+		 * feed serial info deliberately with bad data to
+		 * enforce default settings.
+		 */
+		printk(KERN_ERR "parse_fbxserial_ext was not called. "
+		       "please fix/update your bootloader.\n");
+		fbxserialinfo_read(bad_serial, &serial_info);
+	}
+
+	return 0;
+}
+arch_initcall(fbxserial_parse_check);
+
+
+const struct fbx_serial *arch_get_fbxserial(void)
+{
+	return &serial_info;
+}
+
+EXPORT_SYMBOL(arch_get_fbxserial);
--- /dev/null	2015-07-31 18:17:35.952031993 +0200
+++ linux-4.2-fbx/arch/x86/platform/ce4100/fbx6hd.dts	2013-12-04 14:33:18.619478968 +0100
@@ -0,0 +1,454 @@
+/*
+ * CE4100 on Falcon Falls
+ *
+ * (c) Copyright 2010 Intel Corporation
+ *
+ * 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; version 2 of the License.
+ */
+/dts-v1/;
+/ {
+	model = "freebox,Freebox v6";
+	compatible = "intel,falconfalls";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "intel,ce4100";
+			reg = <0>;
+			lapic = <&lapic0>;
+		};
+	};
+
+	remoti: ti,cc2530@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "ti,remoti";
+		reset-gpio = <100 0>;	// gpio, polarity
+		id = <0>;
+
+		gpio@0 {
+			compatible = "ti,remoti-gpio";
+			gpios = <200 3>;	// base, number
+			#gpio-cells = <2>;
+			gpio-controller;
+		};
+
+		leds@1 {
+			compatible = "ti,remoti-leds";
+
+			rf-activity@0 {
+				label = "rf_activity:blue";
+			};
+
+			rf-pairing@1 {
+				label = "rf_pairing:red";
+			};
+		};
+
+		hdmi-cec@2 {
+			compatible = "ti,remoti-cec";
+		};
+	};
+
+	soc@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "intel,ce4100-cp";
+		ranges;
+
+		ioapic1: interrupt-controller@fec00000 {
+			#interrupt-cells = <2>;
+			compatible = "intel,ce4100-ioapic";
+			interrupt-controller;
+			reg = <0xfec00000 0x1000>;
+		};
+
+		timer@fed00000 {
+			compatible = "intel,ce4100-hpet";
+			reg = <0xfed00000 0x200>;
+		};
+
+		lapic0: interrupt-controller@fee00000 {
+			compatible = "intel,ce4100-lapic";
+			reg = <0xfee00000 0x1000>;
+		};
+
+		pci@3fc {
+			#address-cells = <3>;
+			#size-cells = <2>;
+			compatible = "intel,ce4100-pci", "pci";
+			device_type = "pci";
+			bus-range = <0 0>;
+			ranges = <0x2000000 0 0xbffff000 0xbffff000 0 0x1000
+				  0x2000000 0 0xdffe0000 0xdffe0000 0 0x1000
+				  0x0000000 0 0x0	 0x0	    0 0x100>;
+
+			/* Secondary IO-APIC */
+			ioapic2: interrupt-controller@0,1 {
+				#interrupt-cells = <2>;
+				compatible = "intel,ce4100-ioapic";
+				interrupt-controller;
+				reg = <0x100 0x0 0x0 0x0 0x0>;
+				assigned-addresses = <0x02000000 0x0 0xbffff000 0x0 0x1000>;
+			};
+
+			pci@1,0 {
+				#address-cells = <3>;
+				#size-cells = <2>;
+				compatible = "intel,ce4100-pci", "pci";
+				device_type = "pci";
+				bus-range = <1 1>;
+				reg = <0x0800 0x0 0x0 0x0 0x0>;
+				ranges = <0x2000000 0 0xdffe0000 0x2000000 0 0xdffe0000 0 0x1000>;
+
+				interrupt-parent = <&ioapic2>;
+
+				display@2,0 {
+					compatible = "pci8086,2e5b.2",
+						   "pci8086,2e5b",
+						   "pciclass038000",
+						   "pciclass0380";
+
+					reg = <0x11000 0x0 0x0 0x0 0x0>;
+					interrupts = <0 1>;
+				};
+
+				multimedia@3,0 {
+					compatible = "pci8086,2e5c.2",
+						   "pci8086,2e5c",
+						   "pciclass048000",
+						   "pciclass0480";
+
+					reg = <0x11800 0x0 0x0 0x0 0x0>;
+					interrupts = <2 1>;
+				};
+
+				multimedia@4,0 {
+					compatible = "pci8086,2e5d.2",
+						   "pci8086,2e5d",
+						   "pciclass048000",
+						   "pciclass0480";
+
+					reg = <0x12000 0x0 0x0 0x0 0x0>;
+					interrupts = <4 1>;
+				};
+
+				multimedia@4,1 {
+					compatible = "pci8086,2e5e.2",
+						   "pci8086,2e5e",
+						   "pciclass048000",
+						   "pciclass0480";
+
+					reg = <0x12100 0x0 0x0 0x0 0x0>;
+					interrupts = <5 1>;
+				};
+
+				sound@6,0 {
+					compatible = "pci8086,2e5f.2",
+						   "pci8086,2e5f",
+						   "pciclass040100",
+						   "pciclass0401";
+
+					reg = <0x13000 0x0 0x0 0x0 0x0>;
+					interrupts = <6 1>;
+				};
+
+				sound@6,1 {
+					compatible = "pci8086,2e5f.2",
+						   "pci8086,2e5f",
+						   "pciclass040100",
+						   "pciclass0401";
+
+					reg = <0x13100 0x0 0x0 0x0 0x0>;
+					interrupts = <7 1>;
+				};
+
+				sound@6,2 {
+					compatible = "pci8086,2e60.2",
+						   "pci8086,2e60",
+						   "pciclass040100",
+						   "pciclass0401";
+
+					reg = <0x13200 0x0 0x0 0x0 0x0>;
+					interrupts = <8 1>;
+				};
+
+				display@8,0 {
+					compatible = "pci8086,2e61.2",
+						   "pci8086,2e61",
+						   "pciclass038000",
+						   "pciclass0380";
+
+					reg = <0x14000 0x0 0x0 0x0 0x0>;
+					interrupts = <9 1>;
+				};
+
+				display@8,1 {
+					compatible = "pci8086,2e62.2",
+						   "pci8086,2e62",
+						   "pciclass038000",
+						   "pciclass0380";
+
+					reg = <0x14100 0x0 0x0 0x0 0x0>;
+					interrupts = <10 1>;
+				};
+
+				multimedia@8,2 {
+					compatible = "pci8086,2e63.2",
+						   "pci8086,2e63",
+						   "pciclass048000",
+						   "pciclass0480";
+
+					reg = <0x14200 0x0 0x0 0x0 0x0>;
+					interrupts = <11 1>;
+				};
+
+				entertainment-encryption@9,0 {
+					compatible = "pci8086,2e64.2",
+						   "pci8086,2e64",
+						   "pciclass101000",
+						   "pciclass1010";
+
+					reg = <0x14800 0x0 0x0 0x0 0x0>;
+					interrupts = <12 1>;
+				};
+
+				localbus@a,0 {
+					compatible = "pci8086,2e65.2",
+						   "pci8086,2e65",
+						   "pciclassff0000",
+						   "pciclassff00";
+
+					reg = <0x15000 0x0 0x0 0x0 0x0>;
+				};
+
+				serial@b,0 {
+					compatible = "pci8086,2e66.2",
+						   "pci8086,2e66",
+						   "pciclass070003",
+						   "pciclass0700";
+
+					reg = <0x15800 0x0 0x0 0x0 0x0>;
+					interrupts = <14 1>;
+				};
+
+				gpio@b,1 {
+					compatible = "pci8086,2e67.2",
+						   "pci8086,2e67",
+						   "pciclassff0000",
+						   "pciclassff00";
+
+					#gpio-cells = <2>;
+					reg = <0x15900 0x0 0x0 0x0 0x0>;
+					interrupts = <15 1>;
+					gpio-controller;
+				};
+
+				i2c-controller@b,2 {
+					#address-cells = <2>;
+					#size-cells = <1>;
+					compatible = "pci8086,2e68.2",
+						   "pci8086,2e68",
+						   "pciclass,ff0000",
+						   "pciclass,ff00";
+
+					reg = <0x15a00 0x0 0x0 0x0 0x0>;
+					interrupts = <16 1>;
+					ranges = <0 0	0x02000000 0 0xdffe0500	0x100
+						  1 0	0x02000000 0 0xdffe0600	0x100
+						  2 0	0x02000000 0 0xdffe0700	0x100>;
+
+					i2c@0 {
+						#address-cells = <1>;
+						#size-cells = <0>;
+						compatible = "intel,ce4100-i2c-controller";
+						reg = <0 0 0x100>;
+					};
+
+					i2c@1 {
+						#address-cells = <1>;
+						#size-cells = <0>;
+						compatible = "intel,ce4100-i2c-controller";
+						reg = <1 0 0x100>;
+					};
+
+					i2c@2 {
+						#address-cells = <1>;
+						#size-cells = <0>;
+						compatible = "intel,ce4100-i2c-controller";
+						reg = <2 0 0x100>;
+
+						pmu@60 {
+							#gpio-cells = <2>;
+							compatible = "freebox,pic16-pmu";
+							reg = <0x60>;
+							gpio-controller;
+						};
+					};
+				};
+
+				smard-card@b,3 {
+					compatible = "pci8086,2e69.2",
+						   "pci8086,2e69",
+						   "pciclass070500",
+						   "pciclass0705";
+
+					reg = <0x15b00 0x0 0x0 0x0 0x0>;
+					interrupts = <15 1>;
+				};
+
+				spi-controller@b,4 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible =
+						"pci8086,2e6a.2",
+						"pci8086,2e6a",
+						"pciclass,ff0000",
+						"pciclass,ff00";
+
+					reg = <0x15c00 0x0 0x0 0x0 0x0>;
+					interrupts = <15 1>;
+
+					dac@0 {
+						compatible = "ti,pcm1755";
+						reg = <0>;
+						spi-max-frequency = <115200>;
+					};
+
+					dac@1 {
+						compatible = "ti,pcm1609a";
+						reg = <1>;
+						spi-max-frequency = <115200>;
+					};
+
+					eeprom@2 {
+						compatible = "atmel,at93c46";
+						reg = <2>;
+						spi-max-frequency = <115200>;
+					};
+				};
+
+				multimedia@b,7 {
+					compatible = "pci8086,2e6d.2",
+						   "pci8086,2e6d",
+						   "pciclassff0000",
+						   "pciclassff00";
+
+					reg = <0x15f00 0x0 0x0 0x0 0x0>;
+				};
+
+				ethernet@c,0 {
+					compatible = "pci8086,2e6e.2",
+						   "pci8086,2e6e",
+						   "pciclass020000",
+						   "pciclass0200";
+
+					reg = <0x16000 0x0 0x0 0x0 0x0>;
+					interrupts = <21 1>;
+				};
+
+				clock@c,1 {
+					compatible = "pci8086,2e6f.2",
+						   "pci8086,2e6f",
+						   "pciclassff0000",
+						   "pciclassff00";
+
+					reg = <0x16100 0x0 0x0 0x0 0x0>;
+					interrupts = <3 1>;
+				};
+
+				usb@d,0 {
+					compatible = "pci8086,2e70.2",
+						   "pci8086,2e70",
+						   "pciclass0c0320",
+						   "pciclass0c03";
+
+					reg = <0x16800 0x0 0x0 0x0 0x0>;
+					interrupts = <22 1>;
+				};
+
+				usb@d,1 {
+					compatible = "pci8086,2e70.2",
+						   "pci8086,2e70",
+						   "pciclass0c0320",
+						   "pciclass0c03";
+
+					reg = <0x16900 0x0 0x0 0x0 0x0>;
+					interrupts = <22 1>;
+				};
+
+				sata@e,0 {
+					compatible = "pci8086,2e71.0",
+						   "pci8086,2e71",
+						   "pciclass010601",
+						   "pciclass0106";
+
+					reg = <0x17000 0x0 0x0 0x0 0x0>;
+					interrupts = <23 1>;
+				};
+
+				flash@f,0 {
+					compatible = "pci8086,701.1",
+						   "pci8086,701",
+						   "pciclass050100",
+						   "pciclass0501";
+
+					reg = <0x17800 0x0 0x0 0x0 0x0>;
+					interrupts = <13 1>;
+				};
+
+				entertainment-encryption@10,0 {
+					compatible = "pci8086,702.1",
+						   "pci8086,702",
+						   "pciclass101000",
+						   "pciclass1010";
+
+					reg = <0x18000 0x0 0x0 0x0 0x0>;
+				};
+
+				co-processor@11,0 {
+					compatible = "pci8086,703.1",
+						   "pci8086,703",
+						   "pciclass0b4000",
+						   "pciclass0b40";
+
+					reg = <0x18800 0x0 0x0 0x0 0x0>;
+					interrupts = <1 1>;
+				};
+
+				multimedia@12,0 {
+					compatible = "pci8086,704.0",
+						   "pci8086,704",
+						   "pciclass048000",
+						   "pciclass0480";
+
+					reg = <0x19000 0x0 0x0 0x0 0x0>;
+				};
+			};
+
+			isa@1f,0 {
+				#address-cells = <2>;
+				#size-cells = <1>;
+				compatible = "isa";
+				reg = <0xf800 0x0 0x0 0x0 0x0>;
+				ranges = <1 0 0 0 0 0x100>;
+
+				rtc@70 {
+					compatible = "intel,ce4100-rtc", "motorola,mc146818";
+					interrupts = <8 3>;
+					interrupt-parent = <&ioapic1>;
+					ctrl-reg = <2>;
+					freq-reg = <0x26>;
+					reg = <1 0x70 2>;
+				};
+			};
+		};
+	};
+};
--- /dev/null	2015-07-31 18:17:35.952031993 +0200
+++ linux-4.2-fbx/arch/x86/platform/ce4100/i2c-intelce.c	2013-12-04 14:33:18.619478968 +0100
@@ -0,0 +1,456 @@
+/*
+ * i2c driver for Intel CE
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/msr.h>
+
+#define DEBUG
+
+#ifdef DEBUG
+#define DPRINTF(args...)  printk(args)
+#else
+#define DPRINTF(args...)
+#endif
+
+#define ICR             (0x00)
+#define ISR             (0x04)
+#define ISAR            (0x08)
+#define IBMR            (0x10)
+#define IDBR            (0x0C)
+
+#define ICR_START       (1 << 0)           /* start bit */
+#define ICR_STOP        (1 << 1)           /* stop bit */
+#define ICR_ACKNAK      (1 << 2)           /* send ACK(0) or NAK(1) */
+#define ICR_TB          (1 << 3)           /* transfer byte bit */
+#define ICR_MA          (1 << 4)           /* master abort */
+#define ICR_SCLE        (1 << 5)           /* master clock enable */
+#define ICR_IUE         (1 << 6)           /* unit enable */
+#define ICR_GCD         (1 << 7)           /* general call disable */
+#define ICR_ITEIE       (1 << 8)           /* enable tx interrupts */
+#define ICR_IRFIE       (1 << 9)           /* enable rx interrupts */
+#define ICR_BEIE        (1 << 10)          /* enable bus error ints */
+#define ICR_SSDIE       (1 << 11)          /* slave STOP detected int enable */
+#define ICR_ALDIE       (1 << 12)          /* enable arbitration interrupt */
+#define ICR_SADIE       (1 << 13)          /* slave address detected int enable */
+#define ICR_UR          (1 << 14)          /* unit reset */
+#define ICR_FM          (1 << 15)          /* fast mode */
+
+#define ISR_RWM         (1 << 0)           /* read/write mode */
+#define ISR_ACKNAK      (1 << 1)           /* ack/nak status */
+#define ISR_UB          (1 << 2)           /* unit busy */
+#define ISR_IBB         (1 << 3)           /* bus busy */
+#define ISR_SSD         (1 << 4)           /* slave stop detected */
+#define ISR_ALD         (1 << 5)           /* arbitration loss detected */
+#define ISR_ITE         (1 << 6)           /* tx buffer empty */
+#define ISR_IRF         (1 << 7)           /* rx buffer full */
+#define ISR_GCAD        (1 << 8)           /* general call address detected */
+#define ISR_SAD         (1 << 9)           /* slave address detected */
+#define ISR_BED         (1 << 10)          /* bus error no ACK/NAK */
+#define ISR_RESERVED	0xfffff800
+
+#define I2C_WRITE	0
+#define I2C_READ	1
+
+#define I2C_BUS_ADDR	(0xdffe0500)
+#define I2C_BUS1_ADDR	(I2C_BUS_ADDR + 0x100)
+#define I2C_BUS_SIZE	(0x100 - 1)
+
+#define PFX	"CK505: "
+
+static void __iomem *base_addr;
+
+static inline u32 i2c_reg_read(u32 reg)
+{
+	return readl(base_addr + reg);
+}
+
+static inline void i2c_reg_write(u32 val, u32 reg)
+{
+	writel(val, base_addr + reg);
+}
+
+/*
+ * udelay is not working yet, so provide a dummy version
+ * which is sufficent for polling.
+ */
+static u32 ticks_per_usec = 1000;
+
+static inline void __local_udelay(u32 usec)
+{
+	u64 now;
+	u64 end;
+
+	now = __native_read_tsc();
+	end = now + (u64)usec * ticks_per_usec;
+
+	while (__native_read_tsc() < end)
+		;
+}
+
+/*
+ * this is a hardcoded offset, we do not have working PCI right now to
+ * read the address from the PCI config space. (but it would be
+ * cleaner to do so).
+ */
+#define CRBAR_BASE		0xa0000000
+
+/*
+ * inside CRBAR_BASE
+ */
+#define CRBAR_FSB_REG		0x0
+# define FSB_MASK		0x03
+# define FSB_100		0x0
+# define FSB_133		0x1
+# define FSB_166		0x2
+# define FSB_200		0x3
+
+#define CRBAR_STRAP_RATIO_REG	0x14
+# define STRAP_RATIO_MASK	0xf
+
+/*
+ * name guessed from context in intel source code.
+ */
+#define FUSING_RATIO_MSR	0x198
+# define FUSING_RATIO_SHIFT	8
+# define FUSING_RATIO_MASK	0x1f
+
+static void __iomem *crbar_base;
+
+/*
+ * FSB is found inside CRBAR zone.
+ */
+static u32 get_cpu_fsb_mhz(void)
+{
+	u32 fsb_reg;
+
+	fsb_reg = readl(crbar_base + CRBAR_FSB_REG);
+	switch (fsb_reg & FSB_MASK) {
+	case FSB_100:
+		return 100;
+		break;
+	case FSB_133:
+		return 133;
+		break;
+	case FSB_166:
+		return 166;
+		break;
+	case FSB_200:
+		return 200;
+	}
+	/* safe default ? */
+	return 100;
+}
+
+/*
+ * strapped ratio is found on CRBAR zone too.
+ */
+static u32 get_cpu_strap_ratio(void)
+{
+	u32 strap_ratio_reg;
+
+	strap_ratio_reg = readl(crbar_base + CRBAR_STRAP_RATIO_REG);
+	return 21 - (strap_ratio_reg & STRAP_RATIO_MASK);
+}
+
+/*
+ * use MSRs to get fused limit.
+ */
+static u32 get_cpu_fusing_ratio(void)
+{
+	u32 dummy, fusing_ratio_msr;
+
+	rdmsr(FUSING_RATIO_MSR, dummy, fusing_ratio_msr);
+
+	return (fusing_ratio_msr >> FUSING_RATIO_SHIFT) & FUSING_RATIO_MASK;
+
+}
+
+static unsigned long __get_cpu_mhz(void)
+{
+	u32 fsb_mhz;
+	u32 strap_ratio;
+	u32 fusing_ratio;
+	u32 ratio;
+	u32 cpu_mhz;
+
+	crbar_base = early_ioremap(CRBAR_BASE, 0x20);
+	if (!crbar_base) {
+		printk(KERN_ERR "failde to remap CRBAR base\n");
+		return 1200;
+	}
+
+	fsb_mhz = get_cpu_fsb_mhz();
+	strap_ratio = get_cpu_strap_ratio();
+	fusing_ratio = get_cpu_fusing_ratio();
+
+	if (strap_ratio > fusing_ratio) {
+		printk("warning: strap ratio higher than fused ratio, "
+		       "will use fused ratio.\n");
+		ratio = fusing_ratio;
+	} else
+		ratio = strap_ratio;
+
+	cpu_mhz = ratio * fsb_mhz;
+
+	early_iounmap(crbar_base, 0x20);
+
+	return cpu_mhz;
+}
+
+
+static int i2c_hw_init(void)
+{
+	u32 reg = 0;
+	unsigned long cpu_hz;
+
+	/*
+	 * initialize udelay
+	 */
+	cpu_hz = __get_cpu_mhz() * 1000000;
+	ticks_per_usec = cpu_hz / 1000000;
+
+	base_addr = early_ioremap(I2C_BUS1_ADDR, I2C_BUS_SIZE);
+	if (!base_addr) {
+		printk(KERN_ERR PFX "failed to early_ioremap 0x%08x\n", I2C_BUS1_ADDR);
+		return -1;
+	}
+
+	/*
+	 * reset the unit and clear any pending interrupt
+	 */
+	reg |= ICR_UR;
+	i2c_reg_write(reg, ICR);
+	i2c_reg_write(0, ICR);
+	i2c_reg_write(0, ISR);
+
+	/*
+	 * TX empty and RX full interrupts are set automatically
+	 */
+	reg = ICR_IUE | ICR_SCLE | ICR_GCD;
+	i2c_reg_write(reg, ICR);
+	__local_udelay(100);
+
+	return 0;
+}
+
+static void i2c_clear_interrupt(void)
+{
+	u32 reg;
+
+	reg = i2c_reg_read(ISR);
+	reg &= (ISR_SSD | ISR_ALD | ISR_ITE | ISR_IRF | ISR_SAD | ISR_BED);
+	i2c_reg_write(reg, ISR);
+}
+
+static int i2c_wait(u32 cond, u32 *last_reg)
+{
+	volatile u32 reg;
+	int count = 100;
+
+	while (count) {
+		reg = i2c_reg_read(ISR);
+		if (reg & cond) {
+			*last_reg = reg;
+			i2c_clear_interrupt();
+			return 0;
+		}
+		count--;
+		__local_udelay(10);
+	}
+
+	i2c_clear_interrupt();
+	return -1;
+}
+
+static int i2c_send_start(u8 addr, unsigned op)
+{
+	u32 reg;
+	int status;
+
+	/* write slave address */
+	i2c_reg_write((addr << 1) | op, IDBR);
+
+	reg = i2c_reg_read(ICR);
+	reg &= ~(ICR_START | ICR_STOP | ICR_ALDIE | ICR_ACKNAK | ICR_TB);
+	reg |= ICR_START | ICR_TB;
+	i2c_reg_write(reg, ICR);
+
+	status = i2c_wait(ISR_ITE | ISR_BED, &reg);
+	if (status < 0) {
+		DPRINTF("%s: timeout\n", __func__);
+		return -1;
+	}
+
+	if (reg & ISR_BED) {
+		DPRINTF("%s: bus error\n", __func__);
+		return -1;
+	}
+
+	if (reg & ISR_ACKNAK) {
+		DPRINTF("%s: invalid return: %08x\n", __func__, reg);
+		return -2;
+	}
+
+	return 0;
+}
+
+static int i2c_tx_byte(u8 byte, unsigned stop)
+{
+	u32 reg;
+	int status;
+
+	/* load data */
+	i2c_reg_write(byte, IDBR);
+
+	reg = i2c_reg_read(ICR);
+	reg &= ~(ICR_START | ICR_STOP | ICR_ALDIE | ICR_ACKNAK | ICR_TB);
+	reg |= ICR_ALDIE | ICR_TB;
+	if (stop)
+		reg |= ICR_STOP;
+
+	i2c_reg_write(reg, ICR);
+
+	status = i2c_wait(ISR_ITE, &reg);
+	if (status < 0) {
+		DPRINTF("%s: timeout\n", __func__);
+		return -1;
+	}
+
+	if (reg & ISR_BED) {
+		DPRINTF("%s: bus error\n", __func__);
+		return -1;
+	}
+
+	if (reg & ISR_ACKNAK) {
+		DPRINTF("%s: invalid return: %08x\n", __func__, reg);
+		return -2;
+	}
+
+	return 0;
+}
+
+static int i2c_rx_byte(unsigned stop)
+{
+	u32 reg;
+	int status;
+
+	reg = i2c_reg_read(ICR);
+	reg &= ~(ICR_START | ICR_STOP | ICR_ALDIE | ICR_ACKNAK | ICR_TB);
+	reg |= ICR_ALDIE | ICR_TB;
+	if (stop)
+		reg |= ICR_STOP | ICR_ACKNAK;
+
+	i2c_reg_write(reg, ICR);
+	status = i2c_wait(ISR_IRF, &reg);
+	if (status < 0) {
+		DPRINTF("%s: timeout\n", __func__);
+		return -1;
+	}
+
+	if (reg & ISR_BED) {
+		DPRINTF("%s: bus error\n", __func__);
+		return -1;
+	}
+
+	return i2c_reg_read(IDBR);
+}
+
+#define CK505_ADDR		(0x69)
+#define CK505_SPREAD_REG	(0x01)
+#define CK505_SPREAD_CENTRAL	(1 << 6)
+
+static int __init try_fixup_ck505(void)
+{
+	int ret;
+	u8 byte;
+
+	i2c_hw_init();
+
+	ret = i2c_send_start(CK505_ADDR, I2C_WRITE);
+	if (ret) {
+		printk(KERN_ERR "[%d]: failed to send i2c_send_start: %d\n", __LINE__, ret);
+		goto out_unmap;
+	}
+
+	ret = i2c_tx_byte(CK505_SPREAD_REG, 1);
+	if (ret) {
+		printk(KERN_ERR "[%d]: failed to write reg: %d\n", __LINE__, ret);
+		goto out_unmap;
+	}
+
+	ret = i2c_send_start(CK505_ADDR, I2C_READ);
+	if (ret) {
+		printk(KERN_ERR "[%d]: failed to i2c_send_start: %d\n", __LINE__, ret);
+		goto out_unmap;
+	}
+
+	byte = i2c_rx_byte(0);
+	if (byte < 0) {
+		printk(KERN_ERR "[%d]: failed to read: %d\n", __LINE__, byte);
+		goto out_unmap;
+	}
+
+	byte = i2c_rx_byte(1);
+	if (byte < 0) {
+		printk(KERN_ERR "[%d]: failed to read: %d\n", __LINE__, byte);
+		goto out_unmap;
+	}
+
+	if (byte & CK505_SPREAD_CENTRAL) {
+		printk(KERN_INFO PFX "no fixup required: 0x%02x\n", byte);
+		goto out_unmap;
+	}
+
+	printk(KERN_INFO PFX "fixing up: 0x%02x -> 0x%02x\n",
+				byte, byte | CK505_SPREAD_CENTRAL);
+
+	/* Set the PLL1_SSC_SEL to central spread spectrum mode */
+	byte |= CK505_SPREAD_CENTRAL;
+
+	ret = i2c_send_start(CK505_ADDR, I2C_WRITE);
+	if (ret) {
+		printk(KERN_ERR "[%d]: failed to send start: %d\n", __LINE__, ret);
+		goto out_unmap;
+	}
+
+	ret = i2c_tx_byte(CK505_SPREAD_REG, 0);
+	if (ret) {
+		printk(KERN_ERR "[%d]: failed to write byte\n", ret);
+		goto out_unmap;
+	}
+
+	ret = i2c_tx_byte(CK505_SPREAD_REG, 0);
+	if (ret) {
+		printk(KERN_ERR "[%d]: failed to write byte\n", ret);
+		goto out_unmap;
+	}
+
+	ret = i2c_tx_byte(byte, 1);
+	if (ret) {
+		printk(KERN_ERR "[%d]: failed to write byte\n", ret);
+		goto out_unmap;
+	}
+
+	printk(KERN_INFO PFX "successfully fixed-up\n");
+
+out_unmap:
+	early_iounmap(base_addr, I2C_BUS_SIZE);
+
+	return ret;
+}
+
+int __init sdv_i2c_fixup_ck505(void)
+{
+	size_t i;
+
+	for (i = 0; i < 16; i++) {
+		if (!try_fixup_ck505())
+			break;
+	}
+	return 0;
+}
--- /dev/null	2015-07-31 18:17:35.952031993 +0200
+++ linux-4.2-fbx/config	2015-10-08 15:26:26.423830228 +0200
@@ -0,0 +1,3339 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/x86 4.2.0 Kernel Configuration
+#
+# CONFIG_64BIT is not set
+CONFIG_X86_32=y
+CONFIG_X86=y
+CONFIG_INSTRUCTION_DECODER=y
+CONFIG_PERF_EVENTS_INTEL_UNCORE=y
+CONFIG_OUTPUT_FORMAT="elf32-i386"
+CONFIG_ARCH_DEFCONFIG="arch/x86/configs/i386_defconfig"
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_MMU=y
+CONFIG_NEED_SG_DMA_LENGTH=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_HAS_CPU_RELAX=y
+CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
+CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
+CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
+CONFIG_X86_32_SMP=y
+CONFIG_X86_32_LAZY_GS=y
+CONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-ecx -fcall-saved-edx"
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_PGTABLE_LEVELS=3
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE="/opt/toolchains/atom-glibc-2.21-gcc-5.2.0-binutils-2.25-gdb-7.9.1/bin/i686-fbx-linux-gnu-"
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+CONFIG_KERNEL_XZ=y
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+CONFIG_DEFAULT_HOSTNAME="fbx6hd"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+# CONFIG_FHANDLE is not set
+# CONFIG_USELIB is not set
+CONFIG_AUDIT=y
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+CONFIG_AUDITSYSCALL=y
+CONFIG_AUDIT_WATCH=y
+CONFIG_AUDIT_TREE=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_PENDING_IRQ=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_DOMAIN_HIERARCHY=y
+CONFIG_GENERIC_MSI_IRQ=y
+CONFIG_GENERIC_MSI_IRQ_DOMAIN=y
+# CONFIG_IRQ_DOMAIN_DEBUG is not set
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_CLOCKSOURCE_WATCHDOG=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_CLOCKSOURCE_VALIDATE_LAST_CYCLE=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+
+#
+# Timers subsystem
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ_COMMON=y
+# CONFIG_HZ_PERIODIC is not set
+CONFIG_NO_HZ_IDLE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+
+#
+# CPU/Task time and stats accounting
+#
+# CONFIG_TICK_CPU_ACCOUNTING is not set
+CONFIG_IRQ_TIME_ACCOUNTING=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_PREEMPT_RCU=y
+# CONFIG_RCU_EXPERT is not set
+CONFIG_SRCU=y
+# CONFIG_TASKS_RCU is not set
+CONFIG_RCU_STALL_COMMON=y
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_NOCB_CPU is not set
+# CONFIG_RCU_EXPEDITE_BOOT is not set
+# CONFIG_BUILD_BIN2C is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_LOG_CPU_MAX_BUF_SHIFT=12
+CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
+CONFIG_CGROUPS=y
+# CONFIG_CGROUP_DEBUG is not set
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+# CONFIG_CPUSETS is not set
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_PAGE_COUNTER=y
+CONFIG_MEMCG=y
+# CONFIG_MEMCG_KMEM is not set
+# CONFIG_CGROUP_PERF is not set
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_BLK_CGROUP is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+# CONFIG_USER_NS is not set
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_HAVE_UID16=y
+CONFIG_SYSCTL_EXCEPTION_TRACE=y
+CONFIG_HAVE_PCSPKR_PLATFORM=y
+CONFIG_BPF=y
+CONFIG_EXPERT=y
+CONFIG_UID16=y
+CONFIG_MULTIUSER=y
+# CONFIG_SGETMASK_SYSCALL is not set
+# CONFIG_SYSFS_SYSCALL is not set
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+# CONFIG_PCSPKR_PLATFORM is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_BPF_SYSCALL is not set
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_ADVISE_SYSCALLS=y
+CONFIG_PCI_QUIRKS=y
+CONFIG_EMBEDDED=y
+CONFIG_HAVE_PERF_EVENTS=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_PERF_EVENTS=y
+# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_SLUB_CPU_PARTIAL is not set
+# CONFIG_SYSTEM_TRUSTED_KEYRING is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_OPROFILE_NMI_TIMER=y
+# CONFIG_KPROBES is not set
+# CONFIG_JUMP_LABEL is not set
+# CONFIG_UPROBES is not set
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_KPROBES_ON_FTRACE=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_HW_BREAKPOINT=y
+CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y
+CONFIG_HAVE_USER_RETURN_NOTIFIER=y
+CONFIG_HAVE_PERF_EVENTS_NMI=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
+CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y
+CONFIG_HAVE_CMPXCHG_LOCAL=y
+CONFIG_HAVE_CMPXCHG_DOUBLE=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_SECCOMP_FILTER=y
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+# CONFIG_CC_STACKPROTECTOR is not set
+CONFIG_CC_STACKPROTECTOR_NONE=y
+# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
+# CONFIG_CC_STACKPROTECTOR_STRONG is not set
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
+CONFIG_HAVE_ARCH_HUGE_VMAP=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_HAVE_COPY_THREAD_TLS=y
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_OLD_SIGACTION=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_COMPRESS is not set
+CONFIG_MODULES_TREE_LOOKUP=y
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+CONFIG_BLK_DEV_BSG=y
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+# CONFIG_BLK_CMDLINE_PARSER is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_AIX_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+# CONFIG_CMDLINE_PARTITION is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_UNINLINE_SPIN_UNLOCK=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+CONFIG_RWSEM_SPIN_ON_OWNER=y
+CONFIG_LOCK_SPIN_ON_OWNER=y
+CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y
+CONFIG_QUEUED_SPINLOCKS=y
+CONFIG_ARCH_USE_QUEUED_RWLOCKS=y
+CONFIG_QUEUED_RWLOCKS=y
+CONFIG_FREEZER=y
+
+#
+# Processor type and features
+#
+# CONFIG_ZONE_DMA is not set
+CONFIG_SMP=y
+CONFIG_X86_FEATURE_NAMES=y
+CONFIG_X86_MPPARSE=y
+# CONFIG_X86_BIGSMP is not set
+CONFIG_X86_EXTENDED_PLATFORM=y
+# CONFIG_X86_GOLDFISH is not set
+CONFIG_X86_INTEL_CE=y
+CONFIG_FBX6HD=y
+# CONFIG_X86_INTEL_LPSS is not set
+# CONFIG_X86_AMD_PLATFORM_DEVICE is not set
+# CONFIG_IOSF_MBI is not set
+# CONFIG_X86_RDC321X is not set
+# CONFIG_X86_32_NON_STANDARD is not set
+CONFIG_X86_SUPPORTS_MEMORY_FAILURE=y
+# CONFIG_X86_32_IRIS is not set
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+# CONFIG_HYPERVISOR_GUEST is not set
+CONFIG_NO_BOOTMEM=y
+# CONFIG_M486 is not set
+# CONFIG_M586 is not set
+# CONFIG_M586TSC is not set
+# CONFIG_M586MMX is not set
+# CONFIG_M686 is not set
+# CONFIG_MPENTIUMII is not set
+# CONFIG_MPENTIUMIII is not set
+# CONFIG_MPENTIUMM is not set
+# CONFIG_MPENTIUM4 is not set
+# CONFIG_MK6 is not set
+# CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
+# CONFIG_MCRUSOE is not set
+# CONFIG_MEFFICEON is not set
+# CONFIG_MWINCHIPC6 is not set
+# CONFIG_MWINCHIP3D is not set
+# CONFIG_MELAN is not set
+# CONFIG_MGEODEGX1 is not set
+# CONFIG_MGEODE_LX is not set
+# CONFIG_MCYRIXIII is not set
+# CONFIG_MVIAC3_2 is not set
+# CONFIG_MVIAC7 is not set
+# CONFIG_MCORE2 is not set
+CONFIG_MATOM=y
+# CONFIG_X86_GENERIC is not set
+CONFIG_X86_INTERNODE_CACHE_SHIFT=6
+CONFIG_X86_L1_CACHE_SHIFT=6
+CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_X86_TSC=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_CMOV=y
+CONFIG_X86_MINIMUM_CPU_FAMILY=5
+CONFIG_X86_DEBUGCTLMSR=y
+CONFIG_PROCESSOR_SELECT=y
+CONFIG_CPU_SUP_INTEL=y
+# CONFIG_CPU_SUP_CYRIX_32 is not set
+# CONFIG_CPU_SUP_AMD is not set
+# CONFIG_CPU_SUP_CENTAUR is not set
+# CONFIG_CPU_SUP_TRANSMETA_32 is not set
+# CONFIG_CPU_SUP_UMC_32 is not set
+CONFIG_HPET_TIMER=y
+# CONFIG_DMI is not set
+CONFIG_NR_CPUS=2
+CONFIG_SCHED_SMT=y
+# CONFIG_SCHED_MC is not set
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_COUNT=y
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_X86_IO_APIC=y
+# CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS is not set
+CONFIG_X86_MCE=y
+CONFIG_X86_MCE_INTEL=y
+# CONFIG_X86_MCE_AMD is not set
+# CONFIG_X86_ANCIENT_MCE is not set
+CONFIG_X86_MCE_THRESHOLD=y
+# CONFIG_X86_MCE_INJECT is not set
+CONFIG_X86_THERMAL_VECTOR=y
+# CONFIG_VM86 is not set
+CONFIG_X86_16BIT=y
+CONFIG_X86_ESPFIX32=y
+# CONFIG_TOSHIBA is not set
+# CONFIG_I8K is not set
+CONFIG_X86_REBOOTFIXUPS=y
+# CONFIG_MICROCODE is not set
+# CONFIG_X86_MSR is not set
+# CONFIG_X86_CPUID is not set
+CONFIG_NOHIGHMEM=y
+# CONFIG_HIGHMEM4G is not set
+# CONFIG_HIGHMEM64G is not set
+# CONFIG_VMSPLIT_3G is not set
+CONFIG_VMSPLIT_2G=y
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_X86_PAE=y
+CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ILLEGAL_POINTER_VALUE=0
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
+CONFIG_ARCH_DISCARD_MEMBLOCK=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y
+# CONFIG_COMPACTION is not set
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y
+# CONFIG_MEMORY_FAILURE is not set
+# CONFIG_TRANSPARENT_HUGEPAGE is not set
+# CONFIG_CLEANCACHE is not set
+# CONFIG_CMA is not set
+# CONFIG_ZPOOL is not set
+# CONFIG_ZBUD is not set
+# CONFIG_ZSMALLOC is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+CONFIG_ARCH_SUPPORTS_DEFERRED_STRUCT_PAGE_INIT=y
+# CONFIG_X86_PMEM_LEGACY is not set
+# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set
+CONFIG_X86_RESERVE_LOW=4
+# CONFIG_MATH_EMULATION is not set
+CONFIG_MTRR=y
+CONFIG_MTRR_SANITIZER=y
+CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=0
+CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1
+# CONFIG_X86_PAT is not set
+# CONFIG_ARCH_RANDOM is not set
+# CONFIG_X86_SMAP is not set
+# CONFIG_X86_INTEL_MPX is not set
+# CONFIG_EFI is not set
+CONFIG_SECCOMP=y
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_250 is not set
+CONFIG_HZ_300=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=300
+CONFIG_SCHED_HRTICK=y
+# CONFIG_KEXEC is not set
+CONFIG_PHYSICAL_START=0x100000
+# CONFIG_RELOCATABLE is not set
+CONFIG_PHYSICAL_ALIGN=0x100000
+# CONFIG_HOTPLUG_CPU is not set
+# CONFIG_COMPAT_VDSO is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyS0,115200 earlyprintk=ttyS0,115200 root=/dev/nfs ip=dhcp dhcpclass=linux-fbx6hd pci=noacpi mem=656M"
+CONFIG_CMDLINE_OVERRIDE=y
+
+#
+# Power management and ACPI options
+#
+# CONFIG_SUSPEND is not set
+# CONFIG_PM is not set
+CONFIG_ACPI=y
+CONFIG_ACPI_LEGACY_TABLES_LOOKUP=y
+CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC=y
+CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT=y
+# CONFIG_ACPI_PROCFS_POWER is not set
+# CONFIG_ACPI_REV_OVERRIDE_POSSIBLE is not set
+# CONFIG_ACPI_EC_DEBUGFS is not set
+# CONFIG_ACPI_AC is not set
+# CONFIG_ACPI_BATTERY is not set
+# CONFIG_ACPI_BUTTON is not set
+# CONFIG_ACPI_FAN is not set
+# CONFIG_ACPI_DOCK is not set
+# CONFIG_ACPI_PROCESSOR is not set
+# CONFIG_ACPI_CUSTOM_DSDT is not set
+# CONFIG_ACPI_DEBUG is not set
+# CONFIG_ACPI_PCI_SLOT is not set
+CONFIG_X86_PM_TIMER=y
+# CONFIG_ACPI_CONTAINER is not set
+CONFIG_ACPI_HOTPLUG_IOAPIC=y
+# CONFIG_ACPI_SBS is not set
+# CONFIG_ACPI_HED is not set
+# CONFIG_ACPI_CUSTOM_METHOD is not set
+# CONFIG_ACPI_REDUCED_HARDWARE_ONLY is not set
+# CONFIG_ACPI_NFIT is not set
+CONFIG_HAVE_ACPI_APEI=y
+CONFIG_HAVE_ACPI_APEI_NMI=y
+# CONFIG_ACPI_APEI is not set
+# CONFIG_ACPI_EXTLOG is not set
+# CONFIG_PMIC_OPREGION is not set
+# CONFIG_SFI is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# CPU Idle
+#
+CONFIG_CPU_IDLE=y
+# CONFIG_CPU_IDLE_GOV_LADDER is not set
+CONFIG_CPU_IDLE_GOV_MENU=y
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+CONFIG_INTEL_IDLE=y
+
+#
+# Bus options (PCI etc.)
+#
+CONFIG_PCI=y
+# CONFIG_PCI_GOBIOS is not set
+# CONFIG_PCI_GOMMCONFIG is not set
+CONFIG_PCI_GODIRECT=y
+# CONFIG_PCI_GOANY is not set
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_CNB20LE_QUIRK is not set
+# CONFIG_PCIEPORTBUS is not set
+CONFIG_PCI_MSI=y
+CONFIG_PCI_MSI_IRQ_DOMAIN=y
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set
+# CONFIG_PCI_STUB is not set
+CONFIG_HT_IRQ=y
+# CONFIG_PCI_IOV is not set
+# CONFIG_PCI_PRI is not set
+# CONFIG_PCI_PASID is not set
+CONFIG_PCI_LABEL=y
+
+#
+# PCI host controller drivers
+#
+CONFIG_ISA_DMA_API=y
+# CONFIG_ISA is not set
+# CONFIG_SCx200 is not set
+# CONFIG_ALIX is not set
+# CONFIG_NET5501 is not set
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+# CONFIG_RAPIDIO is not set
+# CONFIG_X86_SYSFB is not set
+
+#
+# Executable file formats / Emulations
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_BINFMT_SCRIPT=y
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+CONFIG_HAVE_ATOMIC_IOMAP=y
+CONFIG_PMC_ATOM=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_NETSKBPAD=16
+# CONFIG_NETRXTHREAD is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_ABSTRACT_IGNORE_NETNS is not set
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_ALGO=y
+CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+# CONFIG_NET_IP_TUNNEL is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_NET_IPVTI is not set
+# CONFIG_NET_UDP_TUNNEL is not set
+# CONFIG_NET_FOU is not set
+# CONFIG_GENEVE_CORE is not set
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_GC_THRESH=32768
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+# CONFIG_INET_XFRM_MODE_BEET is not set
+CONFIG_INET_LRO=y
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_BEET is not set
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_SIT is not set
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_GRE is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_INGRESS is not set
+# CONFIG_NETFILTER_NETLINK_ACCT is not set
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_LOG_COMMON=y
+# CONFIG_NF_CONNTRACK_MARK is not set
+CONFIG_NF_CONNTRACK_PROCFS=y
+# CONFIG_NF_CONNTRACK_EVENTS is not set
+# CONFIG_NF_CONNTRACK_TIMEOUT is not set
+# CONFIG_NF_CONNTRACK_TIMESTAMP is not set
+# CONFIG_NF_CT_PROTO_DCCP is not set
+# CONFIG_NF_CT_PROTO_SCTP is not set
+# CONFIG_NF_CT_PROTO_UDPLITE is not set
+# CONFIG_NF_CONNTRACK_AMANDA is not set
+# CONFIG_NF_CONNTRACK_FTP is not set
+# CONFIG_NF_CONNTRACK_H323 is not set
+# CONFIG_NF_CONNTRACK_IRC is not set
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+# CONFIG_NF_CONNTRACK_SNMP is not set
+# CONFIG_NF_CONNTRACK_PPTP is not set
+# CONFIG_NF_CONNTRACK_SANE is not set
+# CONFIG_NF_CONNTRACK_SIP is not set
+# CONFIG_NF_CONNTRACK_TFTP is not set
+# CONFIG_NF_CT_NETLINK is not set
+# CONFIG_NF_CT_NETLINK_TIMEOUT is not set
+# CONFIG_NF_TABLES is not set
+CONFIG_NETFILTER_XTABLES=y
+
+#
+# Xtables combined modules
+#
+# CONFIG_NETFILTER_XT_MARK is not set
+# CONFIG_NETFILTER_XT_CONNMARK is not set
+
+#
+# Xtables targets
+#
+# CONFIG_NETFILTER_XT_TARGET_AUDIT is not set
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set
+# CONFIG_NETFILTER_XT_TARGET_HMARK is not set
+# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set
+# CONFIG_NETFILTER_XT_TARGET_LED is not set
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+# CONFIG_NETFILTER_XT_TARGET_TEE is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+
+#
+# Xtables matches
+#
+# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_BPF is not set
+# CONFIG_NETFILTER_XT_MATCH_CGROUP is not set
+# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNLABEL is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNMARK is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNTRACK is not set
+# CONFIG_NETFILTER_XT_MATCH_CPU is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ECN is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_HELPER is not set
+# CONFIG_NETFILTER_XT_MATCH_HL is not set
+# CONFIG_NETFILTER_XT_MATCH_IPCOMP is not set
+# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
+# CONFIG_NETFILTER_XT_MATCH_L2TP is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set
+CONFIG_NETFILTER_XT_MATCH_OWNER=y
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_SOCKET is not set
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_IP_SET is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_FFN is not set
+CONFIG_NF_DEFRAG_IPV4=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+# CONFIG_NF_LOG_ARP is not set
+CONFIG_NF_LOG_IPV4=y
+CONFIG_NF_REJECT_IPV4=y
+# CONFIG_NF_NAT_IPV4 is not set
+CONFIG_IP_NF_IPTABLES=y
+# CONFIG_IP_NF_MATCH_AH is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+# CONFIG_IP_NF_TARGET_SYNPROXY is not set
+# CONFIG_IP_NF_NAT is not set
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_RAW is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV6=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_NF_REJECT_IPV6=y
+CONFIG_NF_LOG_IPV6=y
+# CONFIG_NF_NAT_IPV6 is not set
+CONFIG_IP6_NF_IPTABLES=y
+# CONFIG_IP6_NF_MATCH_AH is not set
+# CONFIG_IP6_NF_MATCH_EUI64 is not set
+# CONFIG_IP6_NF_MATCH_FRAG is not set
+# CONFIG_IP6_NF_MATCH_OPTS is not set
+# CONFIG_IP6_NF_MATCH_HL is not set
+# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set
+# CONFIG_IP6_NF_MATCH_MH is not set
+# CONFIG_IP6_NF_MATCH_RT is not set
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+# CONFIG_IP6_NF_TARGET_SYNPROXY is not set
+# CONFIG_IP6_NF_MANGLE is not set
+# CONFIG_IP6_NF_RAW is not set
+# CONFIG_IP6_NF_NAT is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_FBXATM is not set
+# CONFIG_FBXBRIDGE is not set
+# CONFIG_BRIDGE is not set
+CONFIG_HAVE_NET_DSA=y
+CONFIG_VLAN_8021Q=y
+# CONFIG_VLAN_8021Q_GVRP is not set
+# CONFIG_VLAN_8021Q_MVRP is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_6LOWPAN is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_MMAP is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_MPLS is not set
+# CONFIG_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+CONFIG_RPS=y
+CONFIG_RFS_ACCEL=y
+CONFIG_XPS=y
+# CONFIG_CGROUP_NET_PRIO is not set
+# CONFIG_CGROUP_NET_CLASSID is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+CONFIG_NET_FLOW_LIMIT=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+CONFIG_BT=y
+CONFIG_BT_BREDR=y
+# CONFIG_BT_RFCOMM is not set
+# CONFIG_BT_BNEP is not set
+# CONFIG_BT_HIDP is not set
+# CONFIG_BT_LE is not set
+# CONFIG_BT_SELFTEST is not set
+# CONFIG_BT_DEBUGFS is not set
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_INTEL=y
+CONFIG_BT_HCIBTUSB=y
+# CONFIG_BT_HCIBTUSB_BCM is not set
+# CONFIG_BT_HCIBTUSB_RTL is not set
+# CONFIG_BT_HCIUART is not set
+CONFIG_BT_HCIBCM203X=y
+CONFIG_BT_HCIBPA10X=y
+CONFIG_BT_HCIBFUSB=y
+# CONFIG_BT_HCIVHCI is not set
+CONFIG_BT_MRVL=y
+CONFIG_BT_ATH3K=y
+# CONFIG_AF_RXRPC is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_UEVENT_HELPER is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+# CONFIG_ALLOW_DEV_COREDUMP is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+CONFIG_GENERIC_CPU_AUTOPROBE=y
+CONFIG_REGMAP=y
+CONFIG_REGMAP_I2C=m
+# CONFIG_DMA_SHARED_BUFFER is not set
+
+#
+# Bus devices
+#
+# CONFIG_CONNECTOR is not set
+CONFIG_FREEBOX_PROCFS=y
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+CONFIG_MTD_ERASE_PRINTK=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+CONFIG_MTD_FBX6HD_PARTS=y
+# CONFIG_MTD_FBX6HD_PARTS_WRITE_ALL is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+# CONFIG_MTD_PARTITIONED_MASTER is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+CONFIG_MTD_NAND_ECC=y
+# CONFIG_MTD_NAND_ECC_SMC is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_ECC_BCH is not set
+# CONFIG_MTD_SM_COMMON is not set
+CONFIG_MTD_FORCE_BAD_BLOCK_ERASE=y
+# CONFIG_MTD_NAND_DENALI is not set
+# CONFIG_MTD_NAND_GPIO is not set
+# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_RICOH is not set
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_DOCG4 is not set
+# CONFIG_MTD_NAND_CAFE is not set
+# CONFIG_MTD_NAND_CS553X is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_NAND_HISI504 is not set
+CONFIG_MTD_NAND_DENALI_FBX=y
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR & LPDDR2 PCM memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_SPI_NOR is not set
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_LIMIT=20
+# CONFIG_MTD_UBI_FASTMAP is not set
+# CONFIG_MTD_UBI_GLUEBI is not set
+# CONFIG_MTD_UBI_BLOCK is not set
+# CONFIG_FREEBOX_MTD is not set
+CONFIG_DTC=y
+CONFIG_OF=y
+# CONFIG_OF_UNITTEST is not set
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_ADDRESS_PCI=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_NET=y
+CONFIG_OF_PCI=y
+CONFIG_OF_PCI_IRQ=y
+CONFIG_OF_MTD=y
+# CONFIG_OF_OVERLAY is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+# CONFIG_PARPORT is not set
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG_MESSAGES is not set
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_NULL_BLK is not set
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_DRBD is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_NVME is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_RBD is not set
+# CONFIG_BLK_DEV_RSXX is not set
+
+#
+# Misc devices
+#
+# CONFIG_WINTEGRA_MMAP is not set
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_IBM_ASM is not set
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1780 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+CONFIG_INTELCE_PIC16PMU=y
+# CONFIG_BMP085_I2C is not set
+# CONFIG_PCH_PHUB is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_SRAM is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+# CONFIG_VMWARE_VMCI is not set
+
+#
+# Intel MIC Bus Driver
+#
+
+#
+# SCIF Bus Driver
+#
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+
+#
+# SCIF Driver
+#
+# CONFIG_ECHO is not set
+# CONFIG_CXL_BASE is not set
+# CONFIG_CXL_KERNEL_API is not set
+
+#
+# RemoTI support
+#
+CONFIG_REMOTI=y
+CONFIG_REMOTI_LEDS=y
+# CONFIG_REMOTI_GPIO is not set
+CONFIG_REMOTI_USER=y
+
+#
+# HDMI CEC support
+#
+CONFIG_HDMI_CEC=y
+CONFIG_HDMI_CEC_REMOTI=y
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_SCSI_MQ_DEFAULT is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+CONFIG_SCSI_SCAN_ASYNC=y
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_ATA_VERBOSE_ERROR=y
+CONFIG_ATA_ACPI=y
+CONFIG_SATA_PMP=y
+
+#
+# Controllers with non-SFF native interface
+#
+CONFIG_SATA_AHCI=m
+# CONFIG_SATA_AHCI_PLATFORM is not set
+# CONFIG_AHCI_CEVA is not set
+# CONFIG_SATA_INIC162X is not set
+# CONFIG_SATA_ACARD_AHCI is not set
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_ATA_SFF is not set
+# CONFIG_MD is not set
+# CONFIG_TARGET_CORE is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_FIREWIRE_NOSY is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_FC is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_IPVLAN is not set
+# CONFIG_VXLAN is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_TUN is not set
+# CONFIG_TUN_VNET_CROSS_LE is not set
+# CONFIG_VETH is not set
+# CONFIG_NLMON is not set
+# CONFIG_ARCNET is not set
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+# CONFIG_NET_DSA_MV88E6XXX is not set
+# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set
+CONFIG_ETHERNET=y
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_ADAPTEC is not set
+# CONFIG_NET_VENDOR_AGERE is not set
+# CONFIG_NET_VENDOR_ALTEON is not set
+# CONFIG_ALTERA_TSE is not set
+# CONFIG_NET_VENDOR_AMD is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_ATHEROS is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_BROCADE is not set
+# CONFIG_NET_VENDOR_CAVIUM is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_CISCO is not set
+# CONFIG_CX_ECAT is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_VENDOR_DEC is not set
+# CONFIG_NET_VENDOR_DLINK is not set
+# CONFIG_NET_VENDOR_EMULEX is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_EXAR is not set
+# CONFIG_NET_VENDOR_HP is not set
+CONFIG_NET_VENDOR_INTEL=y
+# CONFIG_E100 is not set
+CONFIG_E1000=y
+# CONFIG_E1000E is not set
+# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
+# CONFIG_IXGB is not set
+# CONFIG_IXGBE is not set
+# CONFIG_IXGBEVF is not set
+# CONFIG_I40E is not set
+# CONFIG_I40EVF is not set
+# CONFIG_FM10K is not set
+# CONFIG_NET_VENDOR_I825XX is not set
+# CONFIG_IP1000 is not set
+# CONFIG_JME is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MELLANOX is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MYRI is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NVIDIA is not set
+# CONFIG_NET_VENDOR_OKI is not set
+# CONFIG_ETHOC is not set
+# CONFIG_NET_PACKET_ENGINE is not set
+# CONFIG_NET_VENDOR_QLOGIC is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_REALTEK is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_RDC is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SILAN is not set
+# CONFIG_NET_VENDOR_SIS is not set
+# CONFIG_SFC is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SUN is not set
+# CONFIG_NET_VENDOR_TEHUTI is not set
+# CONFIG_NET_VENDOR_TI is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_NET_SB1000 is not set
+# CONFIG_PHYLIB is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_USB_NET_DRIVERS is not set
+# CONFIG_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_VMXNET3 is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_LEDS is not set
+CONFIG_INPUT_FF_MEMLESS=y
+CONFIG_INPUT_POLLDEV=y
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_JOYSTICK=y
+# CONFIG_JOYSTICK_ANALOG is not set
+# CONFIG_JOYSTICK_A3D is not set
+# CONFIG_JOYSTICK_ADI is not set
+# CONFIG_JOYSTICK_COBRA is not set
+# CONFIG_JOYSTICK_GF2K is not set
+# CONFIG_JOYSTICK_GRIP is not set
+# CONFIG_JOYSTICK_GRIP_MP is not set
+# CONFIG_JOYSTICK_GUILLEMOT is not set
+# CONFIG_JOYSTICK_INTERACT is not set
+# CONFIG_JOYSTICK_SIDEWINDER is not set
+# CONFIG_JOYSTICK_TMDC is not set
+# CONFIG_JOYSTICK_IFORCE is not set
+# CONFIG_JOYSTICK_WARRIOR is not set
+# CONFIG_JOYSTICK_MAGELLAN is not set
+# CONFIG_JOYSTICK_SPACEORB is not set
+# CONFIG_JOYSTICK_SPACEBALL is not set
+# CONFIG_JOYSTICK_STINGER is not set
+# CONFIG_JOYSTICK_TWIDJOY is not set
+# CONFIG_JOYSTICK_ZHENHUA is not set
+# CONFIG_JOYSTICK_AS5011 is not set
+# CONFIG_JOYSTICK_JOYDUMP is not set
+# CONFIG_JOYSTICK_XPAD is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_AD714X is not set
+# CONFIG_INPUT_BMA150 is not set
+# CONFIG_INPUT_E3X0_BUTTON is not set
+# CONFIG_INPUT_MMA8450 is not set
+# CONFIG_INPUT_MPU3050 is not set
+# CONFIG_INPUT_APANEL is not set
+# CONFIG_INPUT_GP2A is not set
+# CONFIG_INPUT_GPIO_BEEPER is not set
+# CONFIG_INPUT_GPIO_TILT_POLLED is not set
+# CONFIG_INPUT_WISTRON_BTNS is not set
+# CONFIG_INPUT_ATLAS_BTNS is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_KXTJ9 is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_UINPUT=y
+# CONFIG_INPUT_PCF8574 is not set
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+# CONFIG_INPUT_ADXL34X is not set
+# CONFIG_INPUT_IMS_PCU is not set
+# CONFIG_INPUT_CMA3000 is not set
+# CONFIG_INPUT_DRV260X_HAPTICS is not set
+# CONFIG_INPUT_DRV2665_HAPTICS is not set
+# CONFIG_INPUT_DRV2667_HAPTICS is not set
+# CONFIG_INPUT_SMSC_CAP1066 is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=16
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVMEM=y
+# CONFIG_DEVKMEM is not set
+CONFIG_DEVPHYSMEM=y
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_EARLYCON=y
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_PNP=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+CONFIG_SERIAL_8250_RSA=y
+# CONFIG_SERIAL_8250_DW is not set
+# CONFIG_SERIAL_8250_FINTEK is not set
+# CONFIG_SERIAL_8250_INGENIC is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_SC16IS7XX is not set
+# CONFIG_SERIAL_TIMBERDALE is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_PCH_UART is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_RP2 is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=m
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_HW_RANDOM_INTEL is not set
+# CONFIG_HW_RANDOM_AMD is not set
+# CONFIG_HW_RANDOM_GEODE is not set
+# CONFIG_HW_RANDOM_VIA is not set
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_SONYPI is not set
+# CONFIG_MWAVE is not set
+# CONFIG_PC8736x_GPIO is not set
+# CONFIG_NSC_GPIO is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HPET is not set
+# CONFIG_HANGCHECK_TIMER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+CONFIG_DEVPORT=y
+# CONFIG_XILLYBUS is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+# CONFIG_ACPI_I2C_OPREGION is not set
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_MUX is not set
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_ISCH is not set
+# CONFIG_I2C_ISMT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+
+#
+# ACPI drivers
+#
+# CONFIG_I2C_SCMI is not set
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_CBUS_GPIO is not set
+# CONFIG_I2C_DESIGNWARE_PCI is not set
+# CONFIG_I2C_EG20T is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+CONFIG_I2C_PXA=y
+CONFIG_I2C_PXA_PCI=y
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_ROBOTFUZZ_OSIF is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_SLAVE is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_SPI is not set
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+# CONFIG_PTP_1588_CLOCK_PCH is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_DEVRES=y
+CONFIG_OF_GPIO=y
+CONFIG_GPIO_ACPI=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO drivers
+#
+# CONFIG_GPIO_74XX_MMIO is not set
+# CONFIG_GPIO_ALTERA is not set
+# CONFIG_GPIO_DWAPB is not set
+# CONFIG_GPIO_F7188X is not set
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_GRGPIO is not set
+# CONFIG_GPIO_ICH is not set
+# CONFIG_GPIO_IT8761E is not set
+# CONFIG_GPIO_LYNXPOINT is not set
+# CONFIG_GPIO_SCH is not set
+# CONFIG_GPIO_SCH311X is not set
+# CONFIG_GPIO_VX855 is not set
+# CONFIG_GPIO_XILINX is not set
+
+#
+# I2C GPIO expanders
+#
+# CONFIG_GPIO_ADP5588 is not set
+# CONFIG_GPIO_ADNP is not set
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+
+#
+# MFD GPIO expanders
+#
+
+#
+# PCI GPIO expanders
+#
+# CONFIG_GPIO_AMD8111 is not set
+# CONFIG_GPIO_BT8XX is not set
+# CONFIG_GPIO_INTEL_MID is not set
+# CONFIG_GPIO_ML_IOH is not set
+# CONFIG_GPIO_PCH is not set
+# CONFIG_GPIO_RDC321X is not set
+# CONFIG_GPIO_SODAVILLE is not set
+
+#
+# USB GPIO expanders
+#
+# CONFIG_FREEBOX_GPIO is not set
+# CONFIG_FREEBOX_JTAG is not set
+# CONFIG_W1 is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_TEST_POWER is not set
+# CONFIG_BATTERY_DS2780 is not set
+# CONFIG_BATTERY_DS2781 is not set
+# CONFIG_BATTERY_DS2782 is not set
+# CONFIG_BATTERY_SBS is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+# CONFIG_BATTERY_MAX17040 is not set
+# CONFIG_BATTERY_MAX17042 is not set
+# CONFIG_CHARGER_MAX8903 is not set
+# CONFIG_CHARGER_LP8727 is not set
+# CONFIG_CHARGER_GPIO is not set
+# CONFIG_CHARGER_BQ2415X is not set
+# CONFIG_CHARGER_BQ24190 is not set
+# CONFIG_CHARGER_BQ24257 is not set
+# CONFIG_CHARGER_BQ24735 is not set
+# CONFIG_CHARGER_BQ25890 is not set
+# CONFIG_CHARGER_SMB347 is not set
+# CONFIG_BATTERY_GAUGE_LTC2941 is not set
+# CONFIG_CHARGER_RT9455 is not set
+# CONFIG_POWER_RESET is not set
+# CONFIG_POWER_AVS is not set
+CONFIG_HWMON=y
+CONFIG_HWMON_VID=y
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7410 is not set
+# CONFIG_SENSORS_ADT7411 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+CONFIG_SENSORS_ADT7475=y
+# CONFIG_SENSORS_ASC7621 is not set
+# CONFIG_SENSORS_K8TEMP is not set
+# CONFIG_SENSORS_K10TEMP is not set
+# CONFIG_SENSORS_FAM15H_POWER is not set
+# CONFIG_SENSORS_APPLESMC is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS620 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_DELL_SMM is not set
+# CONFIG_SENSORS_I5K_AMB is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_FSCHMD is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_G760A is not set
+# CONFIG_SENSORS_G762 is not set
+# CONFIG_SENSORS_GPIO_FAN is not set
+# CONFIG_SENSORS_HIH6130 is not set
+# CONFIG_SENSORS_I5500 is not set
+CONFIG_SENSORS_CORETEMP=y
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_JC42 is not set
+# CONFIG_SENSORS_POWR1220 is not set
+# CONFIG_SENSORS_LINEAGE is not set
+# CONFIG_SENSORS_LTC2945 is not set
+# CONFIG_SENSORS_LTC4151 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4222 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LTC4260 is not set
+# CONFIG_SENSORS_LTC4261 is not set
+# CONFIG_SENSORS_MAX16065 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX1668 is not set
+# CONFIG_SENSORS_MAX197 is not set
+# CONFIG_SENSORS_MAX6639 is not set
+# CONFIG_SENSORS_MAX6642 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_MAX6697 is not set
+# CONFIG_SENSORS_HTU21 is not set
+# CONFIG_SENSORS_MCP3021 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM73 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+CONFIG_SENSORS_LM85=y
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LM95234 is not set
+# CONFIG_SENSORS_LM95241 is not set
+# CONFIG_SENSORS_LM95245 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_NTC_THERMISTOR is not set
+# CONFIG_SENSORS_NCT6683 is not set
+# CONFIG_SENSORS_NCT6775 is not set
+# CONFIG_SENSORS_NCT7802 is not set
+# CONFIG_SENSORS_NCT7904 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_PMBUS is not set
+# CONFIG_SENSORS_SHT15 is not set
+# CONFIG_SENSORS_SHT21 is not set
+# CONFIG_SENSORS_SHTC1 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_EMC1403 is not set
+# CONFIG_SENSORS_EMC2103 is not set
+# CONFIG_SENSORS_EMC6W201 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SCH56XX_COMMON is not set
+# CONFIG_SENSORS_SMM665 is not set
+# CONFIG_SENSORS_ADC128D818 is not set
+# CONFIG_SENSORS_ADS1015 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_AMC6821 is not set
+# CONFIG_SENSORS_INA209 is not set
+# CONFIG_SENSORS_INA2XX is not set
+# CONFIG_SENSORS_TC74 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP102 is not set
+# CONFIG_SENSORS_TMP103 is not set
+# CONFIG_SENSORS_TMP401 is not set
+# CONFIG_SENSORS_TMP421 is not set
+# CONFIG_SENSORS_VIA_CPUTEMP is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83795 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+
+#
+# ACPI drivers
+#
+# CONFIG_SENSORS_ACPI_POWER is not set
+# CONFIG_SENSORS_ATK0110 is not set
+CONFIG_THERMAL=y
+CONFIG_THERMAL_HWMON=y
+CONFIG_THERMAL_OF=y
+# CONFIG_THERMAL_WRITABLE_TRIPS is not set
+CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
+# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
+# CONFIG_THERMAL_GOV_FAIR_SHARE is not set
+CONFIG_THERMAL_GOV_STEP_WISE=y
+# CONFIG_THERMAL_GOV_BANG_BANG is not set
+CONFIG_THERMAL_GOV_USER_SPACE=y
+# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+# CONFIG_THERMAL_EMULATION is not set
+# CONFIG_INTEL_POWERCLAMP is not set
+CONFIG_X86_PKG_TEMP_THERMAL=y
+# CONFIG_INTEL_SOC_DTS_THERMAL is not set
+# CONFIG_INT340X_THERMAL is not set
+
+#
+# Texas Instruments thermal drivers
+#
+# CONFIG_FREEBOX_WATCHDOG is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_CS5535 is not set
+# CONFIG_MFD_AS3711 is not set
+# CONFIG_MFD_AS3722 is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_ATMEL_HLCDC is not set
+# CONFIG_MFD_BCM590XX is not set
+# CONFIG_MFD_AXP20X is not set
+# CONFIG_MFD_CROS_EC is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_MFD_DA9063 is not set
+# CONFIG_MFD_DA9150 is not set
+# CONFIG_MFD_DLN2 is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_MFD_HI6421_PMIC is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_LPC_ICH is not set
+# CONFIG_LPC_SCH is not set
+# CONFIG_INTEL_SOC_PMIC is not set
+# CONFIG_MFD_JANZ_CMODIO is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_88PM800 is not set
+# CONFIG_MFD_88PM805 is not set
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_MAX14577 is not set
+# CONFIG_MFD_MAX77686 is not set
+# CONFIG_MFD_MAX77693 is not set
+# CONFIG_MFD_MAX77843 is not set
+# CONFIG_MFD_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_MT6397 is not set
+# CONFIG_MFD_MENF21BMC is not set
+# CONFIG_MFD_VIPERBOARD is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_RDC321X is not set
+# CONFIG_MFD_RTSX_PCI is not set
+# CONFIG_MFD_RT5033 is not set
+# CONFIG_MFD_RTSX_USB is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_RK808 is not set
+# CONFIG_MFD_RN5T618 is not set
+# CONFIG_MFD_SEC_CORE is not set
+# CONFIG_MFD_SI476X_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_SKY81452 is not set
+# CONFIG_MFD_SMSC is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_STMPE is not set
+# CONFIG_MFD_SYSCON is not set
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_LP3943 is not set
+# CONFIG_MFD_LP8788 is not set
+# CONFIG_MFD_PALMAS is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TPS65218 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS80031 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_MFD_TIMBERDALE is not set
+# CONFIG_MFD_TC3589X is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_VX855 is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_REGULATOR is not set
+CONFIG_MEDIA_SUPPORT=y
+
+#
+# Multimedia core support
+#
+# CONFIG_MEDIA_CAMERA_SUPPORT is not set
+# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set
+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
+# CONFIG_MEDIA_RADIO_SUPPORT is not set
+# CONFIG_MEDIA_SDR_SUPPORT is not set
+CONFIG_MEDIA_RC_SUPPORT=y
+# CONFIG_MEDIA_CONTROLLER is not set
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_DVB_CORE=y
+# CONFIG_DVB_NET is not set
+# CONFIG_TTPCI_EEPROM is not set
+CONFIG_DVB_MAX_ADAPTERS=8
+# CONFIG_DVB_DYNAMIC_MINORS is not set
+
+#
+# Media drivers
+#
+CONFIG_RC_CORE=y
+CONFIG_RC_MAP=y
+CONFIG_RC_DECODERS=y
+# CONFIG_LIRC is not set
+# CONFIG_IR_NEC_DECODER is not set
+# CONFIG_IR_RC5_DECODER is not set
+CONFIG_IR_RC6_DECODER=y
+# CONFIG_IR_JVC_DECODER is not set
+# CONFIG_IR_SONY_DECODER is not set
+# CONFIG_IR_SANYO_DECODER is not set
+# CONFIG_IR_SHARP_DECODER is not set
+CONFIG_IR_MCE_KBD_DECODER=y
+# CONFIG_IR_XMP_DECODER is not set
+CONFIG_RC_DEVICES=y
+# CONFIG_RC_ATI_REMOTE is not set
+# CONFIG_IR_ENE is not set
+# CONFIG_IR_HIX5HD2 is not set
+# CONFIG_IR_IMON is not set
+CONFIG_IR_MCEUSB=y
+# CONFIG_IR_ITE_CIR is not set
+# CONFIG_IR_FINTEK is not set
+# CONFIG_IR_NUVOTON is not set
+# CONFIG_IR_REDRAT3 is not set
+# CONFIG_IR_STREAMZAP is not set
+# CONFIG_IR_WINBOND_CIR is not set
+# CONFIG_IR_IGORPLUGUSB is not set
+# CONFIG_IR_IGUANA is not set
+# CONFIG_IR_TTUSBIR is not set
+# CONFIG_RC_LOOPBACK is not set
+# CONFIG_IR_GPIO_CIR is not set
+CONFIG_MEDIA_USB_SUPPORT=y
+
+#
+# Analog/digital TV USB devices
+#
+# CONFIG_VIDEO_AU0828 is not set
+
+#
+# Digital TV USB devices
+#
+CONFIG_DVB_USB=y
+# CONFIG_DVB_USB_DEBUG is not set
+# CONFIG_DVB_USB_A800 is not set
+# CONFIG_DVB_USB_DIBUSB_MB is not set
+# CONFIG_DVB_USB_DIBUSB_MC is not set
+CONFIG_DVB_USB_DIB0700=m
+# CONFIG_DVB_USB_UMT_010 is not set
+# CONFIG_DVB_USB_CXUSB is not set
+# CONFIG_DVB_USB_M920X is not set
+# CONFIG_DVB_USB_DIGITV is not set
+# CONFIG_DVB_USB_VP7045 is not set
+# CONFIG_DVB_USB_VP702X is not set
+# CONFIG_DVB_USB_GP8PSK is not set
+# CONFIG_DVB_USB_NOVA_T_USB2 is not set
+# CONFIG_DVB_USB_TTUSB2 is not set
+# CONFIG_DVB_USB_DTT200U is not set
+# CONFIG_DVB_USB_OPERA1 is not set
+# CONFIG_DVB_USB_AF9005 is not set
+# CONFIG_DVB_USB_PCTV452E is not set
+# CONFIG_DVB_USB_DW2102 is not set
+# CONFIG_DVB_USB_CINERGY_T2 is not set
+# CONFIG_DVB_USB_DTV5100 is not set
+# CONFIG_DVB_USB_FRIIO is not set
+# CONFIG_DVB_USB_AZ6027 is not set
+# CONFIG_DVB_USB_TECHNISAT_USB2 is not set
+CONFIG_DVB_USB_V2=y
+# CONFIG_DVB_USB_AF9015 is not set
+CONFIG_DVB_USB_AF9035=m
+# CONFIG_DVB_USB_ANYSEE is not set
+# CONFIG_DVB_USB_AU6610 is not set
+# CONFIG_DVB_USB_AZ6007 is not set
+# CONFIG_DVB_USB_CE6230 is not set
+# CONFIG_DVB_USB_EC168 is not set
+# CONFIG_DVB_USB_GL861 is not set
+# CONFIG_DVB_USB_LME2510 is not set
+# CONFIG_DVB_USB_MXL111SF is not set
+# CONFIG_DVB_USB_DVBSKY is not set
+# CONFIG_DVB_TTUSB_BUDGET is not set
+# CONFIG_DVB_TTUSB_DEC is not set
+# CONFIG_SMS_USB_DRV is not set
+# CONFIG_DVB_B2C2_FLEXCOP_USB is not set
+# CONFIG_DVB_AS102 is not set
+
+#
+# Webcam, TV (analog/digital) USB devices
+#
+# CONFIG_MEDIA_PCI_SUPPORT is not set
+
+#
+# Supported MMC/SDIO adapters
+#
+# CONFIG_CYPRESS_FIRMWARE is not set
+
+#
+# Media ancillary drivers (tuners, sensors, i2c, frontends)
+#
+# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
+CONFIG_MEDIA_ATTACH=y
+CONFIG_MEDIA_TUNER=y
+
+#
+# Customize TV tuners
+#
+# CONFIG_MEDIA_TUNER_SIMPLE is not set
+# CONFIG_MEDIA_TUNER_TDA8290 is not set
+# CONFIG_MEDIA_TUNER_TDA827X is not set
+# CONFIG_MEDIA_TUNER_TDA18271 is not set
+# CONFIG_MEDIA_TUNER_TDA9887 is not set
+# CONFIG_MEDIA_TUNER_TEA5761 is not set
+# CONFIG_MEDIA_TUNER_TEA5767 is not set
+# CONFIG_MEDIA_TUNER_MT20XX is not set
+# CONFIG_MEDIA_TUNER_MT2060 is not set
+# CONFIG_MEDIA_TUNER_MT2063 is not set
+# CONFIG_MEDIA_TUNER_MT2266 is not set
+# CONFIG_MEDIA_TUNER_MT2131 is not set
+# CONFIG_MEDIA_TUNER_QT1010 is not set
+# CONFIG_MEDIA_TUNER_XC2028 is not set
+# CONFIG_MEDIA_TUNER_XC5000 is not set
+# CONFIG_MEDIA_TUNER_XC4000 is not set
+# CONFIG_MEDIA_TUNER_MXL5005S is not set
+# CONFIG_MEDIA_TUNER_MXL5007T is not set
+# CONFIG_MEDIA_TUNER_MC44S803 is not set
+# CONFIG_MEDIA_TUNER_MAX2165 is not set
+# CONFIG_MEDIA_TUNER_TDA18218 is not set
+# CONFIG_MEDIA_TUNER_FC0011 is not set
+# CONFIG_MEDIA_TUNER_FC0012 is not set
+# CONFIG_MEDIA_TUNER_FC0013 is not set
+# CONFIG_MEDIA_TUNER_TDA18212 is not set
+# CONFIG_MEDIA_TUNER_E4000 is not set
+# CONFIG_MEDIA_TUNER_FC2580 is not set
+# CONFIG_MEDIA_TUNER_M88RS6000T is not set
+# CONFIG_MEDIA_TUNER_TUA9001 is not set
+# CONFIG_MEDIA_TUNER_SI2157 is not set
+CONFIG_MEDIA_TUNER_IT913X=m
+# CONFIG_MEDIA_TUNER_R820T is not set
+# CONFIG_MEDIA_TUNER_MXL301RF is not set
+# CONFIG_MEDIA_TUNER_QM1D1C0042 is not set
+
+#
+# Customise DVB Frontends
+#
+
+#
+# Multistandard (satellite) frontends
+#
+# CONFIG_DVB_STB0899 is not set
+# CONFIG_DVB_STB6100 is not set
+# CONFIG_DVB_STV090x is not set
+# CONFIG_DVB_STV6110x is not set
+
+#
+# Multistandard (cable + terrestrial) frontends
+#
+# CONFIG_DVB_DRXK is not set
+# CONFIG_DVB_TDA18271C2DD is not set
+# CONFIG_DVB_SI2165 is not set
+
+#
+# DVB-S (satellite) frontends
+#
+# CONFIG_DVB_CX24110 is not set
+# CONFIG_DVB_CX24123 is not set
+# CONFIG_DVB_MT312 is not set
+# CONFIG_DVB_ZL10036 is not set
+# CONFIG_DVB_ZL10039 is not set
+# CONFIG_DVB_S5H1420 is not set
+# CONFIG_DVB_STV0288 is not set
+# CONFIG_DVB_STB6000 is not set
+# CONFIG_DVB_STV0299 is not set
+# CONFIG_DVB_STV6110 is not set
+# CONFIG_DVB_STV0900 is not set
+# CONFIG_DVB_TDA8083 is not set
+# CONFIG_DVB_TDA10086 is not set
+# CONFIG_DVB_TDA8261 is not set
+# CONFIG_DVB_VES1X93 is not set
+# CONFIG_DVB_TUNER_ITD1000 is not set
+# CONFIG_DVB_TUNER_CX24113 is not set
+# CONFIG_DVB_TDA826X is not set
+# CONFIG_DVB_TUA6100 is not set
+# CONFIG_DVB_CX24116 is not set
+# CONFIG_DVB_CX24117 is not set
+# CONFIG_DVB_CX24120 is not set
+# CONFIG_DVB_SI21XX is not set
+# CONFIG_DVB_TS2020 is not set
+# CONFIG_DVB_DS3000 is not set
+# CONFIG_DVB_MB86A16 is not set
+# CONFIG_DVB_TDA10071 is not set
+
+#
+# DVB-T (terrestrial) frontends
+#
+# CONFIG_DVB_SP8870 is not set
+# CONFIG_DVB_SP887X is not set
+# CONFIG_DVB_CX22700 is not set
+# CONFIG_DVB_CX22702 is not set
+# CONFIG_DVB_S5H1432 is not set
+# CONFIG_DVB_DRXD is not set
+# CONFIG_DVB_L64781 is not set
+# CONFIG_DVB_TDA1004X is not set
+# CONFIG_DVB_NXT6000 is not set
+# CONFIG_DVB_MT352 is not set
+# CONFIG_DVB_ZL10353 is not set
+# CONFIG_DVB_DIB3000MB is not set
+# CONFIG_DVB_DIB3000MC is not set
+CONFIG_DVB_DIB7000M=y
+CONFIG_DVB_DIB7000P=y
+# CONFIG_DVB_DIB9000 is not set
+# CONFIG_DVB_TDA10048 is not set
+# CONFIG_DVB_AF9013 is not set
+# CONFIG_DVB_EC100 is not set
+# CONFIG_DVB_HD29L2 is not set
+# CONFIG_DVB_STV0367 is not set
+# CONFIG_DVB_CXD2820R is not set
+# CONFIG_DVB_AS102_FE is not set
+
+#
+# DVB-C (cable) frontends
+#
+# CONFIG_DVB_VES1820 is not set
+# CONFIG_DVB_TDA10021 is not set
+# CONFIG_DVB_TDA10023 is not set
+# CONFIG_DVB_STV0297 is not set
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+# CONFIG_DVB_NXT200X is not set
+# CONFIG_DVB_OR51211 is not set
+# CONFIG_DVB_OR51132 is not set
+# CONFIG_DVB_BCM3510 is not set
+# CONFIG_DVB_LGDT330X is not set
+# CONFIG_DVB_LGDT3305 is not set
+# CONFIG_DVB_LGDT3306A is not set
+# CONFIG_DVB_LG2160 is not set
+# CONFIG_DVB_S5H1409 is not set
+# CONFIG_DVB_AU8522_DTV is not set
+# CONFIG_DVB_S5H1411 is not set
+
+#
+# ISDB-T (terrestrial) frontends
+#
+# CONFIG_DVB_S921 is not set
+# CONFIG_DVB_DIB8000 is not set
+# CONFIG_DVB_MB86A20S is not set
+
+#
+# ISDB-S (satellite) & ISDB-T (terrestrial) frontends
+#
+# CONFIG_DVB_TC90522 is not set
+
+#
+# Digital terrestrial only tuners/PLL
+#
+# CONFIG_DVB_PLL is not set
+CONFIG_DVB_TUNER_DIB0070=y
+# CONFIG_DVB_TUNER_DIB0090 is not set
+
+#
+# SEC control devices for DVB-S
+#
+# CONFIG_DVB_DRX39XYJ is not set
+# CONFIG_DVB_LNBP21 is not set
+# CONFIG_DVB_LNBP22 is not set
+# CONFIG_DVB_ISL6405 is not set
+# CONFIG_DVB_ISL6421 is not set
+# CONFIG_DVB_ISL6423 is not set
+# CONFIG_DVB_A8293 is not set
+# CONFIG_DVB_SP2 is not set
+# CONFIG_DVB_LGS8GL5 is not set
+# CONFIG_DVB_LGS8GXX is not set
+# CONFIG_DVB_ATBM8830 is not set
+# CONFIG_DVB_TDA665x is not set
+# CONFIG_DVB_IX2505V is not set
+# CONFIG_DVB_M88RS2000 is not set
+CONFIG_DVB_AF9033=m
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+
+#
+# Graphics support
+#
+# CONFIG_AGP is not set
+# CONFIG_VGA_ARB is not set
+# CONFIG_VGA_SWITCHEROO is not set
+
+#
+# Direct Rendering Manager
+#
+# CONFIG_DRM is not set
+
+#
+# Frame buffer Devices
+#
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_DUMMY_CONSOLE_COLUMNS=80
+CONFIG_DUMMY_CONSOLE_ROWS=25
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+# CONFIG_SOUND_OSS_CORE_PRECLAIM is not set
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+# CONFIG_SND_MIXER_OSS is not set
+CONFIG_SND_PCM_OSS=y
+# CONFIG_SND_PCM_OSS_PLUGINS is not set
+# CONFIG_SND_HRTIMER is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+# CONFIG_SND_SUPPORT_OLD_API is not set
+CONFIG_SND_PROC_FS=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_DMA_SGBUF=y
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_ALOOP is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+CONFIG_SND_PCI=y
+# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
+# CONFIG_SND_ALS4000 is not set
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ASIHPI is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AW2 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_OXYGEN is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_CS5530 is not set
+# CONFIG_SND_CS5535AUDIO is not set
+# CONFIG_SND_CTXFI is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
+# CONFIG_SND_INDIGOIOX is not set
+# CONFIG_SND_INDIGODJX is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_LOLA is not set
+# CONFIG_SND_LX6464ES is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_SE6X is not set
+# CONFIG_SND_SIS7019 is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_TRIDENT is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VIRTUOSO is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_YMFPCI is not set
+
+#
+# HD-Audio
+#
+# CONFIG_SND_HDA_INTEL is not set
+CONFIG_SND_HDA_PREALLOC_SIZE=64
+CONFIG_SND_USB=y
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_UA101 is not set
+# CONFIG_SND_USB_USX2Y is not set
+# CONFIG_SND_USB_CAIAQ is not set
+# CONFIG_SND_USB_US122L is not set
+# CONFIG_SND_USB_6FIRE is not set
+# CONFIG_SND_USB_HIFACE is not set
+# CONFIG_SND_BCD2000 is not set
+# CONFIG_SND_USB_POD is not set
+# CONFIG_SND_USB_PODHD is not set
+# CONFIG_SND_USB_TONEPORT is not set
+# CONFIG_SND_USB_VARIAX is not set
+# CONFIG_SND_SOC is not set
+# CONFIG_SOUND_PRIME is not set
+
+#
+# HID support
+#
+CONFIG_HID=y
+# CONFIG_HID_BATTERY_STRENGTH is not set
+CONFIG_HIDRAW=y
+CONFIG_UHID=y
+CONFIG_HID_GENERIC=y
+
+#
+# Special HID drivers
+#
+CONFIG_HID_A4TECH=y
+# CONFIG_HID_ACRUX is not set
+CONFIG_HID_APPLE=y
+# CONFIG_HID_APPLEIR is not set
+# CONFIG_HID_AUREAL is not set
+CONFIG_HID_BELKIN=y
+# CONFIG_HID_BETOP_FF is not set
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+# CONFIG_HID_PRODIKEYS is not set
+# CONFIG_HID_CP2112 is not set
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_DRAGONRISE=y
+# CONFIG_DRAGONRISE_FF is not set
+# CONFIG_HID_EMS_FF is not set
+# CONFIG_HID_ELECOM is not set
+# CONFIG_HID_ELO is not set
+CONFIG_HID_EZKEY=y
+# CONFIG_HID_HOLTEK is not set
+# CONFIG_HID_GT683R is not set
+# CONFIG_HID_KEYTOUCH is not set
+CONFIG_HID_KYE=y
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+# CONFIG_HID_FBX_REMOTE_AUDIO is not set
+CONFIG_HID_GYRATION=y
+# CONFIG_HID_ICADE is not set
+# CONFIG_HID_TWINHAN is not set
+CONFIG_HID_KENSINGTON=y
+# CONFIG_HID_LCPOWER is not set
+# CONFIG_HID_LENOVO is not set
+CONFIG_HID_LOGITECH=y
+CONFIG_HID_LOGITECH_DJ=y
+CONFIG_HID_LOGITECH_HIDPP=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+# CONFIG_LOGIG940_FF is not set
+# CONFIG_LOGIWHEELS_FF is not set
+# CONFIG_HID_MAGICMOUSE is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+# CONFIG_HID_MULTITOUCH is not set
+CONFIG_HID_NTRIG=y
+# CONFIG_HID_ORTEK is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PENMOUNT is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_PICOLCD is not set
+# CONFIG_HID_PLANTRONICS is not set
+# CONFIG_HID_PRIMAX is not set
+# CONFIG_HID_ROCCAT is not set
+# CONFIG_HID_SAITEK is not set
+# CONFIG_HID_SAMSUNG is not set
+CONFIG_HID_SONY=y
+# CONFIG_SONY_FF is not set
+# CONFIG_HID_SPEEDLINK is not set
+# CONFIG_HID_STEELSERIES is not set
+CONFIG_HID_SUNPLUS=y
+# CONFIG_HID_RMI is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TIVO is not set
+CONFIG_HID_TOPSEED=y
+# CONFIG_HID_THINGM is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_WACOM is not set
+# CONFIG_HID_WIIMOTE is not set
+# CONFIG_HID_XINMO is not set
+# CONFIG_HID_ZEROPLUS is not set
+# CONFIG_HID_ZYDACRON is not set
+# CONFIG_HID_SENSOR_HUB is not set
+
+#
+# USB HID support
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+CONFIG_USB_HIDDEV=y
+
+#
+# I2C HID support
+#
+# CONFIG_I2C_HID is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEFAULT_PERSIST is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_OTG_FSM is not set
+# CONFIG_USB_ULPI_BUS is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_EHCI_PCI=m
+# CONFIG_USB_EHCI_HCD_PLATFORM is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_FUSBH200_HCD is not set
+# CONFIG_USB_FOTG210_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HCD_TEST_MODE is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_REALTEK is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_STORAGE_ENE_UB6250 is not set
+# CONFIG_USB_UAS is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USBIP_CORE is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_DWC3 is not set
+# CONFIG_USB_DWC2 is not set
+# CONFIG_USB_CHIPIDEA is not set
+# CONFIG_USB_ISP1760 is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_EHSET_TEST_FIXTURE is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+# CONFIG_USB_EZUSB_FX2 is not set
+# CONFIG_USB_HSIC_USB3503 is not set
+# CONFIG_USB_LINK_LAYER_TEST is not set
+# CONFIG_USB_CHAOSKEY is not set
+
+#
+# USB Physical Layer drivers
+#
+# CONFIG_USB_PHY is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ISP1301 is not set
+# CONFIG_USB_GADGET is not set
+# CONFIG_USB_LED_TRIG is not set
+# CONFIG_UWB is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+# CONFIG_LEDS_CLASS_FLASH is not set
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_BCM6328 is not set
+# CONFIG_LEDS_BCM6358 is not set
+# CONFIG_LEDS_LM3530 is not set
+# CONFIG_LEDS_LM3642 is not set
+# CONFIG_LEDS_PCA9532 is not set
+# CONFIG_LEDS_GPIO is not set
+# CONFIG_LEDS_LP3944 is not set
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_LP5523 is not set
+# CONFIG_LEDS_LP5562 is not set
+# CONFIG_LEDS_LP8501 is not set
+# CONFIG_LEDS_LP8860 is not set
+# CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_PCA963X is not set
+# CONFIG_LEDS_BD2802 is not set
+# CONFIG_LEDS_LT3593 is not set
+# CONFIG_LEDS_TCA6507 is not set
+# CONFIG_LEDS_TLC591XX is not set
+# CONFIG_LEDS_LM355x is not set
+# CONFIG_LEDS_OT200 is not set
+
+#
+# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM)
+#
+# CONFIG_LEDS_BLINKM is not set
+# CONFIG_LEDS_PM8941_WLED is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+# CONFIG_LEDS_TRIGGER_ONESHOT is not set
+# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+# CONFIG_LEDS_TRIGGER_CPU is not set
+# CONFIG_LEDS_TRIGGER_GPIO is not set
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+# CONFIG_LEDS_TRIGGER_TRANSIENT is not set
+# CONFIG_LEDS_TRIGGER_CAMERA is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_PCI is not set
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+# CONFIG_X86_PLATFORM_DEVICES is not set
+# CONFIG_CHROME_PLATFORMS is not set
+
+#
+# IntelCE devices
+#
+CONFIG_INTELCE_GPIO=y
+CONFIG_INTELCE_DFX=y
+
+#
+# Hardware Spinlock drivers
+#
+
+#
+# Clock Source drivers
+#
+CONFIG_CLKSRC_I8253=y
+CONFIG_CLKEVT_I8253=y
+CONFIG_CLKBLD_I8253=y
+# CONFIG_ATMEL_PIT is not set
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_SH_TIMER_MTU2 is not set
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+
+#
+# SOC (System On Chip) specific Drivers
+#
+# CONFIG_SUNXI_SRAM is not set
+# CONFIG_SOC_TI is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+# CONFIG_NTB is not set
+# CONFIG_VME_BUS is not set
+# CONFIG_PWM is not set
+CONFIG_IRQCHIP=y
+# CONFIG_IPACK_BUS is not set
+# CONFIG_RESET_CONTROLLER is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+# CONFIG_GENERIC_PHY is not set
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
+# CONFIG_BCM_KONA_USB2_PHY is not set
+# CONFIG_POWERCAP is not set
+# CONFIG_MCB is not set
+# CONFIG_THUNDERBOLT is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# CONFIG_LIBNVDIMM is not set
+
+#
+# Firmware Drivers
+#
+# CONFIG_EDD is not set
+CONFIG_FIRMWARE_MEMMAP=y
+# CONFIG_DELL_RBU is not set
+# CONFIG_DCDBAS is not set
+# CONFIG_ISCSI_IBFT_FIND is not set
+# CONFIG_GOOGLE_FIRMWARE is not set
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_USE_FOR_EXT23=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
+# CONFIG_EXT4_ENCRYPTION is not set
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_JBD2=y
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_XFS_FS=y
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_WARN is not set
+# CONFIG_XFS_DEBUG is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_F2FS_FS is not set
+# CONFIG_FS_DAX is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_EXPORTFS=y
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_FANOTIFY=y
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=y
+# CONFIG_CUSE is not set
+# CONFIG_OVERLAY_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=y
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=850
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+CONFIG_EXFAT_FS=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_PROC_CHILDREN is not set
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
+CONFIG_HFS_FS=y
+CONFIG_HFSPLUS_FS=y
+# CONFIG_HFSPLUS_FS_POSIX_ACL is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+CONFIG_UBIFS_FS=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_LOGFS is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_PSTORE=y
+# CONFIG_PSTORE_CONSOLE is not set
+# CONFIG_PSTORE_PMSG is not set
+CONFIG_PSTORE_RAM=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V2=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+# CONFIG_NFS_SWAP is not set
+# CONFIG_NFS_V4_1 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFS_USE_LEGACY_DNS is not set
+CONFIG_NFS_USE_KERNEL_DNS=y
+# CONFIG_NFSD is not set
+CONFIG_GRACE_PERIOD=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=y
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+CONFIG_NLS_UTF8=y
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+
+#
+# printk and dmesg options
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+
+#
+# Compile-time checks and compiler options
+#
+# CONFIG_DEBUG_INFO is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=0
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_READABLE_ASM is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_PAGE_OWNER is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_SECTION_MISMATCH=y
+CONFIG_ARCH_WANT_FRAME_POINTERS=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1
+CONFIG_DEBUG_KERNEL=y
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_VIRTUAL is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_PER_CPU_MAPS is not set
+CONFIG_HAVE_DEBUG_STACKOVERFLOW=y
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+CONFIG_HAVE_ARCH_KMEMCHECK=y
+# CONFIG_DEBUG_SHIRQ is not set
+
+#
+# Debug Lockups and Hangs
+#
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_HARDLOCKUP_DETECTOR=y
+CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y
+CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE=1
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=1
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+CONFIG_SCHED_DEBUG=y
+CONFIG_SCHED_INFO=y
+CONFIG_SCHEDSTATS=y
+# CONFIG_SCHED_STACK_END_CHECK is not set
+# CONFIG_DEBUG_TIMEKEEPING is not set
+# CONFIG_TIMER_STATS is not set
+CONFIG_DEBUG_PREEMPT=y
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_LOCK_TORTURE_TEST is not set
+# CONFIG_STACKTRACE is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_PI_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_PROVE_RCU is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_TORTURE_TEST is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_RCU_CPU_STALL_TIMEOUT=60
+# CONFIG_RCU_CPU_STALL_INFO is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_RCU_EQS_DEBUG is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_NOTIFIER_ERROR_INJECTION is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS=y
+# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set
+CONFIG_USER_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+
+#
+# Runtime Testing
+#
+# CONFIG_LKDTM is not set
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_RBTREE_TEST is not set
+# CONFIG_INTERVAL_TREE_TEST is not set
+# CONFIG_PERCPU_TEST is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_TEST_LKM is not set
+# CONFIG_TEST_USER_COPY is not set
+# CONFIG_TEST_BPF is not set
+# CONFIG_TEST_FIRMWARE is not set
+# CONFIG_TEST_UDELAY is not set
+# CONFIG_MEMTEST is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_STRICT_DEVMEM is not set
+CONFIG_X86_VERBOSE_BOOTUP=y
+CONFIG_EARLY_PRINTK=y
+# CONFIG_EARLY_PRINTK_DBGP is not set
+# CONFIG_X86_PTDUMP is not set
+CONFIG_DEBUG_RODATA=y
+# CONFIG_DEBUG_RODATA_TEST is not set
+# CONFIG_DEBUG_SET_MODULE_RONX is not set
+# CONFIG_DEBUG_NX_TEST is not set
+CONFIG_DOUBLEFAULT=y
+# CONFIG_DEBUG_TLBFLUSH is not set
+# CONFIG_IOMMU_STRESS is not set
+CONFIG_HAVE_MMIOTRACE_SUPPORT=y
+CONFIG_IO_DELAY_TYPE_0X80=0
+CONFIG_IO_DELAY_TYPE_0XED=1
+CONFIG_IO_DELAY_TYPE_UDELAY=2
+CONFIG_IO_DELAY_TYPE_NONE=3
+CONFIG_IO_DELAY_0X80=y
+# CONFIG_IO_DELAY_0XED is not set
+# CONFIG_IO_DELAY_UDELAY is not set
+# CONFIG_IO_DELAY_NONE is not set
+CONFIG_DEFAULT_IO_DELAY_TYPE=0
+# CONFIG_DEBUG_BOOT_PARAMS is not set
+# CONFIG_CPA_DEBUG is not set
+# CONFIG_OPTIMIZE_INLINING is not set
+# CONFIG_DEBUG_ENTRY is not set
+# CONFIG_DEBUG_NMI_SELFTEST is not set
+# CONFIG_X86_DEBUG_STATIC_CPU_HAS is not set
+# CONFIG_X86_DEBUG_FPU is not set
+# CONFIG_PUNIT_ATOM_DEBUG is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_PERSISTENT_KEYRINGS is not set
+# CONFIG_BIG_KEYS is not set
+# CONFIG_ENCRYPTED_KEYS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=y
+CONFIG_CRYPTO_PCOMP2=y
+CONFIG_CRYPTO_AKCIPHER2=y
+# CONFIG_CRYPTO_RSA is not set
+# CONFIG_CRYPTO_BUILTIN_TEST is not set
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_USER is not set
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_NULL=y
+# CONFIG_CRYPTO_PCRYPT is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_MCRYPTD is not set
+CONFIG_CRYPTO_AUTHENC=y
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_CHACHA20POLY1305 is not set
+# CONFIG_CRYPTO_SEQIV is not set
+CONFIG_CRYPTO_ECHAINIV=y
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_CMAC=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_CRC32C_INTEL is not set
+# CONFIG_CRYPTO_CRC32 is not set
+# CONFIG_CRYPTO_CRC32_PCLMUL is not set
+# CONFIG_CRYPTO_CRCT10DIF is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_POLY1305 is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_AES_586=y
+# CONFIG_CRYPTO_AES_NI_INTEL is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SALSA20_586 is not set
+# CONFIG_CRYPTO_CHACHA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_SERPENT_SSE2_586 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_TWOFISH_586 is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ZLIB is not set
+CONFIG_CRYPTO_LZO=y
+# CONFIG_CRYPTO_842 is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=y
+CONFIG_CRYPTO_DRBG_MENU=y
+CONFIG_CRYPTO_DRBG_HMAC=y
+# CONFIG_CRYPTO_DRBG_HASH is not set
+# CONFIG_CRYPTO_DRBG_CTR is not set
+CONFIG_CRYPTO_DRBG=y
+CONFIG_CRYPTO_JITTERENTROPY=y
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+# CONFIG_CRYPTO_USER_API_RNG is not set
+# CONFIG_CRYPTO_USER_API_AEAD is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_PADLOCK is not set
+# CONFIG_CRYPTO_DEV_GEODE is not set
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_CRYPTO_DEV_CCP is not set
+# CONFIG_CRYPTO_DEV_QAT_DH895xCC is not set
+# CONFIG_ASYMMETRIC_KEY_TYPE is not set
+CONFIG_HAVE_KVM=y
+# CONFIG_VIRTUALIZATION is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_HAVE_ARCH_BITREVERSE is not set
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_FIND_FIRST_BIT=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_PERCPU_RWSEM=y
+CONFIG_ARCH_HAS_FAST_MULTIPLIER=y
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+# CONFIG_CRC8 is not set
+CONFIG_AUDIT_GENERIC=y
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+# CONFIG_XZ_DEC is not set
+# CONFIG_XZ_DEC_BCJ is not set
+CONFIG_REED_SOLOMON=y
+CONFIG_REED_SOLOMON_ENC8=y
+CONFIG_REED_SOLOMON_DEC8=y
+CONFIG_ASSOCIATIVE_ARRAY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAS_DMA=y
+CONFIG_CPU_RMAP=y
+CONFIG_DQL=y
+CONFIG_GLOB=y
+# CONFIG_GLOB_SELFTEST is not set
+CONFIG_NLATTR=y
+CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
+# CONFIG_AVERAGE is not set
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+CONFIG_LIBFDT=y
+CONFIG_OID_REGISTRY=y
+CONFIG_ARCH_HAS_SG_CHAIN=y
+CONFIG_ARCH_HAS_PMEM_API=y
+CONFIG_FBXSERIAL=y
diff -Nruw linux-4.2-fbx/drivers/fbxgpio./Kconfig linux-4.2-fbx/drivers/fbxgpio/Kconfig
--- linux-4.2-fbx/drivers/fbxgpio./Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/fbxgpio/Kconfig	2010-02-25 15:41:07.511150361 +0100
@@ -0,0 +1,3 @@
+config FREEBOX_GPIO
+	tristate "Freebox GPIO control interface"
+	default n
diff -Nruw linux-4.2-fbx/drivers/fbxgpio./Makefile linux-4.2-fbx/drivers/fbxgpio/Makefile
--- linux-4.2-fbx/drivers/fbxgpio./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/fbxgpio/Makefile	2010-02-25 15:41:07.511150361 +0100
@@ -0,0 +1 @@
+obj-$(CONFIG_FREEBOX_GPIO)	+= fbxgpio_core.o
diff -Nruw linux-4.2-fbx/drivers/fbxjtag./Kconfig linux-4.2-fbx/drivers/fbxjtag/Kconfig
--- linux-4.2-fbx/drivers/fbxjtag./Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/fbxjtag/Kconfig	2010-02-25 15:41:07.511150361 +0100
@@ -0,0 +1,3 @@
+config FREEBOX_JTAG
+	tristate "Freebox JTAG control interface"
+	default n
diff -Nruw linux-4.2-fbx/drivers/fbxjtag./Makefile linux-4.2-fbx/drivers/fbxjtag/Makefile
--- linux-4.2-fbx/drivers/fbxjtag./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/fbxjtag/Makefile	2010-02-25 15:41:07.511150361 +0100
@@ -0,0 +1 @@
+obj-$(CONFIG_FREEBOX_JTAG)	+= fbxjtag.o
diff -Nruw linux-4.2-fbx/drivers/fbxmtd./Kconfig linux-4.2-fbx/drivers/fbxmtd/Kconfig
--- linux-4.2-fbx/drivers/fbxmtd./Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/fbxmtd/Kconfig	2010-02-25 15:41:07.511150361 +0100
@@ -0,0 +1,41 @@
+menuconfig FREEBOX_MTD
+	tristate "Freebox Memory Technology Devices (FBXMTD) support"
+
+if FREEBOX_MTD
+
+config FREEBOX_MTD_BACKEND_AMD
+	bool "Support for AMD compatible flash"
+
+config FREEBOX_MTD_BACKEND_INTEL
+	bool "Support for Intel Strataflash"
+
+config FREEBOX_MTD_BLK
+	tristate "Block device access to fbxmtd"
+	depends on BLOCK
+
+config FREEBOX_MTD_CHAR
+	tristate "Character device access to fbxmtd"
+
+
+comment "Mapping drivers"
+
+#
+# Generic mapping driver.
+#
+config FREEBOX_MTD_MAP_DRV_FBX
+	tristate "Freebox mapping Driver."
+	select CRC32
+
+config FREEBOX_MTD_MAP_DRV_BCM963XX
+	tristate "Broadcom 963xx flash format"
+	select CRC32
+
+#
+# Freebox MTD Map Control interface
+#
+config FREEBOX_MTD_MAP_IOCTL
+	tristate "IOCTL control interface"
+	depends on FREEBOX_MTD_MAP_DRV_FBX
+
+endif
+
diff -Nruw linux-4.2-fbx/drivers/fbxmtd./Makefile linux-4.2-fbx/drivers/fbxmtd/Makefile
--- linux-4.2-fbx/drivers/fbxmtd./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/fbxmtd/Makefile	2010-02-25 15:41:07.511150361 +0100
@@ -0,0 +1,24 @@
+
+# core support
+obj-$(CONFIG_FREEBOX_MTD) += fbxmtd.o
+
+fbxmtd-objs += fbxmtd_core.o fbxmtd_core_io.o
+ifeq ($(CONFIG_FREEBOX_MTD_BACKEND_AMD),y)
+fbxmtd-objs += fbxmtd_core_amd.o
+endif
+
+ifeq ($(CONFIG_FREEBOX_MTD_BACKEND_INTEL),y)
+fbxmtd-objs += fbxmtd_core_intel.o
+endif
+
+# generic character device access support (r/w with read erase modify write)
+obj-$(CONFIG_FREEBOX_MTD_CHAR) += fbxmtd_char.o
+fbxmtd_char-objs += fbxmtd_char_dev.o
+
+# generic r/o block device access support
+obj-$(CONFIG_FREEBOX_MTD_BLK) += fbxmtd_blk.o
+fbxmtd_blk-objs += fbxmtd_blk_dev.o
+
+obj-$(CONFIG_FREEBOX_MTD_MAP_DRV_FBX) += fbxmtd_map_drv_fbx.o
+obj-$(CONFIG_FREEBOX_MTD_MAP_DRV_BCM963XX) += fbxmtd_map_drv_bcm963xx.o
+obj-$(CONFIG_FREEBOX_MTD_MAP_IOCTL) += fbxmtd_map_ioctl.o
diff -Nruw linux-4.2-fbx/drivers/fbxprocfs./fbxprocfs.c linux-4.2-fbx/drivers/fbxprocfs/fbxprocfs.c
--- linux-4.2-fbx/drivers/fbxprocfs./fbxprocfs.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/fbxprocfs/fbxprocfs.c	2013-12-04 14:33:18.903478972 +0100
@@ -0,0 +1,299 @@
+/*
+ * Freebox ProcFs interface
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
+#include <linux/sizes.h>
+
+#include <linux/fbxprocfs.h>
+
+#define PFX	"fbxprocfs: "
+
+
+static struct list_head clients;
+static struct mutex clients_mutex;
+
+static struct proc_dir_entry *root;
+
+/*
+ * register  a  fbxprocfs client  with  given  dirname, caller  should
+ * consider returned struct opaque
+ */
+struct fbxprocfs_client *fbxprocfs_add_client(const char *dirname,
+					      struct module *owner)
+{
+	struct fbxprocfs_client *ret, *p;
+
+	ret = NULL;
+	mutex_lock(&clients_mutex);
+
+	/* check for duplicate */
+	list_for_each_entry(p, &clients, list) {
+		if (!strcmp(dirname, p->dirname))
+			goto out;
+	}
+
+	if (!(ret = kmalloc(sizeof (*ret), GFP_KERNEL))) {
+		printk(KERN_ERR PFX "kmalloc failed\n");
+		goto out;
+	}
+
+	/* try to create client directory */
+	if (!(ret->dir = proc_mkdir(dirname, root))) {
+		printk(KERN_ERR PFX "can't create %s dir\n", dirname);
+		kfree(ret);
+		ret = NULL;
+		goto out;
+	}
+
+	atomic_set(&ret->refcount, 1);
+	ret->dirname = dirname;
+	list_add(&ret->list, &clients);
+
+out:
+	mutex_unlock(&clients_mutex);
+	return ret;
+}
+
+/*
+ * unregister  a  fbxprocfs client, make sure usage count is zero
+ */
+int fbxprocfs_remove_client(struct fbxprocfs_client *client)
+{
+	int ret;
+
+	mutex_lock(&clients_mutex);
+
+	ret = 0;
+	if (atomic_read(&client->refcount) > 1) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	remove_proc_entry(client->dirname, root);
+	list_del(&client->list);
+	kfree(client);
+
+out:
+	mutex_unlock(&clients_mutex);
+	return ret;
+}
+
+/*
+ * remove given entries from client directory
+ */
+static int
+__remove_entries(struct fbxprocfs_client *client,
+		 const struct fbxprocfs_desc *ro_desc,
+		 const struct fbxprocfs_desc *rw_desc)
+{
+	int i;
+
+	for (i = 0; ro_desc && ro_desc[i].name; i++) {
+		remove_proc_entry(ro_desc[i].name, client->dir);
+		atomic_dec(&client->refcount);
+	}
+
+	for (i = 0; rw_desc && rw_desc[i].name; i++) {
+		remove_proc_entry(rw_desc[i].name, client->dir);
+		atomic_dec(&client->refcount);
+	}
+
+	return 0;
+}
+
+/*
+ * replacement for NULL rfunc.
+ */
+static int bad_rfunc(struct seq_file *m, void *ptr)
+{
+	return -EACCES;
+}
+
+/*
+ * fbxprocfs write path is now handled by seq_file code. this
+ * simplifies client code greatly.
+ */
+static int fbxprocfs_open(struct inode *inode, struct file *file)
+{
+	const struct fbxprocfs_desc *desc = PDE_DATA(inode);
+
+	return single_open(file, desc->rfunc ? desc->rfunc : bad_rfunc,
+			   (void*)desc->id);
+}
+
+/*
+ * no particular help from kernel in the write path, fetch user buffer
+ * in a kernel buffer and call write func.
+ */
+static int fbxprocfs_write(struct file *file, const char __user *ubuf,
+			   size_t len, loff_t *off)
+{
+	/*
+	 * get fbxprocfs desc via the proc_dir_entry in file inode
+	 */
+	struct fbxprocfs_desc *d = PDE_DATA(file_inode(file));
+	char *kbuf;
+	int ret;
+
+	/*
+	 * must have a wfunc callback.
+	 */
+	if (!d->wfunc)
+		return -EACCES;
+
+	/*
+	 * allow up to SZ_4K bytes to be written.
+	 */
+	if (len > SZ_4K)
+		return -EOVERFLOW;
+
+	/*
+	 * alloc and fetch kernel buffer containing user data.
+	 */
+	kbuf = kmalloc(SZ_4K, GFP_KERNEL);
+	if (!kbuf)
+		return -ENOMEM;
+
+	ret = -EFAULT;
+	if (copy_from_user(kbuf, ubuf, len))
+		goto kfree;
+
+	ret = d->wfunc(file, kbuf, len, (void*)d->id);
+
+kfree:
+	kfree(kbuf);
+	return ret;
+}
+
+/*
+ * fbxprocfs file operations, read stuff is handled by seq_file code.
+ */
+static const struct file_operations fbxprocfs_fops = {
+	.open		= fbxprocfs_open,
+	.llseek		= seq_lseek,
+	.read		= seq_read,
+	.release	= seq_release,
+	.write		= fbxprocfs_write,
+};
+
+/*
+ * replaces create_proc_read_entry removed in latest kernels.
+ */
+static struct proc_dir_entry *__create_proc_read_entry(
+				       const struct fbxprocfs_desc *desc,
+				       struct proc_dir_entry *base)
+{
+	return proc_create_data(desc->name, 0, base, &fbxprocfs_fops,
+				(void*)desc);
+}
+
+/*
+ * replaces create_proc_entry removed in latest kernels.
+ */
+static struct proc_dir_entry *__create_proc_entry(
+					const struct fbxprocfs_desc *desc,
+					struct proc_dir_entry *base)
+{
+	return proc_create_data(desc->name, S_IFREG | S_IWUSR | S_IRUGO,
+				base, &fbxprocfs_fops, (void*)desc);
+}
+
+/*
+ * create given entries in client directory
+ */
+static int
+__create_entries(struct fbxprocfs_client *client,
+		 const struct fbxprocfs_desc *ro_desc,
+		 const struct fbxprocfs_desc *rw_desc)
+{
+	struct proc_dir_entry	*proc;
+	int			i;
+
+	for (i = 0; ro_desc && ro_desc[i].name; i++) {
+		if (!(proc = __create_proc_read_entry(&ro_desc[i],
+						      client->dir))) {
+			printk(KERN_ERR PFX "can't create %s/%s entry\n",
+			       client->dirname, ro_desc[i].name);
+			goto err;
+		}
+		atomic_inc(&client->refcount);
+	}
+
+	for (i = 0; rw_desc && rw_desc[i].name; i++) {
+		if (!(proc = __create_proc_entry(&rw_desc[i], client->dir))) {
+			printk(KERN_ERR PFX "can't create %s/%s entry\n",
+			       client->dirname, ro_desc[i].name);
+			goto err;
+		}
+		atomic_inc(&client->refcount);
+	}
+
+	return 0;
+
+err:
+	__remove_entries(client, ro_desc, rw_desc);
+	return -1;
+}
+
+int
+fbxprocfs_create_entries(struct fbxprocfs_client *client,
+			 const struct fbxprocfs_desc *ro_desc,
+			 const struct fbxprocfs_desc *rw_desc)
+{
+	int	ret;
+
+	ret = __create_entries(client, ro_desc, rw_desc);
+	return ret;
+}
+
+int
+fbxprocfs_remove_entries(struct fbxprocfs_client *client,
+			 const struct fbxprocfs_desc *ro_desc,
+			 const struct fbxprocfs_desc *rw_desc)
+{
+	int	ret;
+
+	ret = __remove_entries(client, ro_desc, rw_desc);
+	return ret;
+}
+
+
+static int __init
+fbxprocfs_init(void)
+{
+	INIT_LIST_HEAD(&clients);
+	mutex_init(&clients_mutex);
+
+	/* create freebox directory */
+	if (!(root = proc_mkdir("freebox", NULL))) {
+		printk(KERN_ERR PFX "can't create freebox/ dir\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+static void __exit
+fbxprocfs_exit(void)
+{
+	remove_proc_entry("freebox", NULL);
+}
+
+module_init(fbxprocfs_init);
+module_exit(fbxprocfs_exit);
+
+EXPORT_SYMBOL(fbxprocfs_create_entries);
+EXPORT_SYMBOL(fbxprocfs_remove_entries);
+EXPORT_SYMBOL(fbxprocfs_add_client);
+EXPORT_SYMBOL(fbxprocfs_remove_client);
+
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0");
+MODULE_AUTHOR("Maxime Bizon <mbizon@freebox.fr>");
+
diff -Nruw linux-4.2-fbx/drivers/fbxprocfs./Kconfig linux-4.2-fbx/drivers/fbxprocfs/Kconfig
--- linux-4.2-fbx/drivers/fbxprocfs./Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/fbxprocfs/Kconfig	2010-02-25 15:41:07.519542884 +0100
@@ -0,0 +1,2 @@
+config FREEBOX_PROCFS
+	tristate "Freebox procfs interface"
diff -Nruw linux-4.2-fbx/drivers/fbxprocfs./Makefile linux-4.2-fbx/drivers/fbxprocfs/Makefile
--- linux-4.2-fbx/drivers/fbxprocfs./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/fbxprocfs/Makefile	2010-02-25 15:41:07.519542884 +0100
@@ -0,0 +1 @@
+obj-$(CONFIG_FREEBOX_PROCFS) += fbxprocfs.o
diff -Nruw linux-4.2-fbx/drivers/fbxwatchdog./Kconfig linux-4.2-fbx/drivers/fbxwatchdog/Kconfig
--- linux-4.2-fbx/drivers/fbxwatchdog./Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/fbxwatchdog/Kconfig	2013-12-04 14:33:18.903478972 +0100
@@ -0,0 +1,20 @@
+menuconfig FREEBOX_WATCHDOG
+	tristate "Freebox Watchdog"
+	default n
+
+if FREEBOX_WATCHDOG
+
+config FREEBOX_WATCHDOG_CHAR
+	bool "Freebox Watchdog char device interface."
+	default n
+
+config FREEBOX_WATCHDOG_ORION
+	tristate "Marvell Orion support"
+	depends on PLAT_ORION
+
+config FREEBOX_WATCHDOG_BCM63XX
+	tristate "Broadcom 63xx Freebox Watchdog support"
+	depends on BCM63XX
+	default n
+
+endif
diff -Nruw linux-4.2-fbx/drivers/fbxwatchdog./Makefile linux-4.2-fbx/drivers/fbxwatchdog/Makefile
--- linux-4.2-fbx/drivers/fbxwatchdog./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/fbxwatchdog/Makefile	2013-12-04 14:33:18.903478972 +0100
@@ -0,0 +1,9 @@
+obj-$(CONFIG_FREEBOX_WATCHDOG) += fbxwatchdog.o
+
+fbxwatchdog-objs = fbxwatchdog_core.o
+ifeq ($(CONFIG_FREEBOX_WATCHDOG_CHAR),y)
+fbxwatchdog-objs += fbxwatchdog_char.o
+endif
+
+obj-$(CONFIG_FREEBOX_WATCHDOG_ORION)	+= fbxwatchdog_orion.o
+obj-$(CONFIG_FREEBOX_WATCHDOG_BCM63XX)	+= fbxwatchdog_bcm63xx.o
diff -Nruw linux-4.2-fbx/drivers/media/platform/tango2./Kconfig linux-4.2-fbx/drivers/media/platform/tango2/Kconfig
--- linux-4.2-fbx/drivers/media/platform/tango2./Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/media/platform/tango2/Kconfig	2013-12-04 14:33:19.559478983 +0100
@@ -0,0 +1,11 @@
+config DVB_TANGO2
+	tristate "Tango2 DVB adapter"
+	depends on ARCH_FBX5_B
+	select I2C
+	select I2C_ALGOBIT
+	select DVB_TDA1004X
+	select DVB_PLL
+
+config DVB_TANGO2_TESTBED
+	bool "extended testing and useful error codes"
+	depends on DVB_TANGO2
diff -Nruw linux-4.2-fbx/drivers/media/platform/tango2./Makefile linux-4.2-fbx/drivers/media/platform/tango2/Makefile
--- linux-4.2-fbx/drivers/media/platform/tango2./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/media/platform/tango2/Makefile	2013-12-04 14:33:19.559478983 +0100
@@ -0,0 +1,5 @@
+obj-$(CONFIG_DVB_TANGO2) = tango2_dvb.o
+
+tango2_dvb-objs := tango2.o
+
+EXTRA_CFLAGS = -Idrivers/media/dvb-core/ -Idrivers/media/dvb-frontends/
--- /dev/null	2015-07-31 18:17:35.952031993 +0200
+++ linux-4.2-fbx/drivers/media/rc/keymaps/rc-rc6-freebox.c	2013-12-04 14:33:19.575478983 +0100
@@ -0,0 +1,135 @@
+/* rc-rc6-freebox.c - Keytable for Freebox/Alicebox IR controller
+ *
+ * Copyright (c) 2012 by Nicolas Pouillon <npouillon@freebox.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <media/rc-map.h>
+#include <linux/module.h>
+
+#define RC6_FREEBOX_TV 0xf2
+#define RC6_FREEBOX_WIDE 0x49
+#define RC6_FREEBOX_POWER 0x0c
+#define RC6_FREEBOX_STOP 0x31
+#define RC6_FREEBOX_REC 0x37
+#define RC6_FREEBOX_REW 0x2f
+#define RC6_FREEBOX_PLAY 0xb8
+#define RC6_FREEBOX_FF 0x2e
+#define RC6_FREEBOX_PREV 0x4d
+#define RC6_FREEBOX_NEXT 0x4c
+#define RC6_FREEBOX_RELOAD 0x83
+#define RC6_FREEBOX_MENU 0xcc
+#define RC6_FREEBOX_UP 0x99
+#define RC6_FREEBOX_LEFT 0x9b
+#define RC6_FREEBOX_RIGHT 0x9c
+#define RC6_FREEBOX_DOWN 0x9a
+#define RC6_FREEBOX_OK 0x5c
+#define RC6_FREEBOX_VOL_INC 0x5b
+#define RC6_FREEBOX_VOL_DEC 0x5a
+#define RC6_FREEBOX_MUTE 0x0d
+#define RC6_FREEBOX_PROG_UP 0x58
+#define RC6_FREEBOX_PROG_DOWN 0x59
+#define RC6_FREEBOX_FREEBOX 0xd7
+#define RC6_FREEBOX_RED 0x6d
+#define RC6_FREEBOX_GREEN 0x6e
+#define RC6_FREEBOX_YELLOW 0x6f
+#define RC6_FREEBOX_BLUE 0x70
+#define RC6_FREEBOX_1 0x01
+#define RC6_FREEBOX_2 0x02
+#define RC6_FREEBOX_3 0x03
+#define RC6_FREEBOX_4 0x04
+#define RC6_FREEBOX_5 0x05
+#define RC6_FREEBOX_6 0x06
+#define RC6_FREEBOX_7 0x07
+#define RC6_FREEBOX_8 0x08
+#define RC6_FREEBOX_9 0x09
+#define RC6_FREEBOX_BACK 0x9e
+#define RC6_FREEBOX_0 0x00
+#define RC6_FREEBOX_SWAP 0x0a
+#define RC6_FREEBOX_HELP 0x81
+#define RC6_FREEBOX_INFO 0x0f
+#define RC6_FREEBOX_GUIDE 0x97
+#define RC6_FREEBOX_OPTIONS 0x54
+
+#define MAP(x,y) { 0x80382600 + RC6_FREEBOX_##x, KEY_##y }
+
+static struct rc_map_table rc6_freebox[] = {
+	MAP(0, NUMERIC_0),
+	MAP(1, NUMERIC_1),
+	MAP(2, NUMERIC_2),
+	MAP(3, NUMERIC_3),
+	MAP(4, NUMERIC_4),
+	MAP(5, NUMERIC_5),
+	MAP(6, NUMERIC_6),
+	MAP(7, NUMERIC_7),
+	MAP(8, NUMERIC_8),
+	MAP(9, NUMERIC_9),
+	MAP(SWAP, BACK),
+	MAP(POWER, POWER),
+	MAP(MUTE, MUTE),
+	MAP(INFO, INFO),
+
+	MAP(FF, FASTFORWARD),
+	MAP(REW, REWIND),
+	MAP(STOP, STOP),
+	MAP(REC, RECORD),
+	MAP(WIDE, ZOOM),
+	MAP(PREV, PREVIOUS),
+	MAP(NEXT, NEXT),
+
+	MAP(OPTIONS, OPTION),
+	MAP(PROG_UP, CHANNELUP),
+	MAP(PROG_DOWN, CHANNELDOWN),
+	MAP(VOL_DEC, VOLUMEDOWN),
+	MAP(VOL_INC, VOLUMEUP),
+	MAP(OK, OK),
+
+	MAP(RED, RED),
+	MAP(GREEN, GREEN),
+	MAP(YELLOW, YELLOW),
+	MAP(BLUE, BLUE),
+
+	MAP(HELP, HELP),
+	MAP(RELOAD, REFRESH),
+
+	MAP(GUIDE, PROGRAM),
+	MAP(UP, UP),
+	MAP(DOWN, DOWN),
+	MAP(LEFT, LEFT),
+	MAP(RIGHT, RIGHT),
+	MAP(BACK, BACKSPACE),
+	MAP(PLAY, PLAY),
+
+	MAP(MENU, LIST),
+	MAP(FREEBOX, HOME),
+	MAP(TV, SCREEN),
+};
+
+static struct rc_map_list rc6_freebox_map = {
+	.map = {
+		.scan    = rc6_freebox,
+		.size    = ARRAY_SIZE(rc6_freebox),
+		.rc_type = RC_TYPE_RC6_MCE,
+		.name    = "rc-rc6-freebox",
+	}
+};
+
+static int __init init_rc_map_rc6_freebox(void)
+{
+	return rc_map_register(&rc6_freebox_map);
+}
+
+static void __exit exit_rc_map_rc6_freebox(void)
+{
+	rc_map_unregister(&rc6_freebox_map);
+}
+
+module_init(init_rc_map_rc6_freebox)
+module_exit(exit_rc_map_rc6_freebox)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Nicolas Pouillon <npouillon@freebox.fr>");
diff -Nruw linux-4.2-fbx/drivers/misc/hdmi-cec./core.c linux-4.2-fbx/drivers/misc/hdmi-cec/core.c
--- linux-4.2-fbx/drivers/misc/hdmi-cec./core.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/misc/hdmi-cec/core.c	2015-09-15 19:18:37.914454588 +0200
@@ -0,0 +1,580 @@
+/*
+ * HDMI Consumer Electronics Control, core module
+ *
+ * Copyright (C) 2011, Florian Fainelli <ffainelli@freebox;fr>
+ *
+ * This file is subject to the GPLv2 licensing terms.
+ *
+ */
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+#include <linux/completion.h>
+#include <linux/mutex.h>
+
+#include <linux/hdmi-cec/hdmi-cec.h>
+#include <linux/hdmi-cec/dev.h>
+
+#include "hdmi-cec-priv.h"
+
+static unsigned cec_adapter_count;
+
+#define CEC_RX_QUEUE_MAX_LEN	(20)
+
+/**
+ * cec_set_logical_address() - sets the cec logical address
+ * @adapter:	adapter pointer
+ * @addr:	logical address
+ *
+ * calls the adapter specific set_logical_address callback
+ */
+int cec_set_logical_address(struct cec_adapter *adapter, const u8 addr)
+{
+	int ret;
+
+	if (addr > CEC_ADDR_MAX)
+		return -EINVAL;
+
+	mutex_lock(&adapter->lock);
+	if (adapter->dead)
+		ret = -ENODEV;
+	else
+		ret = adapter->ops->set_logical_address(adapter, addr);
+	mutex_unlock(&adapter->lock);
+
+	return ret;
+}
+
+/**
+ *  __cec_rx_queue_len() - returns the lenght of a cec driver rx queue
+ * @adapter:	adapter pointer
+ */
+unsigned __cec_rx_queue_len(struct cec_adapter *adapter)
+{
+	unsigned qlen;
+
+	spin_lock(&adapter->rx_msg_list_lock);
+	qlen = adapter->rx_msg_len;
+	spin_unlock(&adapter->rx_msg_list_lock);
+
+	return qlen;
+}
+
+/**
+ * adapter_rx_done() - called by an adapter when message is received
+ * @adapter:	adapter pointer
+ * @data:	message blob
+ * @len:	message length
+ */
+int adapter_rx_done(struct cec_adapter *adapter,
+		    const u8 *data, const u8 len,
+		    bool valid, u8 rx_flags)
+{
+	struct cec_rx_kmsg *kmsg;
+	struct cec_rx_msg *msg;
+	int ret = 0;
+
+	if (!len || len > CEC_MAX_MSG_LEN)
+		return -EINVAL;
+
+	if (!adapter->attached) {
+		pr_debug("%s: no client attached, dropping", adapter->name);
+		goto out;
+	}
+
+	spin_lock(&adapter->rx_msg_list_lock);
+	if (adapter->rx_msg_len >= CEC_RX_QUEUE_MAX_LEN) {
+		pr_debug("%s: queue full!\n", adapter->name);
+		ret = -ENOSPC;
+		goto out_unlock;
+	}
+
+	kmsg = kzalloc(sizeof(*kmsg), GFP_ATOMIC);
+	if (!kmsg) {
+		ret = ENOMEM;
+		goto out_unlock;
+	}
+
+	msg = &kmsg->msg;
+	memcpy(&msg->data, data, len);
+	msg->len = len;
+	msg->valid = valid;
+	msg->flags = rx_flags;
+	list_add_tail(&kmsg->next, &adapter->rx_msg_list);
+	adapter->rx_msg_len++;
+
+out_unlock:
+	spin_unlock(&adapter->rx_msg_list_lock);
+
+	/* wake up clients, they can dequeue a buffer now */
+	wake_up_interruptible(&adapter->wait);
+
+out:
+	return ret;
+}
+EXPORT_SYMBOL(adapter_rx_done);
+
+/**
+ * cec_read_message() - reads a cec message from the adapter's rx queue
+ * @adapter:	adapter pointer
+ * @msg:	cec user-space exposed message pointer
+ *
+ * Reads a CEC message from the adapter's RX queue in blocking mode with
+ * either a finite or inifinite timeout
+ */
+int cec_read_message(struct cec_adapter *adapter,
+		     struct cec_rx_msg *msg,
+		     bool non_block)
+{
+	struct cec_rx_kmsg *kmsg;
+	int ret = 0;
+
+	if (!non_block) {
+		ret = wait_event_interruptible(adapter->wait,
+					       __cec_rx_queue_len(adapter) != 0 ||
+					       adapter->dead);
+		if (ret)
+			return ret;
+	}
+
+	if (adapter->dead)
+		return -ENODEV;
+
+	spin_lock(&adapter->rx_msg_list_lock);
+	if (list_empty(&adapter->rx_msg_list)) {
+		ret = -EAGAIN;
+		goto out;
+	}
+
+	kmsg = list_first_entry(&adapter->rx_msg_list,
+				struct cec_rx_kmsg, next);
+	memcpy(msg, &kmsg->msg, sizeof (*msg));
+	list_del(&kmsg->next);
+	kfree(kmsg);
+	adapter->rx_msg_len--;
+
+out:
+	spin_unlock(&adapter->rx_msg_list_lock);
+	return ret;
+}
+
+/**
+ * cec_send_message() - sends an user fed cec message
+ * @adapter:	adapter pointer
+ * @msg:	user-exposed cec message pointer
+ *
+ * Send a message using the specific adapter
+ */
+int cec_send_message(struct cec_adapter *adapter, struct cec_tx_msg *msg)
+{
+	int ret;
+
+	if (!msg->len || msg->len > CEC_MAX_MSG_LEN)
+		return -EINVAL;
+
+	mutex_lock(&adapter->lock);
+
+	if (adapter->dead) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	/* prevent queuing more than one message */
+	if (test_bit(0, &adapter->tx_pending)) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	/* try to send it */
+	set_bit(0, &adapter->tx_pending);
+	ret = adapter->ops->send(adapter, msg->expire_ms,
+				 msg->data, msg->len);
+	if (ret)
+		clear_bit(0, &adapter->tx_pending);
+
+	adapter->tx_timeout_timer.expires = jiffies + HZ * 5;
+	add_timer(&adapter->tx_timeout_timer);
+
+out:
+	mutex_unlock(&adapter->lock);
+	return ret;
+}
+
+/**
+ * adapter_tx_done() - called by adapter when tx is complete
+ * @adapter:	adapter pointer
+ *
+ */
+static void __adapter_tx_done(struct cec_adapter *adapter, bool success,
+			      u8 flags, u8 tries)
+{
+	adapter->last_tx_success = success;
+	adapter->last_tx_flags = flags;
+	adapter->last_tx_tries = tries;
+	smp_mb__before_atomic();
+	clear_bit(0, &adapter->tx_pending);
+	wake_up_interruptible(&adapter->wait);
+}
+
+void adapter_tx_done(struct cec_adapter *adapter, bool success,
+		     u8 flags, u8 tries)
+{
+	del_timer_sync(&adapter->tx_timeout_timer);
+	__adapter_tx_done(adapter, success, flags, tries);
+}
+
+EXPORT_SYMBOL(adapter_tx_done);
+
+/*
+ *
+ */
+static void adapter_tx_timeout(unsigned long data)
+{
+	struct cec_adapter *adapter = (struct cec_adapter *)data;
+	dev_err(&adapter->dev, "tx timeout\n");
+	__adapter_tx_done(adapter, false, CEC_TX_F_UNKNOWN_ERROR, 0);
+}
+
+/**
+ * cec_reset_device() - resets a cec adapter
+ * @adapter:	adapter pointer
+ *
+ * Resets a CEC device to a sane state
+ */
+int cec_reset_device(struct cec_adapter *adapter)
+{
+	int ret;
+
+	mutex_lock(&adapter->lock);
+	if (adapter->dead)
+		ret = -ENODEV;
+	else
+		ret = adapter->ops->reset(adapter);
+	mutex_unlock(&adapter->lock);
+	return ret;
+}
+
+/**
+ * cec_get_counters() - gets counters from a cec adapter
+ * @adapter:	adapter pointer
+ * @cnt:	struct cec_counters pointer
+ *
+ * Get counters from the CEC adapter if supported, adapter should advertise
+ * CEC_HW_HAS_COUNTERS flag
+ */
+int cec_get_counters(struct cec_adapter *adapter, struct cec_counters *cnt)
+{
+	int ret;
+
+	mutex_lock(&adapter->lock);
+	if (!(adapter->flags & CEC_HW_HAS_COUNTERS))
+		ret = -ENOTSUPP;
+	else if (adapter->dead)
+		ret = -ENODEV;
+	else
+		ret = adapter->ops->get_counters(adapter, cnt);
+	mutex_unlock(&adapter->lock);
+
+	return ret;
+}
+
+/**
+ * cec_set_detached_config() - send detached config to adapter
+ * @adapter:	adapter pointer
+ * @config:	config
+ *
+ */
+int cec_set_detached_config(struct cec_adapter *adapter,
+			    const struct cec_detached_config *config)
+{
+	int ret;
+
+	mutex_lock(&adapter->lock);
+	if (adapter->dead)
+		ret = -ENODEV;
+	else
+		ret = adapter->ops->set_detached_config(adapter, config);
+	mutex_unlock(&adapter->lock);
+
+	return ret;
+}
+
+/**
+ * cec_set_rx_mode() - sets the adapter receive mode
+ * @adapter:	adapter pointer
+ * @mode:	receive mode (accept all, unicast only)
+ *
+ * Set the receive mode filter of the adapter
+ */
+int cec_set_rx_mode(struct cec_adapter *adapter, enum cec_rx_mode mode)
+{
+	int ret;
+
+	if (~adapter->flags & CEC_HW_HAS_RX_FILTER)
+		return -ENOTSUPP;
+
+	if (mode >= CEC_RX_MODE_MAX)
+		return -EINVAL;
+
+	mutex_lock(&adapter->lock);
+	if (adapter->dead)
+		ret = -ENODEV;
+	else
+		ret = adapter->ops->set_rx_mode(adapter, mode);
+	mutex_unlock(&adapter->lock);
+
+	return ret;
+}
+
+/**
+ * cec_attach_host - attaches a host to the adapter
+ * @adapter:	adapter pointer
+ *
+ * Attaches the host to the adapter. In case the hardware is able
+ * to process CEC messages itself, it should now send them to the
+ * host for processing
+ */
+int cec_attach_host(struct cec_adapter *adapter)
+{
+	int ret = 0;
+
+	if (adapter->attached)
+		return -EBUSY;
+
+	mutex_lock(&adapter->lock);
+	if (adapter->dead)
+		ret = -ENODEV;
+	else {
+		if (adapter->ops->attach)
+			ret = adapter->ops->attach(adapter);
+		if (!ret)
+			adapter->attached = true;
+	}
+	mutex_unlock(&adapter->lock);
+	return ret;
+}
+
+/**
+ * cec_detach_host - detaches a host from the adapter
+ * @adapter:	adapter pointer
+ *
+ * Detaches the host from the adapter. In case the hardware is able
+ * to process CEC messages itself, it should now keep the messages for
+ * itself and no longer send them to the host
+ */
+int cec_detach_host(struct cec_adapter *adapter)
+{
+	int ret;
+
+	mutex_lock(&adapter->lock);
+	if (adapter->dead)
+		ret = -ENODEV;
+	else {
+		if (adapter->ops->detach(adapter))
+			adapter->ops->detach(adapter);
+		adapter->attached = false;
+	}
+	mutex_unlock(&adapter->lock);
+
+	return 0;
+}
+
+/**
+ * alloc_cec_adapter() - allocate a new cec adapter
+ * @priv_size:	sizeof of adapter private date
+ */
+struct cec_adapter *alloc_cec_adapter(size_t priv_size)
+{
+	size_t size;
+
+	size = sizeof (struct cec_adapter) + priv_size + CECDEV_PRIV_ALIGN;
+	return kzalloc(size, GFP_KERNEL);
+}
+EXPORT_SYMBOL(alloc_cec_adapter);
+
+/**
+ * cec_flush_queues() - flushes a cec adapter queues
+ * @adapter:	adapter pointer
+ */
+void cec_flush_queues(struct cec_adapter *adapter)
+{
+	struct cec_rx_kmsg *cur, *next;
+
+	spin_lock(&adapter->rx_msg_list_lock);
+
+	list_for_each_entry_safe(cur, next, &adapter->rx_msg_list, next)
+		kfree(cur);
+	INIT_LIST_HEAD(&adapter->rx_msg_list);
+	adapter->rx_msg_len = 0;
+
+	spin_unlock(&adapter->rx_msg_list_lock);
+}
+
+/*
+ * device refcounting
+ */
+int cec_get_adapter(struct cec_adapter *adapter)
+{
+	int ret;
+
+	mutex_lock(&adapter->lock);
+	ret = adapter->dead;
+	if (!ret)
+		atomic_inc(&adapter->users);
+	mutex_unlock(&adapter->lock);
+	return ret;
+}
+
+void cec_put_adapter(struct cec_adapter *adapter)
+{
+	if (atomic_dec_and_test(&adapter->users))
+		kfree(adapter);
+}
+
+/**
+ * free_cec_adapter() - free cec adapter
+ */
+void free_cec_adapter(struct cec_adapter *adapter)
+{
+	cec_put_adapter(adapter);
+}
+EXPORT_SYMBOL(free_cec_adapter);
+
+/*
+ * called by sysfs when all device references have been dropped
+ */
+static void cec_adapter_sysfs_release(struct device *dev)
+{
+	struct cec_adapter *adapter = to_cec_adapter(dev);
+	free_cec_adapter(adapter);
+}
+
+/*
+ * cec device sysfs class
+ */
+static struct class cec_class = {
+	.name		= "cec",
+	.dev_release	= cec_adapter_sysfs_release,
+};
+
+/**
+ * register_cec_adapter() - registers a new cec adapter
+ * @cec_adapter:	cec_adapter pointer
+ */
+int register_cec_adapter(struct cec_adapter *adapter)
+{
+	struct device *dev = &adapter->dev;
+	int ret;
+
+	memset(dev, 0, sizeof (*dev));
+
+	adapter->attached = false;
+	mutex_init(&adapter->lock);
+
+	adapter->tx_pending = 0;
+	init_waitqueue_head(&adapter->wait);
+
+	spin_lock_init(&adapter->rx_msg_list_lock);
+	INIT_LIST_HEAD(&adapter->rx_msg_list);
+	adapter->rx_msg_len = 0;
+
+	init_timer(&adapter->tx_timeout_timer);
+	adapter->tx_timeout_timer.function = adapter_tx_timeout;
+	adapter->tx_timeout_timer.data = (unsigned long)adapter;
+
+	snprintf(adapter->name, sizeof (adapter->name),
+		 "%s%d", adapter->driver_name,
+		 cec_adapter_count++);
+
+	/* create char device */
+	ret = cec_create_adapter_node(adapter);
+	if (ret < 0)
+		return ret;
+
+	/* register to sysfs */
+	dev_set_name(dev, adapter->name);
+	dev->class = &cec_class;
+
+	ret = device_register(dev);
+	if (ret < 0)
+		return ret;
+
+	/* 2 users, driver itself + sysfs */
+	atomic_set(&adapter->users, 2);
+	dev_info(dev, "registered cec adapter\n");
+	return 0;
+}
+EXPORT_SYMBOL(register_cec_adapter);
+
+/**
+ * unregister_cec_adapter() - unregisters a cec adapter
+ * @cec_adapter:	cec_adapter pointer
+ */
+void unregister_cec_adapter(struct cec_adapter *adapter)
+{
+	/* mark as dead */
+	mutex_lock(&adapter->lock);
+	adapter->dead = true;
+	mutex_unlock(&adapter->lock);
+
+	/* from this point, no adapter ops can be called again */
+
+	/* unregister char dev openers */
+	cec_remove_adapter_node(adapter);
+
+	del_timer_sync(&adapter->tx_timeout_timer);
+
+	/* wake up any sleeper */
+	adapter->last_tx_success = false;
+	adapter->last_tx_flags = 0;
+	adapter->tx_pending = 0;
+	wake_up_all(&adapter->wait);
+
+	cec_detach_host(adapter);
+	cec_flush_queues(adapter);
+	/* let sysfs release the device */
+	dev_info(&adapter->dev, "unregistering cec adapter\n");
+	device_unregister(&adapter->dev);
+}
+
+EXPORT_SYMBOL(unregister_cec_adapter);
+
+static int __init cec_init(void)
+{
+	int ret;
+
+	ret = class_register(&cec_class);
+	if (ret) {
+		pr_err("failed to create cec device class\n");
+		return ret;
+	}
+
+	ret = cec_cdev_init();
+	if (ret) {
+		pr_err("failed to create devices\n");
+		goto failed_class;
+	}
+
+	return 0;
+
+failed_class:
+	class_unregister(&cec_class);
+	return 1;
+}
+
+static void __exit cec_exit(void)
+{
+	cec_cdev_exit();
+	class_unregister(&cec_class);
+}
+
+module_init(cec_init);
+module_exit(cec_exit);
+
+MODULE_AUTHOR("Florian Fainelli <ffainelli@freebox.fr>");
+MODULE_DESCRIPTION("HDMI CEC core driver");
+MODULE_LICENSE("GPL");
diff -Nruw linux-4.2-fbx/drivers/misc/hdmi-cec./dev.c linux-4.2-fbx/drivers/misc/hdmi-cec/dev.c
--- linux-4.2-fbx/drivers/misc/hdmi-cec./dev.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/misc/hdmi-cec/dev.c	2013-12-04 14:33:19.703478985 +0100
@@ -0,0 +1,293 @@
+/*
+ * HDMI CEC character device code
+ *
+ * Copyright (C), 2011 Florian Fainelli <ffainelli@freebox.fr>
+ *
+ * This file is subject to the GPLv2 licensing terms
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/cdev.h>
+#include <linux/uaccess.h>
+#include <linux/spinlock.h>
+#include <linux/ioctl.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+
+#include <linux/hdmi-cec/hdmi-cec.h>
+#include <linux/hdmi-cec/dev.h>
+
+#include "hdmi-cec-priv.h"
+
+static int cec_major;
+
+static DEFINE_MUTEX(cec_minors_lock);
+static bool cec_minors[256];
+
+static int cec_dev_open(struct inode *i, struct file *f)
+{
+	struct cdev *cdev = i->i_cdev;
+	struct cec_adapter *adapter =
+			container_of(cdev, struct cec_adapter, cdev);
+
+	if (f->private_data)
+		return -EBUSY;
+
+	if (cec_get_adapter(adapter))
+		return -ENODEV;
+
+	f->private_data = adapter;
+	return cec_attach_host(adapter);
+}
+
+static int cec_dev_close(struct inode *i, struct file *f)
+{
+	struct cec_adapter *adapter = f->private_data;
+
+	cec_detach_host(adapter);
+	cec_flush_queues(adapter);
+	f->private_data = NULL;
+	cec_put_adapter(adapter);
+	return 0;
+}
+
+static int wait_tx_done(struct cec_adapter *adapter)
+{
+	int ret;
+
+	ret = wait_event_interruptible(adapter->wait,
+				       !test_bit(0, &adapter->tx_pending) ||
+				       adapter->dead);
+	if (ret)
+		return ret;
+
+	if (adapter->dead)
+		return -ENODEV;
+
+	return 0;
+}
+
+static long cec_dev_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+{
+	struct cec_adapter *adapter;
+	void __user *argp = (void __user *)arg;
+	int __user *p = argp;
+	int val, ret;
+	struct cec_counters cnt;
+	struct cec_tx_status tx_status;
+	struct cec_detached_config config;
+
+	if (!f->private_data)
+		return -EINVAL;
+
+	adapter = f->private_data;
+
+	ret = -ENOTTY;
+	switch (cmd) {
+	case CEC_SET_LOGICAL_ADDRESS:
+		if (get_user(val, p))
+			return -EFAULT;
+
+		ret = cec_set_logical_address(adapter, (u8)val);
+		break;
+
+	case CEC_RESET_DEVICE:
+		ret = cec_reset_device(adapter);
+		break;
+
+	case CEC_GET_COUNTERS:
+		memset(&cnt, 0, sizeof(cnt));
+
+		ret = cec_get_counters(adapter, &cnt);
+		if (ret)
+			return ret;
+
+		if (copy_to_user(argp, &cnt, sizeof(cnt)))
+			return -EFAULT;
+		break;
+
+	case CEC_GET_TX_STATUS:
+		tx_status.sent = !test_bit(0, &adapter->tx_pending);
+		tx_status.success = adapter->last_tx_success;
+		tx_status.flags = adapter->last_tx_flags;
+		tx_status.tries = adapter->last_tx_tries;
+
+		if (copy_to_user(argp, &tx_status, sizeof(tx_status)))
+			return -EFAULT;
+
+		ret = 0;
+		break;
+
+	case CEC_SET_RX_MODE:
+		if (get_user(val, p))
+			return -EFAULT;
+
+		ret = cec_set_rx_mode(adapter, (enum cec_rx_mode)val);
+		break;
+
+	case CEC_SET_DETACHED_CONFIG:
+		if (copy_from_user(&config, argp, sizeof (config)))
+			return -EFAULT;
+
+		ret = cec_set_detached_config(adapter, &config);
+		break;
+
+	default:
+		dev_err(&adapter->dev, "unsupported ioctl: %08x\n", cmd);
+		break;
+	}
+
+	return ret;
+}
+
+static int cec_dev_write(struct file *f, const char __user *buf,
+			size_t count, loff_t *pos)
+{
+	struct cec_adapter *adapter = f->private_data;
+	struct cec_tx_msg msg;
+	int ret;
+
+	if (count != sizeof (struct cec_tx_msg))
+		return -EINVAL;
+
+	if (copy_from_user(&msg, buf, sizeof (msg)))
+		return -EFAULT;
+
+	ret = cec_send_message(adapter, &msg);
+	if (ret)
+		return ret;
+
+	if (!(f->f_flags & O_NONBLOCK)) {
+		ret = wait_tx_done(adapter);
+		if (ret)
+			return ret;
+	}
+
+	/* update status */
+	msg.success = adapter->last_tx_success;
+	msg.flags = adapter->last_tx_flags;
+	msg.tries = adapter->last_tx_tries;
+
+	if (copy_to_user((char __user *)buf, &msg, sizeof (msg)))
+		return -EFAULT;
+
+	return count;
+}
+
+static int cec_dev_read(struct file *f, char __user *buf,
+			size_t count, loff_t *pos)
+{
+	struct cec_adapter *adapter = f->private_data;
+	int ret;
+	struct cec_rx_msg msg;
+
+	if (count != sizeof (struct cec_rx_msg))
+		return -EINVAL;
+
+	ret = cec_read_message(adapter, &msg, f->f_flags & O_NONBLOCK);
+	if (ret)
+		return ret;
+
+	if (copy_to_user(buf, &msg, sizeof (msg)))
+		return -EFAULT;
+
+	return sizeof (msg);
+}
+
+static unsigned int cec_dev_poll(struct file *f, poll_table *wait)
+{
+	struct cec_adapter *adapter = f->private_data;
+	unsigned int flags;
+
+	if (adapter->dead)
+		return POLLERR | POLLHUP;
+
+	poll_wait(f, &adapter->wait, wait);
+
+	flags = 0;
+	if (__cec_rx_queue_len(adapter))
+		flags |= POLLIN;
+
+	if (!test_bit(0, &adapter->tx_pending))
+		flags |= POLLOUT;
+
+	return flags;
+}
+
+static const struct file_operations cec_adapter_fops = {
+	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
+	.open		= cec_dev_open,
+	.release	= cec_dev_close,
+	.unlocked_ioctl	= cec_dev_ioctl,
+	.read		= cec_dev_read,
+	.write		= cec_dev_write,
+	.poll		= cec_dev_poll,
+};
+
+int cec_create_adapter_node(struct cec_adapter *adapter)
+{
+	size_t i;
+	dev_t devno;
+	int ret;
+
+	cdev_init(&adapter->cdev, &cec_adapter_fops);
+	adapter->cdev.owner = THIS_MODULE;
+
+	/* allocate minor */
+	mutex_lock(&cec_minors_lock);
+	for (i = 0; i < ARRAY_SIZE(cec_minors); i++) {
+		if (!cec_minors[i])
+			break;
+	}
+	mutex_unlock(&cec_minors_lock);
+
+	if (i == ARRAY_SIZE(cec_minors)) {
+		dev_err(&adapter->dev, "no minor available\n");
+		return 1;
+	}
+
+	devno = MKDEV(cec_major, i);
+	ret = cdev_add(&adapter->cdev, devno, 1);
+	if (ret) {
+		dev_err(&adapter->dev, "failed to add char device\n");
+		return ret;
+	}
+
+	adapter->dev.devt = devno;
+	return 0;
+}
+
+void cec_remove_adapter_node(struct cec_adapter *adapter)
+{
+	mutex_lock(&cec_minors_lock);
+	cec_minors[MINOR(adapter->cdev.dev)] = false;
+	mutex_unlock(&cec_minors_lock);
+	cdev_del(&adapter->cdev);
+}
+
+int __init cec_cdev_init(void)
+{
+	dev_t dev = 0;
+	int ret;
+
+	ret = alloc_chrdev_region(&dev, 0, CEC_MAX_DEVS, "cec");
+	if (ret < 0) {
+		printk(KERN_ERR "alloc_chrdev_region() failed for cec\n");
+		goto out;
+	}
+
+	cec_major = MAJOR(dev);
+	return 0;
+
+out:
+	unregister_chrdev_region(MKDEV(cec_major, 0), CEC_MAX_DEVS);
+	return ret;
+}
+
+void __exit cec_cdev_exit(void)
+{
+	unregister_chrdev_region(MKDEV(cec_major, 0), CEC_MAX_DEVS);
+}
+
diff -Nruw linux-4.2-fbx/drivers/misc/hdmi-cec./hdmi-cec-priv.h linux-4.2-fbx/drivers/misc/hdmi-cec/hdmi-cec-priv.h
--- linux-4.2-fbx/drivers/misc/hdmi-cec./hdmi-cec-priv.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/misc/hdmi-cec/hdmi-cec-priv.h	2013-12-04 14:33:19.703478985 +0100
@@ -0,0 +1,34 @@
+#ifndef __HDMI_CEC_PRIV_H
+#define __HDMI_CEC_PRIV_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+/**
+ * struct cec_rx_kmsg - kernel-side cec message cookie
+ * @msg:	user-side cec message cookie
+ * @next:	list pointer to next message
+ */
+struct cec_rx_kmsg {
+	struct cec_rx_msg	msg;
+	struct list_head	next;
+};
+
+int cec_get_adapter(struct cec_adapter *);
+void cec_put_adapter(struct cec_adapter *);
+int cec_read_message(struct cec_adapter *, struct cec_rx_msg *msg,
+		     bool non_block);
+int cec_send_message(struct cec_adapter *, struct cec_tx_msg *msg);
+int cec_reset_device(struct cec_adapter *);
+int cec_get_counters(struct cec_adapter *, struct cec_counters *cnt);
+int cec_set_logical_address(struct cec_adapter *, const u8 addr);
+int cec_set_rx_mode(struct cec_adapter *, enum cec_rx_mode mode);
+void cec_flush_queues(struct cec_adapter *);
+unsigned __cec_rx_queue_len(struct cec_adapter *);
+int cec_attach_host(struct cec_adapter *);
+int cec_detach_host(struct cec_adapter *);
+int cec_set_detached_config(struct cec_adapter *,
+			    const struct cec_detached_config *);
+
+#endif /* __HDMI_CEC_PRIV_H */
+
diff -Nruw linux-4.2-fbx/drivers/misc/hdmi-cec./Kconfig linux-4.2-fbx/drivers/misc/hdmi-cec/Kconfig
--- linux-4.2-fbx/drivers/misc/hdmi-cec./Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/misc/hdmi-cec/Kconfig	2013-12-04 14:33:19.703478985 +0100
@@ -0,0 +1,15 @@
+menu "HDMI CEC support"
+
+config HDMI_CEC
+	tristate "HDMI CEC (Consumer Electronics Control) support"
+	---help---
+	   HDMI Consumer Electronics Control support.
+
+config HDMI_CEC_REMOTI
+	tristate "RemoTI CEC driver"
+	depends on HDMI_CEC
+	select REMOTI
+	---help---
+	   HDMI CEC driver using RemoTI IPCs.
+
+endmenu
diff -Nruw linux-4.2-fbx/drivers/misc/hdmi-cec./Makefile linux-4.2-fbx/drivers/misc/hdmi-cec/Makefile
--- linux-4.2-fbx/drivers/misc/hdmi-cec./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/misc/hdmi-cec/Makefile	2013-12-04 14:33:19.703478985 +0100
@@ -0,0 +1,6 @@
+obj-$(CONFIG_HDMI_CEC)		+= hdmi-cec.o
+hdmi-cec-objs			+= core.o dev.o
+
+# drivers
+obj-$(CONFIG_HDMI_CEC_REMOTI)	+= remoti-cec.o
+remoti-cec-objs			:= remoti.o
diff -Nruw linux-4.2-fbx/drivers/misc/hdmi-cec./remoti.c linux-4.2-fbx/drivers/misc/hdmi-cec/remoti.c
--- linux-4.2-fbx/drivers/misc/hdmi-cec./remoti.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/misc/hdmi-cec/remoti.c	2013-12-04 14:33:19.703478985 +0100
@@ -0,0 +1,637 @@
+/*
+ * HDMI CEC driver using RemoTI IPCs
+ *
+ * Copyright (C) Florian Fainelli <ffainelli@freebox.fr>
+ *
+ * This file is subject to the GPLv2 licensing terms
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/remoti/remoti.h>
+#include <linux/of.h>
+
+#include <linux/hdmi-cec/hdmi-cec.h>
+
+/* HDMI CEC command (util subsystem) */
+#define RTI_CEC_SET_LADDR		0x20
+#define RTI_CEC_GET_CNT			0x21
+#define RTI_CEC_RST			0x22
+#define RTI_CEC_MODE			0x23
+#define RTI_CEC_ATTACH			0x24
+#define RTI_CEC_DETACH			0x25
+#define RTI_CEC_RECV_MSG_IND		0x26
+
+#define RTI_CEC_SEND_MSG_REQ		0x28
+#define RTI_CEC_SEND_MSG_CNF		0x29
+
+#define RTI_CEC_RECV_RAW_IND		0x2a
+#define RTI_CEC_SET_DETACHED_CONFIG	0x2b
+
+
+/*
+ * Exposed return status codes
+ */
+enum {
+	RTI_CEC_SUCCESS = 0,
+	RTI_CEC_INVALID,
+	RTI_CEC_TX_BUSY,
+	RTI_CEC_TX_FAIL,
+};
+
+/*
+ * Exposed modes
+ */
+enum {
+	RTI_CEC_MODE_DISABLED = 0,
+	RTI_CEC_MODE_NORMAL,
+	RTI_CEC_MODE_RAW,
+};
+
+/*
+ * rx filtering (normal mode)
+ */
+enum {
+	RTI_CEC_RX_FILTER_DEFAULT = 0,
+	RTI_CEC_RX_FILTER_PROMISC,
+};
+
+/*
+ * RTI data for rx message
+ *
+ * we send this as-is to host (no memcpy to create a message) so don't
+ * change field order
+ */
+enum rti_cec_rx_msg_flags {
+	/* global valid bit for all message (got eom & ack) */
+	RTI_CEC_RX_FLAG_VALID		= (1 << 0),
+
+	/* true if this is a complete message (else its truncated) */
+	RTI_CEC_RX_FLAG_GOT_EOM		= (1 << 1),
+
+	/* true if the message has been acked */
+	RTI_CEC_RX_FLAG_ACKED		= (1 << 2),
+};
+
+struct rti_cec_rx_msg {
+	/* bitmask of rti_cec_rx_msg_flags */
+	uint8_t	flags;
+
+	/* number of bits in data */
+	uint8_t	len;
+
+	/* all message data (no eom/ack bit here), we only send "len"
+	 * bytes of this array */
+	uint8_t	data[16];
+};
+
+#define RTI_CEC_RX_MSG_CONSTANT_LEN         \
+		offsetof(struct rti_cec_rx_msg, data)
+
+
+/*
+ * RTI data for tx completion
+ */
+enum rti_cec_tx_flags  {
+	/*
+	 * message was nacked at some point
+	 */
+	RTI_CEC_TX_F_NACK		= (1 << 0),
+
+	/*
+	 * abort sending because total time to send was elapsed
+	 */
+	RTI_CEC_TX_F_TIMEOUT		= (1 << 1),
+
+	/*
+	 * abort sending because maximum number of retry has passed
+	 */
+	RTI_CEC_TX_F_MAX_RETRIES	= (1 << 2),
+
+	/*
+	 * abort sending because of arbitration loss
+	 */
+	RTI_CEC_TX_F_ARBITRATION_LOST	= (1 << 3),
+
+	/*
+	 * abort sending because we failed to respect timings
+	 */
+	RTI_CEC_TX_F_MISSED_DEADLINE	= (1 << 4),
+};
+
+struct rti_cec_tx_status {
+	uint8_t	status;
+
+	uint8_t	flags;
+
+	/* number of tx tries we did (0 = no try done because of busy
+	 * bus) */
+	uint8_t	tries;
+};
+
+
+static inline int remoti_cec_map_error(const u8 ret)
+{
+	switch (ret) {
+	case RTI_CEC_SUCCESS:
+		return 0;
+	default:
+		return -EINVAL;
+	case RTI_CEC_TX_BUSY:
+		return -EBUSY;
+	case RTI_CEC_TX_FAIL:
+		return -EIO;
+	}
+}
+
+static DEFINE_MUTEX(remoti_cec_list_mutex);
+static struct list_head remoti_cec_list;
+
+/*
+ * Driver private context
+ */
+struct remoti_cec_priv {
+	struct platform_device	*pdev;
+	unsigned int		rti_dev_id;
+
+	struct rti_udev		*udev;
+	struct cec_adapter	*adapter;
+	struct list_head	next;
+};
+
+struct remoti_cec_adapter_priv {
+	struct remoti_cec_priv	*priv;
+};
+
+static int remoti_cec_send(struct cec_adapter *adapter,
+			   u16 expire_ms,
+			   const u8 *data,
+			   const u8 len)
+{
+	struct remoti_cec_adapter_priv *apriv = cec_adapter_priv(adapter);
+	struct remoti_cec_priv *priv = apriv->priv;
+	struct rti_msg msg;
+	int ret;
+
+	memset(&msg, 0, sizeof (msg));
+	msg.type = NPI_SREQ;
+	msg.subsys = NPI_SYS_UTIL;
+	msg.cmd = RTI_CEC_SEND_MSG_REQ;
+
+	msg.data[0] = expire_ms & 0xff;
+	msg.data[1] = (expire_ms >> 8) & 0xff;
+	memcpy(msg.data + 2, data, len);
+	msg.data_len = len + 2;
+
+	ret = rti_send_sync_msg(priv->udev, &msg);
+	if (ret)
+		return ret;
+
+	if (msg.reply_len != 1)
+		return -EIO;
+
+	if (msg.reply[0] != RTI_CEC_SUCCESS)
+		return remoti_cec_map_error(msg.reply[0]);
+
+	return 0;
+}
+
+
+static int remoti_cec_set_logical_address(struct cec_adapter *adapter,
+					  const u8 logical_address)
+{
+	struct remoti_cec_adapter_priv *apriv = cec_adapter_priv(adapter);
+	struct remoti_cec_priv *priv = apriv->priv;
+	struct rti_msg msg;
+	int ret;
+
+	memset(&msg, 0, sizeof (msg));
+	msg.type = NPI_SREQ;
+	msg.subsys = NPI_SYS_UTIL;
+	msg.cmd = RTI_CEC_SET_LADDR;
+
+	memcpy(msg.data, &logical_address, 1);
+	msg.data_len = sizeof (logical_address);
+
+	ret = rti_send_sync_msg(priv->udev, &msg);
+	if (ret)
+		return ret;
+
+	if (msg.reply_len != 1)
+		return -EIO;
+
+	return remoti_cec_map_error(msg.reply[0]);
+}
+
+static int remoti_cec_get_counters(struct cec_adapter *adapter,
+				   struct cec_counters *cnt)
+{
+	struct remoti_cec_adapter_priv *apriv = cec_adapter_priv(adapter);
+	struct remoti_cec_priv *priv = apriv->priv;
+	struct rti_msg msg;
+	int ret;
+
+	memset(&msg, 0, sizeof (msg));
+	msg.type = NPI_SREQ;
+	msg.subsys = NPI_SYS_UTIL;
+	msg.cmd = RTI_CEC_GET_CNT;
+
+	ret = rti_send_sync_msg(priv->udev, &msg);
+	if (ret)
+		return ret;
+
+	if (msg.reply_len != sizeof (*cnt)) {
+		printk(KERN_ERR "invalid cec counters size\n");
+		return -EIO;
+	}
+
+	memcpy(cnt, msg.reply, msg.reply_len);
+	return 0;
+}
+
+static int remoti_cec_reset(struct cec_adapter *adapter)
+{
+	struct remoti_cec_adapter_priv *apriv = cec_adapter_priv(adapter);
+	struct remoti_cec_priv *priv = apriv->priv;
+	struct rti_msg msg;
+
+	memset(&msg, 0, sizeof (msg));
+	msg.type = NPI_SREQ;
+	msg.subsys = NPI_SYS_UTIL;
+	msg.cmd = RTI_CEC_RST;
+
+	return rti_send_sync_msg(priv->udev, &msg);
+}
+
+static int remoti_cec_set_detached_config(struct cec_adapter *adapter,
+					  const struct cec_detached_config *cfg)
+{
+	struct remoti_cec_adapter_priv *apriv = cec_adapter_priv(adapter);
+	struct remoti_cec_priv *priv = apriv->priv;
+	struct rti_msg msg;
+
+	memset(&msg, 0, sizeof (msg));
+	msg.type = NPI_SREQ;
+	msg.subsys = NPI_SYS_UTIL;
+	msg.cmd = RTI_CEC_SET_DETACHED_CONFIG;
+
+	msg.data_len = 4;
+	msg.data[0] = cfg->phys_addr_valid ? 1 : 0;
+	msg.data[1] = cfg->phys_addr[0];
+	msg.data[2] = cfg->phys_addr[1];
+	msg.data[3] = cfg->flags;
+
+	return rti_send_sync_msg(priv->udev, &msg);
+}
+
+static int remoti_cec_set_rx_mode(struct cec_adapter *adapter,
+				  enum cec_rx_mode rx_mode)
+{
+	struct remoti_cec_adapter_priv *apriv = cec_adapter_priv(adapter);
+	struct remoti_cec_priv *priv = apriv->priv;
+	struct rti_msg msg;
+	int ret;
+
+	memset(&msg, 0, sizeof (msg));
+	msg.type = NPI_SREQ;
+	msg.subsys = NPI_SYS_UTIL;
+	msg.cmd = RTI_CEC_MODE;
+
+	msg.data_len = 2;
+	if (rx_mode == CEC_RX_MODE_DISABLED)
+		msg.data[0] = RTI_CEC_MODE_DISABLED;
+	else {
+		msg.data[0] = RTI_CEC_MODE_NORMAL;
+		if (rx_mode == CEC_RX_MODE_ACCEPT_ALL)
+			msg.data[1] = RTI_CEC_RX_FILTER_PROMISC;
+		else
+			msg.data[1] = RTI_CEC_RX_FILTER_DEFAULT;
+	}
+
+	ret = rti_send_sync_msg(priv->udev, &msg);
+	if (ret)
+		return ret;
+
+	if (msg.reply_len != 1)
+		return -EIO;
+
+	return remoti_cec_map_error(msg.reply[0]);
+}
+
+static int remoti_cec_attach(struct cec_adapter *adapter)
+{
+	struct remoti_cec_adapter_priv *apriv = cec_adapter_priv(adapter);
+	struct remoti_cec_priv *priv = apriv->priv;
+	struct rti_msg msg;
+	int ret;
+
+	memset(&msg, 0, sizeof (msg));
+	msg.type = NPI_SREQ;
+	msg.subsys = NPI_SYS_UTIL;
+	msg.cmd = RTI_CEC_ATTACH;
+
+	ret = rti_send_sync_msg(priv->udev, &msg);
+	if (ret)
+		return ret;
+
+	if (msg.reply_len != 1)
+		return -EIO;
+
+	return remoti_cec_map_error(msg.reply[0]);
+}
+
+static int remoti_cec_detach(struct cec_adapter *adapter)
+{
+	struct remoti_cec_adapter_priv *apriv = cec_adapter_priv(adapter);
+	struct remoti_cec_priv *priv = apriv->priv;
+	struct rti_msg msg;
+	int ret;
+
+	memset(&msg, 0, sizeof (msg));
+	msg.type = NPI_SREQ;
+	msg.subsys = NPI_SYS_UTIL;
+	msg.cmd = RTI_CEC_DETACH;
+
+	ret = rti_send_sync_msg(priv->udev, &msg);
+	if (ret)
+		return ret;
+
+	if (msg.reply_len != 1)
+		return -EIO;
+
+	return remoti_cec_map_error(msg.reply[0]);
+}
+
+static void remoti_cec_recv_ind(void *cb_data,
+				const struct rti_msg *msg)
+{
+	struct remoti_cec_priv *priv = (struct remoti_cec_priv *)cb_data;
+	const struct rti_cec_rx_msg *rti_rx_msg;
+	u8 rx_flags;
+
+	if (msg->data_len < RTI_CEC_RX_MSG_CONSTANT_LEN) {
+		printk(KERN_ERR "invalid recv message size\n");
+		return;
+	}
+
+	rti_rx_msg = (const struct rti_cec_rx_msg *)msg->data;
+
+	/* ignore message with non full bytes */
+	if (rti_rx_msg->len % 8)
+		return;
+
+	/* send message to upper layers */
+	rx_flags = 0;
+	if (rti_rx_msg->flags & RTI_CEC_RX_FLAG_ACKED)
+		rx_flags |= CEC_RX_F_ACKED;
+	if (rti_rx_msg->flags & RTI_CEC_RX_FLAG_GOT_EOM)
+		rx_flags |= CEC_RX_F_COMPLETE;
+
+	adapter_rx_done(priv->adapter,
+			rti_rx_msg->data,
+			rti_rx_msg->len / 8,
+			rti_rx_msg->flags & RTI_CEC_RX_FLAG_VALID,
+			rx_flags);
+}
+
+static void remoti_cec_send_cnf(void *cb_data,
+				const struct rti_msg *msg)
+{
+	struct remoti_cec_priv *priv = (struct remoti_cec_priv *)cb_data;
+	const struct rti_cec_tx_status *rti_tx_status;
+	bool tx_success;
+	u8 tx_flags, tx_tries;
+
+	if (msg->data_len < sizeof (*rti_tx_status)) {
+		printk(KERN_ERR "bad completion status\n");
+		tx_success = false;
+		tx_flags = CEC_TX_F_UNKNOWN_ERROR;
+		tx_tries = 0;
+	} else {
+		rti_tx_status = (const struct rti_cec_tx_status *)msg->data;
+		tx_success = (rti_tx_status->status == RTI_CEC_SUCCESS);
+		tx_flags = 0;
+		if (rti_tx_status->flags & RTI_CEC_TX_F_NACK)
+			tx_flags |= CEC_TX_F_NACK;
+		if (rti_tx_status->flags & RTI_CEC_TX_F_TIMEOUT)
+			tx_flags |= CEC_TX_F_TIMEOUT;
+		if (rti_tx_status->flags & RTI_CEC_TX_F_MAX_RETRIES)
+			tx_flags |= CEC_TX_F_MAX_RETRIES;
+		if (rti_tx_status->flags & RTI_CEC_TX_F_ARBITRATION_LOST)
+			tx_flags |= CEC_TX_F_ARBITRATION_LOST;
+		if (rti_tx_status->flags & RTI_CEC_TX_F_MISSED_DEADLINE)
+			tx_flags |= CEC_TX_F_UNKNOWN_ERROR;
+		tx_tries = rti_tx_status->tries;
+	}
+	adapter_tx_done(priv->adapter, tx_success, tx_flags, tx_tries);
+}
+
+static const struct rti_kcallback callbacks[] = {
+	{
+		.subsys		= NPI_SYS_UTIL,
+		.cmd		= RTI_CEC_RECV_MSG_IND,
+		.cb		= remoti_cec_recv_ind,
+	},
+
+	{
+		.subsys		= NPI_SYS_UTIL,
+		.cmd		= RTI_CEC_SEND_MSG_CNF,
+		.cb		= remoti_cec_send_cnf,
+	},
+};
+
+static const struct cec_adapter_ops remoti_cec_ops = {
+	.set_logical_address	= remoti_cec_set_logical_address,
+	.send			= remoti_cec_send,
+	.reset			= remoti_cec_reset,
+	.get_counters		= remoti_cec_get_counters,
+	.set_rx_mode		= remoti_cec_set_rx_mode,
+	.attach			= remoti_cec_attach,
+	.detach			= remoti_cec_detach,
+	.set_detached_config	= remoti_cec_set_detached_config,
+};
+
+static int try_register_cec_adapter(struct remoti_cec_priv *priv)
+{
+	struct cec_adapter *adapter;
+	struct remoti_cec_adapter_priv *apriv;
+	int ret;
+
+	BUG_ON(priv->udev);
+
+	priv->udev = rti_get_udevice(priv->rti_dev_id);
+	if (!priv->udev)
+		return 0;
+
+	adapter = alloc_cec_adapter(sizeof (*apriv));
+	if (!adapter) {
+		dev_err(&priv->pdev->dev, "failed to allocate memory\n");
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	/* setup adapter */
+	adapter->driver_name = "remoti-cec";
+	adapter->ops = &remoti_cec_ops;
+	adapter->module = THIS_MODULE;
+	adapter->flags = CEC_HW_HAS_COUNTERS | CEC_HW_HAS_RX_FILTER;
+
+	/* setup adapter private data */
+	apriv = cec_adapter_priv(adapter);
+	apriv->priv = priv;
+
+	ret = register_cec_adapter(adapter);
+	if (ret) {
+		dev_err(&priv->pdev->dev, "unable to register cec adapter\n");
+		goto fail_free;
+	}
+
+	priv->adapter = adapter;
+
+	ret = rti_register_cmds_callback(priv->udev,
+					 callbacks, ARRAY_SIZE(callbacks),
+					 priv);
+	if (ret) {
+		dev_err(&priv->pdev->dev, "unable to register rti callback\n");
+		goto fail_unregister;
+	}
+
+	return 0;
+
+fail_unregister:
+	unregister_cec_adapter(adapter);
+
+fail_free:
+	free_cec_adapter(adapter);
+	priv->adapter = NULL;
+
+fail:
+	rti_release_udevice(priv->udev);
+	priv->udev = NULL;
+	return ret;
+}
+
+static int rti_udev_notifier_cb(struct notifier_block *n,
+				unsigned long id, void *data)
+{
+	struct remoti_cec_priv *priv;
+	enum rti_udev_state *st = (enum rti_udev_state *)data;
+
+	mutex_lock(&remoti_cec_list_mutex);
+
+	list_for_each_entry(priv, &remoti_cec_list, next) {
+
+		if (priv->rti_dev_id != id)
+			continue;
+
+		switch (*st) {
+		case RTI_UDEV_UP:
+			if (priv->udev)
+				continue;
+
+			try_register_cec_adapter(priv);
+			break;
+
+		case RTI_UDEV_GOING_DOWN:
+			if (!priv->udev)
+				continue;
+
+			unregister_cec_adapter(priv->adapter);
+			free_cec_adapter(priv->adapter);
+			rti_release_udevice(priv->udev);
+			priv->udev = NULL;
+			break;
+		}
+	}
+
+	mutex_unlock(&remoti_cec_list_mutex);
+	return 0;
+}
+
+static struct notifier_block rti_udev_notifier_block = {
+	.notifier_call = rti_udev_notifier_cb,
+};
+
+
+static int remoti_cec_probe(struct platform_device *pdev)
+{
+	struct remoti_cec_priv *priv;
+
+	priv = kzalloc(sizeof (*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(&pdev->dev, "failed to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	priv->pdev = pdev;
+	platform_set_drvdata(pdev, priv);
+
+	mutex_lock(&remoti_cec_list_mutex);
+	try_register_cec_adapter(priv);
+	list_add_tail(&priv->next, &remoti_cec_list);
+	mutex_unlock(&remoti_cec_list_mutex);
+	return 0;
+}
+
+static int remoti_cec_remove(struct platform_device *pdev)
+{
+	struct remoti_cec_priv *priv = platform_get_drvdata(pdev);
+
+	mutex_lock(&remoti_cec_list_mutex);
+	if (priv->udev) {
+		rti_unregister_cmds_callback(priv->udev,
+					     callbacks, ARRAY_SIZE(callbacks));
+		unregister_cec_adapter(priv->adapter);
+		free_cec_adapter(priv->adapter);
+		rti_release_udevice(priv->udev);
+	}
+	mutex_unlock(&remoti_cec_list_mutex);
+	kfree(priv);
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+static struct of_device_id remoti_cec_of_ids[] = {
+	{ .compatible = "ti,remoti-cec" },
+	{ /* sentinel*/ },
+};
+MODULE_DEVICE_TABLE(of, remoti_cec_of_ids);
+
+static struct platform_driver remoti_cec_driver = {
+	.driver	= {
+		.name	= "remoti-cec",
+		.owner	= THIS_MODULE,
+		.of_match_table = remoti_cec_of_ids,
+	},
+	.probe	= remoti_cec_probe,
+	.remove	= remoti_cec_remove,
+};
+
+static int __init remoti_cec_init(void)
+{
+	int ret;
+
+	INIT_LIST_HEAD(&remoti_cec_list);
+
+	ret = platform_driver_register(&remoti_cec_driver);
+	if (ret)
+		return ret;
+
+	rti_register_udevice_notifier(&rti_udev_notifier_block);
+	return 0;
+}
+
+static void __exit remoti_cec_exit(void)
+{
+	rti_unregister_udevice_notifier(&rti_udev_notifier_block);
+	platform_driver_unregister(&remoti_cec_driver);
+}
+
+module_init(remoti_cec_init);
+module_exit(remoti_cec_exit);
+
+MODULE_AUTHOR("Florian Fainelli <ffainelli@freebox.fr>");
+MODULE_DESCRIPTION("CEC transport over RemoTI");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:remoti-cec");
--- /dev/null	2015-07-31 18:17:35.952031993 +0200
+++ linux-4.2-fbx/drivers/misc/pic16-pmu.c	2015-09-15 19:18:37.926454663 +0200
@@ -0,0 +1,700 @@
+/*
+ * PIC16F72x PMU / LED / button driver
+ *
+ * Copyright (C) 2010, Florian Fainelli <ffainelli@freebox.fr>
+ *
+ * This file is subject to the GPLv2 licensing terms
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <linux/sysfs.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/input-polldev.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+
+#define PIC16_PMU_LED_COUNT		3
+#define PIC16_PMU_PWR_COUNT		3
+#define PIC16_PMU_BTN_COUNT		3
+#define PIC16_PMU_RST_COUNT		1
+
+/*
+ * Per LED private structure
+ */
+struct pic16_pmu_led_data {
+	u8 id;
+	u8 status:1;
+	u8 blink:1;
+	struct led_classdev ldev;
+	struct i2c_client *client;
+	struct work_struct work;
+};
+
+struct pic16_pmu_input_data {
+	struct i2c_client *client;
+	struct input_polled_dev	*poll_dev;
+	unsigned short keymap[PIC16_PMU_BTN_COUNT];
+};
+
+static unsigned short default_map[PIC16_PMU_BTN_COUNT] = {
+	BTN_0,
+	BTN_1,
+	BTN_2,
+};
+
+/*
+ * Global device structure
+ */
+struct pic16_pmu_data {
+	struct device *hwmon_dev;
+	struct attribute_group attrs;
+	struct mutex lock;
+	unsigned long last_updated;
+	struct i2c_client *client;
+	struct pic16_pmu_led_data leds[PIC16_PMU_LED_COUNT];
+	struct pic16_pmu_input_data btns;
+	u8 model;
+	u8 revision;
+	u8 power;
+	u8 buttons;
+	u8 resets;
+	u8 hw_revision;
+	struct gpio_chip chip;
+};
+
+static const unsigned short normal_i2c[] = { 0x60, I2C_CLIENT_END };
+
+static const struct i2c_device_id pic16_pmu_idtable[] = {
+	{ "pic16-pmu", 0 },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c, pic16_pmu_idtable);
+
+/*
+ * device registers
+ */
+#define PIC16_PMU_REG_DEV	0x00
+#define  PIC16_PMU_16F722	0x22
+
+#define PIC16_PMU_REG_REV	0x01
+#define PIC16_PMU_REG_LED	0x02
+#define PIC16_PMU_REG_PWR	0x03
+#define  PIC16_PMU_REG_PWR_MSK	0x1f
+#define PIC16_PMU_REG_BTN	0x04
+#define PIC16_PMU_REG_RST	0x05
+#define  PIC16_PMU_REG_RST_MSK	0x05
+#define PIC16_PMU_REG_CTL	0x06
+#define PIC16_PMU_REG_BLINK	0x07
+#define PIC16_PMU_REG_HW_REV	0x08
+
+#define PIC16_PMU_REFRESH	(60 * HZ)	/* 1 minute */
+
+static inline int pic16_pmu_reg_read(struct i2c_client *client, u8 reg, u8 *value)
+{
+	int tmp;
+
+	tmp = i2c_smbus_read_byte_data(client, reg);
+	if (tmp < 0)
+		tmp = i2c_smbus_read_byte_data(client, reg);
+		if (tmp < 0)
+			return -EINVAL;
+
+	*value = tmp;
+
+	return 0;
+}
+
+static inline int pic16_pmu_reg_write(struct i2c_client *client, u8 reg, u8 value)
+{
+	return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+static struct pic16_pmu_data *pic16_pmu_update(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct pic16_pmu_data *data = i2c_get_clientdata(client);
+	u8 val;
+	int ret;
+	unsigned long local_jiffies = jiffies;
+
+	mutex_lock(&data->lock);
+	if (time_before(local_jiffies, data->last_updated +
+			PIC16_PMU_REFRESH))
+		goto exit;
+
+	ret = pic16_pmu_reg_read(client, PIC16_PMU_REG_DEV, &val);
+	if (ret) {
+		dev_err(&client->dev, "error reading device model\n");
+		goto exit;
+	}
+	data->model = val;
+
+	ret = pic16_pmu_reg_read(client, PIC16_PMU_REG_REV, &val);
+	if (ret) {
+		dev_err(&client->dev, "error reading revision\n");
+		goto exit;
+	}
+	data->revision = val;
+
+	ret = pic16_pmu_reg_read(client, PIC16_PMU_REG_PWR, &val);
+	if (ret) {
+		dev_err(&client->dev, "erorr reading power status\n");
+		goto exit;
+	}
+	data->power = val;
+
+	ret = pic16_pmu_reg_read(client, PIC16_PMU_REG_BTN, &val);
+	if (ret) {
+		dev_err(&client->dev, "error reading button status\n");
+		goto exit;
+	}
+	data->buttons = val;
+
+	ret = pic16_pmu_reg_read(client, PIC16_PMU_REG_RST, &val);
+	if (ret) {
+		dev_err(&client->dev, "error reading reset status\n");
+		goto exit;
+	}
+	data->resets = val;
+
+	ret = pic16_pmu_reg_read(client, PIC16_PMU_REG_HW_REV, &val);
+	if (ret) {
+		dev_err(&client->dev, "error reading hw revision\n");
+		goto exit;
+	}
+	data->hw_revision = val;
+
+	data->last_updated = local_jiffies;
+exit:
+	mutex_unlock(&data->lock);
+	return data;
+}
+
+static ssize_t show_pwr(struct device *dev,
+			struct device_attribute *devattr,
+			char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pic16_pmu_data *data = pic16_pmu_update(dev);
+	int val;
+
+	val = (((data->power & PIC16_PMU_REG_PWR_MSK) &
+					(1 << attr->index)) >> attr->index);
+
+	return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t show_model(struct device *dev,
+			struct device_attribute *devattr,
+			char *buf)
+{
+	struct pic16_pmu_data *data = pic16_pmu_update(dev);
+	return sprintf(buf, "Microchip PIC16F%02x\n", data->model);
+}
+
+static ssize_t show_revision(struct device *dev,
+			struct device_attribute *devattrr,
+			char *buf)
+{
+	struct pic16_pmu_data *data = pic16_pmu_update(dev);
+	return sprintf(buf, "%02x\n", data->revision);
+}
+
+static ssize_t show_hw_revision(struct device *dev,
+			struct device_attribute *devattrr,
+			char *buf)
+{
+	struct pic16_pmu_data *data = pic16_pmu_update(dev);
+	return sprintf(buf, "%02x\n", data->hw_revision);
+}
+
+static ssize_t show_rst(struct device *dev,
+			struct device_attribute *devattr,
+			char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pic16_pmu_data *data = pic16_pmu_update(dev);
+	int val;
+
+	val = (((data->resets & PIC16_PMU_REG_RST_MSK) &
+					(1 << attr->index)) >> attr->index);
+
+	return sprintf(buf, "%d\n", val);
+}
+
+static int pic16_pmu_set_reset(struct i2c_client *client,
+				struct pic16_pmu_data *data,
+				unsigned int index, long value)
+{
+	int ret;
+	u8 val = data->resets;
+
+	if (value)
+		val |= (1 << index);
+	else
+		val &= ~(1 << index);
+
+	data->resets = val;
+
+	mutex_lock(&data->lock);
+	ret = pic16_pmu_reg_write(client, PIC16_PMU_REG_RST, val);
+	mutex_unlock(&data->lock);
+
+	return ret;
+}
+
+static ssize_t set_rst(struct device *dev,
+			struct device_attribute *devattr,
+			const char *buf,
+			size_t count)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pic16_pmu_data *data = pic16_pmu_update(dev);
+	struct i2c_client *client = to_i2c_client(dev);
+	long temp;
+
+	if (kstrtol(buf, 10, &temp))
+		return -EINVAL;
+
+	pic16_pmu_set_reset(client, data, attr->index, temp);
+
+	return count;
+}
+
+static ssize_t show_btn(struct device *dev,
+			struct device_attribute *devattr,
+			char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pic16_pmu_data *data = i2c_get_clientdata(client);
+	u8 val = 0;
+	int ret;
+
+	mutex_lock(&data->lock);
+	ret = pic16_pmu_reg_read(client, PIC16_PMU_REG_BTN, &val);
+	if (ret) {
+		dev_err(&client->dev, "unable to read status\n");
+		goto out_unlock;
+	}
+
+	val = (val & (1 << attr->index)) >> attr->index;
+
+out_unlock:
+	mutex_unlock(&data->lock);
+	return sprintf(buf, "%u\n", 1 - val);
+}
+
+/*
+ * Power attributes
+ */
+static SENSOR_DEVICE_ATTR(pwrgd_ps, S_IRUGO, show_pwr, NULL, 0);
+static SENSOR_DEVICE_ATTR(vcc1p5_ddr_pg, S_IRUGO, show_pwr, NULL, 1);
+static SENSOR_DEVICE_ATTR(vcc0p95_core_ok, S_IRUGO, show_pwr, NULL, 2);
+static SENSOR_DEVICE_ATTR(power_state, S_IRUGO, show_pwr, NULL, 3);
+static SENSOR_DEVICE_ATTR(standby_state, S_IRUGO, show_pwr, NULL, 4);
+
+/*
+ * Device revision attributes
+ */
+static SENSOR_DEVICE_ATTR(revision, S_IRUGO, show_revision, NULL, 0);
+static SENSOR_DEVICE_ATTR(model, S_IRUGO, show_model, NULL, 0);
+static SENSOR_DEVICE_ATTR(hw_revision, S_IRUGO, show_hw_revision, NULL, 0);
+
+/*
+ * Reset control attributes
+ */
+static SENSOR_DEVICE_ATTR(rf_rst, S_IWUSR | S_IRUGO, show_rst, set_rst, 0);
+static SENSOR_DEVICE_ATTR(cold_rst, S_IWUSR | S_IRUGO, show_rst, set_rst, 1);
+static SENSOR_DEVICE_ATTR(dvd_en, S_IWUSR | S_IRUGO, show_rst, set_rst, 2);
+
+/*
+ * Button attributes
+ */
+static SENSOR_DEVICE_ATTR(bank0_btn, S_IRUGO, show_btn, NULL, 0);
+static SENSOR_DEVICE_ATTR(reset_btn, S_IRUGO, show_btn, NULL, 1);
+static SENSOR_DEVICE_ATTR(power_btn, S_IRUGO, show_btn, NULL, 2);
+
+static struct attribute *pic16_pmu_attr[] = {
+	&sensor_dev_attr_pwrgd_ps.dev_attr.attr,
+	&sensor_dev_attr_vcc1p5_ddr_pg.dev_attr.attr,
+	&sensor_dev_attr_vcc0p95_core_ok.dev_attr.attr,
+	&sensor_dev_attr_power_state.dev_attr.attr,
+	&sensor_dev_attr_standby_state.dev_attr.attr,
+	&sensor_dev_attr_revision.dev_attr.attr,
+	&sensor_dev_attr_model.dev_attr.attr,
+	&sensor_dev_attr_rf_rst.dev_attr.attr,
+	&sensor_dev_attr_cold_rst.dev_attr.attr,
+	&sensor_dev_attr_dvd_en.dev_attr.attr,
+	&sensor_dev_attr_hw_revision.dev_attr.attr,
+	&sensor_dev_attr_bank0_btn.dev_attr.attr,
+	&sensor_dev_attr_reset_btn.dev_attr.attr,
+	&sensor_dev_attr_power_btn.dev_attr.attr,
+	NULL
+};
+
+static void pic16_pmu_set_brightness(struct led_classdev *led_cdev,
+				enum led_brightness brightness)
+{
+	struct pic16_pmu_led_data *led;
+
+	led = container_of(led_cdev, struct pic16_pmu_led_data, ldev);
+	led->status = brightness;
+	schedule_work(&led->work);
+}
+
+static int pic16_pmu_set_blink(struct led_classdev *led_cdev,
+				unsigned long *delay_on, unsigned long *delay_off)
+{
+	struct pic16_pmu_led_data *led;
+
+	led = container_of(led_cdev, struct pic16_pmu_led_data, ldev);
+	led->blink = !led->blink;
+	schedule_work(&led->work);
+
+	return 0;
+}
+
+static int pic16_pmu_led_set(struct pic16_pmu_led_data *led, u8 status, u8 blink)
+{
+	struct pic16_pmu_data *data = i2c_get_clientdata(led->client);
+	int ret;
+	u8 val = 0;
+
+	mutex_lock(&data->lock);
+
+	ret = pic16_pmu_reg_read(led->client, PIC16_PMU_REG_BLINK, &val);
+	if( ret) {
+		dev_err(&led->client->dev, "error reading BLINK reg for %d\n",
+								led->id);
+		goto exit;
+	}
+
+	if (blink)
+		val |= (1 << led->id);
+	else
+		val &= ~(1 << led->id);
+
+	ret = pic16_pmu_reg_write(led->client, PIC16_PMU_REG_BLINK, val);
+	if (ret) {
+		dev_err(&led->client->dev, "error writing back to BLINK reg value"
+							" for %d\n", led->id);
+		goto exit;
+	}
+
+	val = (1 << (led->id + 4));
+	if (status)
+		val |= (1 << led->id);
+
+	ret = pic16_pmu_reg_write(led->client, PIC16_PMU_REG_LED, val);
+	if (ret) {
+		dev_err(&led->client->dev, "error writing back to LED reg value"
+			" for %d\n", led->id);
+		goto exit;
+	}
+
+exit:
+	mutex_unlock(&data->lock);
+
+	return ret;
+}
+
+static void pic16_pmu_led_work(struct work_struct *work)
+{
+	struct pic16_pmu_led_data *led;
+
+	led = container_of(work, struct pic16_pmu_led_data, work);
+	pic16_pmu_led_set(led, led->status, led->blink);
+}
+
+static struct led_classdev pic16_pmu_leds[] = {
+	{	.name			= "power:red", },
+	{ 	.name			= "power:blue", },
+	{	.name			= "error:red",},
+};
+
+static int pic16_pmu_led_configure(struct i2c_client *client)
+{
+	int i, err = 0;
+	struct pic16_pmu_data *data = i2c_get_clientdata(client);
+	u8 val;
+
+	mutex_lock(&data->lock);
+	err = pic16_pmu_reg_read(client, PIC16_PMU_REG_LED, &val);
+	mutex_unlock(&data->lock);
+
+	if (err)
+		return err;
+
+	data->last_updated = jiffies - PIC16_PMU_REFRESH - 1;
+
+	for (i = 0; i < PIC16_PMU_LED_COUNT; i++) {
+		struct pic16_pmu_led_data *led = &data->leds[i];
+
+		led->id = i;
+		led->client = client;
+
+		led->status = val & (1 << i);
+		memcpy(&led->ldev, &pic16_pmu_leds[i], sizeof(struct led_classdev));
+
+		led->ldev.max_brightness = 1;
+		led->ldev.brightness_set = pic16_pmu_set_brightness;
+		led->ldev.blink_set = pic16_pmu_set_blink;
+		led->ldev.flags	= LED_CORE_SUSPENDRESUME;
+
+		INIT_WORK(&led->work, pic16_pmu_led_work);
+		err = led_classdev_register(&client->dev, &led->ldev);
+		if (err < 0) {
+			dev_err(&client->dev, "cannot register LED %s\n",
+				led->ldev.name);
+			goto exit;
+		}
+	}
+
+	return err;
+exit:
+	if (i > 0) {
+		for (i = i - 1; i >= 0; i--) {
+			led_classdev_unregister(&data->leds[i].ldev);
+			cancel_work_sync(&data->leds[i].work);
+		}
+	}
+	return err;
+}
+
+static int pic16_pmu_detect(struct i2c_client *client,
+			    struct i2c_board_info *info)
+{
+	struct i2c_adapter *adapter = client->adapter;
+	int device, revision;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -ENODEV;
+
+	device = i2c_smbus_read_byte_data(client, PIC16_PMU_REG_DEV);
+	if (device != PIC16_PMU_16F722)
+		return -ENODEV;
+
+	revision = i2c_smbus_read_byte_data(client, PIC16_PMU_REG_REV);
+	dev_info(&client->dev, "device: PIC16F%02x rev: %02x\n",
+		 device, revision);
+
+	strlcpy(info->type, "pic16-pmu", I2C_NAME_SIZE);
+
+	return 0;
+}
+
+/*
+ * input callbacks
+ */
+static void pic16_pmu_input_poll(struct input_polled_dev *dev)
+{
+	struct pic16_pmu_input_data *priv = dev->private;
+	struct input_dev *input = dev->input;
+	struct pic16_pmu_data *data = i2c_get_clientdata(priv->client);
+	u8 val;
+	int ret, i;
+
+	mutex_lock(&data->lock);
+	ret = pic16_pmu_reg_read(priv->client, PIC16_PMU_REG_BTN, &val);
+	if (ret) {
+		dev_err(&input->dev, "unable to read status\n");
+		goto out_unlock;
+	}
+
+	for (i = 0; i < PIC16_PMU_BTN_COUNT; i++)
+		input_report_key(input, priv->keymap[i],
+				(val & (1 << i)) ? 0 : 1);
+	input_sync(input);
+
+out_unlock:
+	mutex_unlock(&data->lock);
+}
+
+/*
+ * gpiolib callbacks
+ */
+static void pic16_pmu_gpio_set(struct gpio_chip *chip,
+				unsigned offset, int value)
+{
+	struct pic16_pmu_data *data;
+
+	data = container_of(chip, struct pic16_pmu_data, chip);
+
+	pic16_pmu_set_reset(data->client, data, offset, value);
+}
+
+static int pic16_pmu_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct pic16_pmu_data *data;
+
+	data = container_of(chip, struct pic16_pmu_data, chip);
+
+	return data->resets & (1 << offset);
+}
+
+static int pic16_pmu_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	return 0;
+}
+
+static int pic16_pmu_gpio_direction_output(struct gpio_chip *chip,
+					unsigned offset, int value)
+{
+	return 0;
+}
+
+static int pic16_pmu_probe(struct i2c_client *client,
+		const struct i2c_device_id *id)
+{
+	struct pic16_pmu_data *data;
+	struct input_polled_dev *poll_dev;
+	struct input_dev *input;
+	int err, i;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data) {
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	data->client = client;
+	i2c_set_clientdata(client, data);
+	mutex_init(&data->lock);
+
+	dev_info(&client->dev, "%s chip found\n", client->name);
+
+	data->attrs.attrs = pic16_pmu_attr;
+	err = sysfs_create_group(&client->dev.kobj, &data->attrs);
+	if (err)
+		goto exit_free;
+
+	data->hwmon_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		err = PTR_ERR(data->hwmon_dev);
+		goto exit_remove;
+	}
+
+	poll_dev = input_allocate_polled_device();
+	if (!poll_dev) {
+		err = -ENOMEM;
+		goto exit_hwmon;
+	}
+
+	data->btns.client = client;
+	data->btns.poll_dev = poll_dev;
+	memcpy(data->btns.keymap, default_map, sizeof(default_map));
+	poll_dev->private = &data->btns;
+	poll_dev->poll = pic16_pmu_input_poll;
+	poll_dev->poll_interval = 200; /* ms */
+
+	input = poll_dev->input;
+	input->name = "pic16-pmu";
+	input->phys = "pic16-pmu/input0";
+	input->id.bustype = BUS_I2C;
+	input->dev.parent = &client->dev;
+	input->keycode = data->btns.keymap;
+	input->keycodemax = ARRAY_SIZE(data->btns.keymap);
+	input->keycodesize = sizeof(unsigned short);
+
+	set_bit(EV_KEY, input->evbit);
+	for (i = 0; i < ARRAY_SIZE(data->btns.keymap); i++)
+		set_bit(data->btns.keymap[i], input->keybit);
+
+	err = input_register_polled_device(poll_dev);
+	if (err)
+		goto exit_input;
+
+	/*
+	 * update device on startup to provide consistent
+	 * informations
+	 */
+	pic16_pmu_update(&client->dev);
+
+	/* Register gpiochip driver */
+	data->chip.label = "pic16-pmu";
+	data->chip.set = pic16_pmu_gpio_set;
+	data->chip.get = pic16_pmu_gpio_get;
+	data->chip.direction_input = pic16_pmu_gpio_direction_input;
+	data->chip.direction_output = pic16_pmu_gpio_direction_output;
+	data->chip.base = 100;
+	data->chip.ngpio = PIC16_PMU_RST_COUNT;
+
+	err = gpiochip_add(&data->chip);
+	if (err)
+		goto exit_input;
+
+	return pic16_pmu_led_configure(client);
+
+exit_input:
+	input_free_polled_device(poll_dev);
+exit_hwmon:
+	hwmon_device_unregister(data->hwmon_dev);
+exit_remove:
+	sysfs_remove_group(&client->dev.kobj, &data->attrs);
+exit_free:
+	kfree(data);
+exit:
+	return err;
+}
+
+static int pic16_pmu_remove(struct i2c_client *client)
+{
+	int i;
+	struct pic16_pmu_data *data = i2c_get_clientdata(client);
+
+	gpiochip_remove(&data->chip);
+
+	for (i = 0; i < PIC16_PMU_LED_COUNT; i++) {
+		led_classdev_unregister(&data->leds[i].ldev);
+		cancel_work_sync(&data->leds[i].work);
+	}
+
+	input_unregister_polled_device(data->btns.poll_dev);
+	input_free_polled_device(data->btns.poll_dev);
+	hwmon_device_unregister(data->hwmon_dev);
+	sysfs_remove_group(&client->dev.kobj, &data->attrs);
+	kfree(data);
+	i2c_set_clientdata(client, NULL);
+
+	return 0;
+}
+
+static struct i2c_driver pic16_pmu_driver = {
+	.class		= I2C_CLASS_HWMON,
+	.driver	= {
+		.name	= "pic16-pmu",
+	},
+	.id_table	= pic16_pmu_idtable,
+	.probe		= pic16_pmu_probe,
+	.remove		= pic16_pmu_remove,
+	.detect		= pic16_pmu_detect,
+};
+
+static int __init pic16_pmu_init(void)
+{
+	return i2c_add_driver(&pic16_pmu_driver);
+}
+
+static void __exit pic16_pmu_exit(void)
+{
+	i2c_del_driver(&pic16_pmu_driver);
+}
+
+module_init(pic16_pmu_init);
+module_exit(pic16_pmu_exit);
+
+MODULE_AUTHOR("Florian Fainelli <ffainelli@freebox.fr>");
+MODULE_DESCRIPTION("PIC16F7xx PMU / LED i2c driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pic16-pmu");
diff -Nruw linux-4.2-fbx/drivers/misc/remoti./core.c linux-4.2-fbx/drivers/misc/remoti/core.c
--- linux-4.2-fbx/drivers/misc/remoti./core.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/misc/remoti/core.c	2015-09-15 19:18:37.926454663 +0200
@@ -0,0 +1,1918 @@
+/*
+ * Copyright (C) 2010 Florian Fainelli <ffainelli@freebox.fr>
+ *
+ * RemoTI core module driver.
+ *
+ * This file is subject to the GPLv2 licensing terms.
+ */
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/completion.h>
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/gpio.h>
+#include <linux/tty.h>
+#include <linux/of.h>
+
+#include "core-priv.h"
+
+#define REMOTI_FW_NAME		"rnp_cc2530.bin"
+#define REMOTI_FW_MAX_SIZE	((256 - 2) * 1024)
+#define REMOTI_MSG_TIMEOUT	(5 * HZ)
+
+/* list of remoti devices */
+static DEFINE_SPINLOCK(remoti_devs_list_lock);
+static struct list_head remoti_devs_list;
+
+static struct blocking_notifier_head udev_notifier;
+
+/*
+ * toggle device hw reset gpio
+ */
+static void dev_hw_reset_set(struct remoti_device *rd, int value)
+{
+	int ret;
+
+	ret = gpio_request(rd->pdata.reset_gpio, rd->pdev->name);
+	if (ret) {
+		dev_err(&rd->pdev->dev, "failed to request reset gpio: %d\n",
+			ret);
+		return;
+	}
+
+	gpio_direction_output(rd->pdata.reset_gpio, value);
+	gpio_set_value(rd->pdata.reset_gpio, value);
+	gpio_free(rd->pdata.reset_gpio);
+}
+
+static void dev_hw_reset_hold(struct remoti_device *rd)
+{
+	dev_hw_reset_set(rd, 1);
+}
+
+static void dev_hw_reset_release(struct remoti_device *rd)
+{
+	dev_hw_reset_set(rd, 0);
+}
+
+static void dev_hw_reset_cycle(struct remoti_device *rd)
+{
+	dev_hw_reset_hold(rd);
+	msleep(1);
+	dev_hw_reset_release(rd);
+	msleep(1);
+}
+
+/*
+ *
+ */
+static void handle_rx_msg(struct remoti_device *rd,
+			  struct remoti_rx_msg *rx_msg)
+{
+	struct remoti_tx_msg *tx_msg;
+	const struct rti_msg *msg;
+
+	rd->stats.rx_packets++;
+	msg = &rx_msg->msg;
+
+	/* sanity check */
+	if (msg->subsys >= NPI_SYS_MAX) {
+		dev_err(&rd->pdev->dev, "received message with "
+			"unknown subsys: %u\n", msg->subsys);
+		rd->stats.rx_subsys_errors++;
+		goto release_msg;
+	}
+
+	if (msg->type >= NPI_TYPE_MAX) {
+		dev_err(&rd->pdev->dev, "received message with "
+			"unknown type: %u\n", msg->type);
+		rd->stats.rx_type_errors++;
+		goto release_msg;
+	}
+
+	switch (msg->subsys) {
+	case NPI_SYS_RCAF:
+		rd->stats.rx_rcaf_packets++;
+		break;
+	case NPI_SYS_BOOT:
+		rd->stats.rx_boot_packets++;
+		break;
+	case NPI_SYS_UTIL:
+		rd->stats.rx_util_packets++;
+		break;
+	default:
+		rd->stats.rx_other_packets++;
+		break;
+	}
+
+	switch (msg->type) {
+	case NPI_AREQ:
+	{
+		struct remoti_cmd_callback *cb;
+		bool found;
+
+		/* async message, deliver to all listeners */
+		found = false;
+		spin_lock(&rd->callback_list_lock);
+		list_for_each_entry(cb, &rd->callback_list, next) {
+			if (msg->subsys == cb->subsys &&
+			    msg->cmd == cb->cmd) {
+				found = true;
+				break;
+			}
+		}
+
+		if (!found) {
+			spin_unlock(&rd->callback_list_lock);
+			if (printk_ratelimit())
+				dev_warn(&rd->pdev->dev,
+					 "no callback for async "
+					 "message type:%u subsys:%u "
+					 "cmd:0x%02x data_len:%u\n",
+					 msg->type, msg->subsys,
+					 msg->cmd, msg->data_len);
+			rd->stats.rx_no_callback++;
+			break;
+		}
+
+		cb->cb(cb->cb_priv, msg);
+		spin_unlock(&rd->callback_list_lock);
+		break;
+	}
+
+	case NPI_SREQ:
+		dev_warn(&rd->pdev->dev, "received unexpected sync "
+			 "request type:%u subsys:%u cmd:0x%02x "
+			 "data_len:%u\n",
+			 msg->type, msg->subsys,
+			 msg->cmd, msg->data_len);
+		break;
+
+	case NPI_POLL:
+	case NPI_SRSP:
+		/*
+		 * check if it is a synchronous reply to the currently
+		 * pending tx message, note that we are serialized wrt
+		 * tx_work since we run in the same workqueue
+		 *
+		 * note that we handle NPI_POLL like a response
+		 * because the serial bootloader does not use any
+		 * type, but still behave like synchronous
+		 */
+		tx_msg = NULL;
+		spin_lock(&rd->tx_msg_list_lock);
+		if (!list_empty(&rd->tx_msg_list)) {
+			tx_msg = list_first_entry(&rd->tx_msg_list,
+						  struct remoti_tx_msg, next);
+			if (tx_msg->tx_state != RTI_TX_MSG_S_WAIT_RX_ACK)
+				tx_msg = NULL;
+		}
+		spin_unlock(&rd->tx_msg_list_lock);
+
+		if (!tx_msg) {
+			dev_warn(&rd->pdev->dev, "received unexpected sync "
+				 "response type:%u subsys:%u cmd:0x%02x\n",
+				 msg->type, msg->subsys, msg->cmd);
+			goto release_msg;
+		}
+
+		if (tx_msg &&
+		    (tx_msg->msg->subsys != msg->subsys ||
+		     tx_msg->msg->reply_cmd != msg->cmd)) {
+			/* can't find any corresponding synchronous
+			 * request */
+			dev_warn(&rd->pdev->dev, "received unexpected sync "
+				 "response type:%u subsys:%u cmd:0x%02x - "
+				 "pending subsys:%u cmd:0x%02x\n",
+				 msg->type, msg->subsys, msg->cmd,
+				 tx_msg->msg->subsys,
+				 tx_msg->msg->reply_cmd);
+			goto release_msg;
+		}
+
+		/* copy message data inside tx message and complete
+		 * its transmission */
+		memcpy(tx_msg->msg->reply, msg->data, msg->data_len);
+		tx_msg->msg->reply_len = msg->data_len;
+
+		spin_lock(&rd->tx_msg_list_lock);
+		list_del(&tx_msg->next);
+		spin_unlock(&rd->tx_msg_list_lock);
+
+		/* kick tx work now that message is complete */
+		queue_work(rd->io_workqueue, &rd->tx_work);
+		complete(&tx_msg->complete);
+		break;
+	}
+
+release_msg:
+	kfree(rx_msg);
+}
+
+/*
+ * workqueue used to handle rx commands
+ */
+static void remoti_rx_work(struct work_struct *work)
+{
+	struct remoti_device *rd =
+		container_of(work, struct remoti_device, rx_work);
+
+	/* stop_tty() locking seems unreliable, make sure rx seems
+	 * stopped when we set stopping state */
+	if (dev_is_stopping(rd))
+		return;
+
+	/* dequeue all pending messages */
+	do {
+		struct remoti_rx_msg *rx_msg;
+		unsigned long flags;
+
+		/* tty recv can run from irq context */
+		rx_msg = NULL;
+		spin_lock_irqsave(&rd->rx_msg_list_lock, flags);
+		if (!list_empty(&rd->rx_msg_list)) {
+			rx_msg = list_first_entry(&rd->rx_msg_list,
+						  struct remoti_rx_msg, next);
+			list_del(&rx_msg->next);
+		}
+		spin_unlock_irqrestore(&rd->rx_msg_list_lock, flags);
+
+		if (!rx_msg)
+			break;
+
+		handle_rx_msg(rd, rx_msg);
+
+	} while (1);
+}
+
+/*
+ * generate fcs for uart rti frames
+ */
+static u8 remoti_calc_fcs(const u8 *data, int len, u8 fcs)
+{
+	while (len--)
+		fcs ^= *data++;
+
+	return fcs;
+}
+
+/*
+ * handle valid char received on UART
+ */
+static void remoti_tty_recv_char(struct remoti_device *rd, const u8 c)
+{
+	switch (rd->tty_fsm_state) {
+	case RTI_TTY_FSM_SOF:
+		switch (c) {
+		case RTI_UART_CHR_WAKEUP:
+			complete(&rd->wakeup_complete);
+			break;
+		case RTI_UART_CHR_SOF:
+			rd->tty_fsm_state = RTI_TTY_FSM_LEN;
+			break;
+		default:
+			rd->stats.rx_bad_sof++;
+			break;
+		}
+		break;
+
+	case RTI_TTY_FSM_LEN:
+		if (c == RTI_UART_CHR_SOF)
+			break;
+
+		/* Guard against malformed frames */
+		if (c > NPI_MAX_DATA_LEN) {
+			dev_err(&rd->pdev->dev, "ignoring too big "
+				"frame: len: %u\n", c);
+			rd->stats.rx_len_errors++;
+			rd->tty_fsm_state = RTI_TTY_FSM_SOF;
+			break;
+		}
+
+		rd->rx_buf[0] = c;
+		rd->rx_buf_len = 1;
+		rd->tty_fsm_state = RTI_TTY_FSM_DATA;
+		break;
+
+	case RTI_TTY_FSM_DATA:
+	{
+		size_t total_len;
+
+		rd->rx_buf[rd->rx_buf_len++] = c;
+
+		/* total bytes to read is hdr_size (len + subsys + cmd) +
+		 * data_len */
+		total_len = 3 + rd->rx_buf[0];
+		if (rd->rx_buf_len == total_len)
+			rd->tty_fsm_state = RTI_TTY_FSM_FCS;
+		break;
+	}
+
+	case RTI_TTY_FSM_FCS:
+	{
+		struct remoti_rx_msg *rx_msg;
+		struct rti_msg *msg;
+		u8 fcs;
+
+		rd->tty_fsm_state = RTI_TTY_FSM_SOF;
+
+		fcs = remoti_calc_fcs(rd->rx_buf, rd->rx_buf_len, 0);
+		if (fcs != c) {
+			rd->stats.rx_fcs_errors++;
+			dev_err(&rd->pdev->dev, "got fcs error "
+				"on rx message\n");
+			break;
+		}
+
+
+		rx_msg = kmalloc(sizeof (*rx_msg), GFP_ATOMIC);
+		if (!rx_msg) {
+			rd->stats.rx_full_errors++;
+			break;
+		}
+
+		msg = &rx_msg->msg;
+		msg->type = (rd->rx_buf[1] >> NPI_TYPE_SHIFT) & NPI_TYPE_MASK;
+		msg->subsys = rd->rx_buf[1] & NPI_SYS_MASK;
+		msg->cmd = rd->rx_buf[2];
+		msg->data_len = rd->rx_buf[0];
+		memcpy(msg->data, rd->rx_buf + 3, msg->data_len);
+
+		/* add message to rx queue & schedule work */
+		spin_lock(&rd->rx_msg_list_lock);
+		list_add_tail(&rx_msg->next, &rd->rx_msg_list);
+		spin_unlock(&rd->rx_msg_list_lock);
+		queue_work(rd->io_workqueue, &rd->rx_work);
+		break;
+	}
+	}
+}
+
+/*
+ * kernel callback when there are data to read on uart
+ */
+static void remoti_tty_recv_buf(struct tty_struct *tty, const u8 *data,
+				char *flags, int count)
+{
+	struct remoti_device *rd;
+	const u8 *dp;
+	char flag;
+	char *f;
+	int i;
+
+	/* if line is not yet attached to any device, just ignore */
+	rd = (struct remoti_device *)tty->disc_data;
+	if (!rd)
+		return;
+
+	/* Walk the received buffer in inverse order */
+	for (i = 0, dp = data, f = flags; i < count; i++, dp++) {
+		flag = *f++;
+		switch (flag) {
+		case TTY_NORMAL:
+			remoti_tty_recv_char(rd, *dp);
+			break;
+		case TTY_OVERRUN:
+		case TTY_BREAK:
+		case TTY_PARITY:
+		case TTY_FRAME:
+			rd->tty_fsm_state = RTI_TTY_FSM_SOF;
+			rd->stats.rx_tty_errors++;
+			break;
+		default:
+			pr_err("%s: unknown tty flag %d\n", tty->name, flag);
+			break;
+		}
+	}
+	rd->stats.rx_bytes += count;
+}
+
+/*
+ *
+ */
+static void release_tx_msg(struct remoti_tx_msg *tx_msg)
+{
+	if (!atomic_dec_and_test(&tx_msg->users))
+		return;
+	kfree(tx_msg);
+}
+
+/*
+ * workqueue used to dequeue and push command into tx buf and wait for
+ * completion
+ */
+static void remoti_tx_work(struct work_struct *work)
+{
+	struct remoti_device *rd =
+		container_of(work, struct remoti_device, tx_work);
+	struct remoti_tx_msg *tx_msg;
+	u8 buf[RTI_MAX_FRAME_LEN + 1]; /* +1 is for the wakeup char */
+	unsigned int buf_len;
+	int room, sent;
+
+	/* don't handle with tx message list when we try to stop
+	 * device, we will force complete them from another place */
+	if (dev_is_stopping(rd))
+		return;
+
+	tx_msg = NULL;
+	spin_lock(&rd->tx_msg_list_lock);
+	if (!list_empty(&rd->tx_msg_list))
+		tx_msg = list_first_entry(&rd->tx_msg_list,
+					  struct remoti_tx_msg, next);
+	spin_unlock(&rd->tx_msg_list_lock);
+
+
+	if (!tx_msg) {
+		/* no message to send, send wakeup if requested */
+		if (rd->tx_need_send_wakeup) {
+			buf[0] = RTI_UART_CHR_WAKEUP;
+			sent = rd->tty->ops->write(rd->tty, buf, 1);
+			if (sent)
+				rd->tx_need_send_wakeup = false;
+		}
+		return;
+	}
+
+	if (tx_msg->tx_state == RTI_TX_MSG_S_WAIT_RX_ACK) {
+		/* we are waiting for an rx ack for this message,
+		 * don't send anything */
+		return;
+	}
+
+	room = tty_write_room(rd->tty);
+	if (room == 0) {
+		/* no room, tty resume callback will reschedule tx
+		 * later */
+		return;
+	}
+
+	buf_len = 0;
+	switch (tx_msg->tx_state) {
+	case RTI_TX_MSG_S_WAITING:
+		if (room && rd->tx_need_send_wakeup) {
+			buf[buf_len++] = RTI_UART_CHR_WAKEUP;
+			room--;
+			rd->tx_need_send_wakeup = false;
+		}
+
+		if (!room)
+			break;
+
+		buf[buf_len++] = RTI_UART_CHR_SOF;
+		room--;
+		tx_msg->tx_state = RTI_TX_MSG_S_SOF_SENT;
+		/* fallthrough */
+
+	case RTI_TX_MSG_S_SOF_SENT:
+		/* send all header at once */
+		if (room < 3)
+			break;
+
+		buf[buf_len] = tx_msg->msg->data_len;
+		buf[buf_len + 1] = (tx_msg->msg->type << NPI_TYPE_SHIFT) |
+			(tx_msg->msg->subsys & NPI_SYS_MASK);
+		buf[buf_len + 2] = tx_msg->msg->cmd;
+		tx_msg->fcs = remoti_calc_fcs(buf + buf_len, 3, tx_msg->fcs);
+
+		buf_len += 3;
+		room -= 3;
+		tx_msg->tx_state = RTI_TX_MSG_S_HDR_SENT;
+		/* fallthrough */
+
+	case RTI_TX_MSG_S_HDR_SENT:
+	{
+		size_t to_send;
+
+		/* send as many data as possible */
+		to_send = tx_msg->msg->data_len - tx_msg->tx_data_sent;
+		if (to_send > room)
+			to_send = room;
+
+		memcpy(buf + buf_len,
+		       tx_msg->msg->data + tx_msg->tx_data_sent,
+		       to_send);
+
+		tx_msg->fcs = remoti_calc_fcs(buf + buf_len, to_send,
+					      tx_msg->fcs);
+		buf_len += to_send;
+		tx_msg->tx_data_sent += to_send;
+		room -= to_send;
+
+		if (tx_msg->tx_data_sent != tx_msg->msg->data_len)
+			break;
+
+		tx_msg->tx_state = RTI_TX_MSG_S_DATA_SENT;
+		/* fallthrough */
+	}
+
+	case RTI_TX_MSG_S_DATA_SENT:
+		if (!room)
+			break;
+
+		buf[buf_len++] = tx_msg->fcs;
+		tx_msg->tx_state = RTI_TX_MSG_S_SENT;
+		break;
+
+	default:
+		break;
+	}
+
+	if (!buf_len)
+		return;
+
+#if 0
+	printk("remoti_tx_work: sending buf_len %u\n", buf_len);
+	{
+		size_t i;
+
+		for (i = 0; i < buf_len; i++) {
+			printk("%02x ", buf[i]);
+		}
+		printk("\n");
+	}
+#endif
+
+	sent = rd->tty->ops->write(rd->tty, buf, buf_len);
+	if (unlikely(sent < 0)) {
+		pr_err("tty->ops->write failed with %d\n", sent);
+		return;
+	}
+
+	if (unlikely(sent < buf_len)) {
+		/* since we check available room before calling write,
+		 * this only happen when tty is closing */
+		spin_lock(&rd->tx_msg_list_lock);
+		tx_msg->canceled = true;
+		list_del(&tx_msg->next);
+		complete(&tx_msg->complete);
+		release_tx_msg(tx_msg);
+		spin_unlock(&rd->tx_msg_list_lock);
+		return;
+	}
+
+	rd->stats.tx_bytes += sent;
+
+	if (tx_msg->tx_state == RTI_TX_MSG_S_SENT) {
+
+		/* actually wait for data to be written it hw fifo,
+		 * not just in tty buffer, before we complete message
+		 * sending */
+		rd->tty->ops->wait_until_sent(rd->tty, 0);
+
+		/* send complete, update counters */
+		rd->stats.tx_packets++;
+		switch (tx_msg->msg->subsys) {
+		case NPI_SYS_RCAF:
+			rd->stats.tx_rcaf_packets++;
+			break;
+		case NPI_SYS_UTIL:
+			rd->stats.tx_util_packets++;
+			break;
+		case NPI_SYS_BOOT:
+			rd->stats.tx_boot_packets++;
+			break;
+		default:
+			rd->stats.tx_other_packets++;
+			break;
+		}
+
+		if (tx_msg->need_rx_ack) {
+			/* rx work will complete the message, note
+			 * that we cannot race with rx work since we
+			 * run in the same workqueue */
+			tx_msg->tx_state = RTI_TX_MSG_S_WAIT_RX_ACK;
+			return;
+		}
+
+		spin_lock(&rd->tx_msg_list_lock);
+		list_del(&tx_msg->next);
+		complete(&tx_msg->complete);
+		release_tx_msg(tx_msg);
+		spin_unlock(&rd->tx_msg_list_lock);
+	}
+}
+
+/*
+ * kernel callback when there is room in send buffer
+ */
+static void remoti_tty_write_resume(struct tty_struct *tty)
+{
+	struct remoti_device *rd = (struct remoti_device *)tty->disc_data;
+
+	/* can be called from irq context, defer to userspace to be
+	 * safe */
+	queue_work(rd->io_workqueue, &rd->tx_work);
+}
+
+/*
+ *
+ */
+static int __remoti_send_msg(struct remoti_device *rd,
+			     struct rti_msg *msg, bool async)
+{
+	struct remoti_tx_msg *tx_msg;
+	unsigned int timeout;
+	int ret;
+
+	if (msg->data_len > NPI_MAX_DATA_LEN)
+		return -EFBIG;
+
+	/* alloc & queue message */
+	tx_msg = kzalloc(sizeof (*tx_msg), GFP_KERNEL);
+	if (!tx_msg)
+		return -ENOMEM;
+
+	if (!msg->custom_reply_cmd)
+		msg->reply_cmd = msg->cmd;
+	msg->reply_len = 0;
+
+	tx_msg->msg = msg;
+	tx_msg->need_rx_ack = !async;
+	atomic_set(&tx_msg->users, 1);
+	init_completion(&tx_msg->complete);
+
+	spin_lock(&rd->tx_msg_list_lock);
+	atomic_inc(&tx_msg->users);
+	list_add_tail(&tx_msg->next, &rd->tx_msg_list);
+	spin_unlock(&rd->tx_msg_list_lock);
+
+	/* kick tx queue */
+	queue_work(rd->io_workqueue, &rd->tx_work);
+
+	/* wait for message to be sent */
+	ret = 0;
+	timeout = wait_for_completion_timeout(&tx_msg->complete,
+					      REMOTI_MSG_TIMEOUT);
+	if (!timeout) {
+		dev_err(&rd->pdev->dev, "timeout sending message "
+			"type:%u subsys:%u cmd:0x%02x data_len:%u\n",
+			msg->type, msg->subsys, msg->cmd, msg->data_len);
+		ret = -ETIMEDOUT;
+	}
+
+	if (tx_msg->canceled)
+		ret = -EIO;
+
+	release_tx_msg(tx_msg);
+	return ret;
+}
+
+static int remoti_send_sync_msg(struct remoti_device *rd,
+				struct rti_msg *msg)
+{
+	return __remoti_send_msg(rd, msg, false);
+}
+
+static int remoti_send_async_msg(struct remoti_device *rd,
+				 struct rti_msg *msg)
+{
+	return __remoti_send_msg(rd, msg, true);
+}
+
+/*
+ * high level api to access device
+ */
+struct rti_udev *rti_get_udevice(unsigned int id)
+{
+	struct remoti_device *rd;
+	bool found;
+
+	found = false;
+	spin_lock(&remoti_devs_list_lock);
+	list_for_each_entry(rd, &remoti_devs_list, next) {
+		if (rd->pdata.id == id) {
+			found = true;
+			break;
+		}
+	}
+	spin_unlock(&remoti_devs_list_lock);
+
+	if (!found)
+		return NULL;
+
+	spin_lock(&rd->state_lock);
+	if (rd->state != RTI_DEV_S_OPERATIONAL) {
+		spin_unlock(&rd->state_lock);
+		return NULL;
+	}
+
+	atomic_inc(&rd->user_count);
+	spin_unlock(&rd->state_lock);
+	return (struct rti_udev *)rd;
+}
+
+EXPORT_SYMBOL(rti_get_udevice);
+
+/*
+ *
+ */
+void rti_release_udevice(struct rti_udev *udev)
+{
+	struct remoti_device *rd = (struct remoti_device *)udev;
+	atomic_dec(&rd->user_count);
+}
+
+EXPORT_SYMBOL(rti_release_udevice);
+
+/*
+ *
+ */
+static int __rti_send_msg(struct rti_udev *udev, struct rti_msg *msg,
+			  bool async)
+{
+	struct remoti_device *rd = (struct remoti_device *)udev;
+	int ret;
+
+	if (!dev_is_operational(rd))
+		return -EIO;
+
+	ret = __remoti_send_msg(rd, msg, async);
+	if (ret == -ETIMEDOUT) {
+		/* catch any timeout, assume device is dead and mark
+		 * it as such */
+		rd->timeout = true;
+		queue_work(rd->fsm_workqueue, &rd->hw_fsm_work);
+		ret = -EIO;
+	}
+
+	return ret;
+}
+
+/*
+ *
+ */
+int rti_send_sync_msg(struct rti_udev *udev, struct rti_msg *msg)
+{
+	return __rti_send_msg(udev, msg, false);
+}
+
+EXPORT_SYMBOL(rti_send_sync_msg);
+
+/*
+ *
+ */
+int rti_send_async_msg(struct rti_udev *udev, struct rti_msg *msg)
+{
+	return __rti_send_msg(udev, msg, true);
+}
+
+EXPORT_SYMBOL(rti_send_async_msg);
+
+/*
+ *
+ */
+static int remoti_register_cmd_callback(struct remoti_device *rd,
+					u8 subsys, u8 cmd,
+					void (*cb)(void *cb_priv,
+						   const struct rti_msg *msg),
+					void *cb_priv)
+{
+	struct remoti_cmd_callback *cb_elem, *new_cb_elem;
+	bool found;
+
+	new_cb_elem = kmalloc(sizeof (*cb_elem), GFP_KERNEL);
+	if (!new_cb_elem)
+		return -ENOMEM;
+	new_cb_elem->subsys = subsys;
+	new_cb_elem->cmd = cmd;
+	new_cb_elem->cb = cb;
+	new_cb_elem->cb_priv = cb_priv;
+
+	found = false;
+	spin_lock(&rd->callback_list_lock);
+	list_for_each_entry(cb_elem, &rd->callback_list, next) {
+		if (new_cb_elem->subsys == cb_elem->subsys &&
+		    new_cb_elem->cmd == cb_elem->cmd) {
+			found = true;
+			break;
+		}
+	}
+
+	if (found) {
+		spin_unlock(&rd->callback_list_lock);
+		kfree(new_cb_elem);
+		dev_warn(&rd->pdev->dev, "refuse to register a second "
+			 "callback for subsys:%u cmd:0x%02x\n", subsys, cmd);
+		return -EEXIST;
+	}
+
+	list_add_tail(&new_cb_elem->next, &rd->callback_list);
+	spin_unlock(&rd->callback_list_lock);
+
+	return 0;
+}
+
+static void remoti_unregister_cmd_callback(struct remoti_device *rd,
+					   u8 subsys, u8 cmd)
+{
+	struct remoti_cmd_callback *cb_elem;
+	bool found;
+
+	found = false;
+	spin_lock(&rd->callback_list_lock);
+	list_for_each_entry(cb_elem, &rd->callback_list, next) {
+		if (subsys == cb_elem->subsys &&
+		    cmd == cb_elem->cmd) {
+			found = true;
+			break;
+		}
+	}
+
+	if (found)
+		list_del(&cb_elem->next);
+	else
+		cb_elem = NULL;
+
+	spin_unlock(&rd->callback_list_lock);
+
+	kfree(cb_elem);
+}
+
+/*
+ *
+ */
+int rti_register_cmd_callback(struct rti_udev *udev,
+			      u8 subsys, u8 cmd,
+			      void (*cb)(void *cb_priv,
+					 const struct rti_msg *msg),
+			      void *cb_priv)
+{
+	struct remoti_device *rd = (struct remoti_device *)udev;
+
+	if (!dev_is_operational(rd))
+		return -EIO;
+
+	return remoti_register_cmd_callback(rd, subsys, cmd, cb, cb_priv);
+}
+
+EXPORT_SYMBOL(rti_register_cmd_callback);
+
+void rti_unregister_cmd_callback(struct rti_udev *udev, u8 subsys, u8 cmd)
+{
+	return remoti_unregister_cmd_callback((struct remoti_device *)udev,
+					      subsys, cmd);
+}
+
+EXPORT_SYMBOL(rti_unregister_cmd_callback);
+
+int rti_register_cmds_callback(struct rti_udev *udev,
+			       const struct rti_kcallback *cbs,
+			       size_t cb_count,
+			       void *cb_priv)
+{
+	size_t i, j;
+	int ret;
+
+	for (i = 0; i < cb_count; i++) {
+		ret = rti_register_cmd_callback(udev,
+						cbs[i].subsys,
+						cbs[i].cmd,
+						cbs[i].cb,
+						cb_priv);
+		if (ret)
+			goto fail;
+	}
+
+	return 0;
+
+fail:
+	for (j = 0; j < i; j++)
+		rti_unregister_cmd_callback(udev, cbs[j].subsys, cbs[j].cmd);
+
+	return ret;
+}
+
+EXPORT_SYMBOL(rti_register_cmds_callback);
+
+void rti_unregister_cmds_callback(struct rti_udev *udev,
+				  const struct rti_kcallback *cbs,
+				  size_t cb_count)
+{
+	size_t i;
+
+	for (i = 0; i < cb_count; i++)
+		rti_unregister_cmd_callback(udev, cbs[i].subsys, cbs[i].cmd);
+}
+
+EXPORT_SYMBOL(rti_unregister_cmds_callback);
+
+/*
+ *
+ */
+static void remoti_call_udev_notifier(struct remoti_device *rd)
+{
+	enum rti_udev_state st;
+
+	switch (rd->state) {
+	case RTI_DEV_S_OPERATIONAL:
+		st = RTI_UDEV_UP;
+		break;
+
+	case RTI_DEV_S_STOPPING:
+		st = RTI_UDEV_GOING_DOWN;
+		break;
+
+	default:
+		return;
+	}
+	blocking_notifier_call_chain(&udev_notifier, rd->pdata.id, &st);
+}
+
+/*
+ *
+ */
+void rti_register_udevice_notifier(struct notifier_block *nb)
+{
+	blocking_notifier_chain_register(&udev_notifier, nb);
+}
+
+EXPORT_SYMBOL(rti_register_udevice_notifier);
+
+/*
+ *
+ */
+void rti_unregister_udevice_notifier(struct notifier_block *nb)
+{
+	blocking_notifier_chain_unregister(&udev_notifier, nb);
+}
+
+EXPORT_SYMBOL(rti_unregister_udevice_notifier);
+
+/*
+ *
+ */
+static int send_read_fw_version(struct remoti_device *rd,
+				uint32_t *version)
+{
+	struct rti_msg msg;
+	struct rti_rcaf_read_item_req *req;
+	struct rti_rcaf_read_item_resp *resp;
+	int ret;
+
+	memset(&msg, 0, sizeof (msg));
+	msg.type = NPI_SREQ;
+	msg.subsys = NPI_SYS_RCAF;
+	msg.cmd = RTI_READ_ITEM;
+	msg.data_len = sizeof (*req);
+
+	req = (struct rti_rcaf_read_item_req *)msg.data;
+	req->item = RTI_ITEM_FW_VER;
+	req->item_len = sizeof (*version);
+
+	ret = remoti_send_sync_msg(rd, &msg);
+	if (ret)
+		return ret;
+
+	resp = (struct rti_rcaf_read_item_resp *)msg.reply;
+
+	if (msg.reply_len != sizeof (*resp) + sizeof (*version) ||
+	    resp->status != RTI_SUCCESS) {
+		dev_err(&rd->pdev->dev, "invalid read item "
+			"version response\n");
+		return 1;
+	}
+
+	memcpy(version, msg.reply + sizeof (*resp), sizeof (*version));
+	*version = __le32_to_cpu(*version);
+	return 0;
+}
+
+/*
+ *
+ */
+static int send_fw_erase(struct remoti_device *rd)
+{
+	struct rti_msg msg;
+	int ret;
+
+	/* send a boot subsystem message to the operational firmware,
+	 * it will erase itself and trigger watchdog to reboot */
+	memset(&msg, 0, sizeof (msg));
+	msg.type = NPI_AREQ;
+	msg.subsys = NPI_SYS_BOOT;
+	msg.cmd = RTI_SB_RELOAD;
+
+	ret = remoti_send_async_msg(rd, &msg);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+/*
+ *
+ */
+static int serial_boot_send_firmware(struct remoti_device *rd,
+				     const struct firmware *fw)
+{
+	struct rti_msg msg;
+	struct rti_sb_write_req *wr_req;
+	int frame, num_frames;
+	int ret;
+	u8 *p;
+
+	memset(&msg, 0, sizeof (msg));
+	msg.type = NPI_POLL;
+	msg.subsys = NPI_SYS_BOOT;
+	msg.cmd = RTI_SB_WRITE_REQ;
+	msg.custom_reply_cmd = true;
+	msg.reply_cmd = (1 << 7) | msg.cmd;
+	msg.data_len = sizeof (*wr_req);
+	wr_req = (struct rti_sb_write_req *)msg.data;
+
+	/* Round-up to the right number of frames */
+	num_frames = DIV_ROUND_UP(fw->size, SB_DATA_SIZE);
+
+	for (frame = 0; frame < num_frames; frame++) {
+		unsigned int flash_offset;
+
+		p = (u8 *)(fw->data + (SB_DATA_SIZE * frame));
+
+		flash_offset = frame * (SB_DATA_SIZE / RTI_SB_FLASH_WORD);
+		wr_req->addr = cpu_to_le16(flash_offset);
+		memcpy(wr_req->data, p, SB_DATA_SIZE);
+
+		ret = remoti_send_sync_msg(rd, &msg);
+		if (ret)
+			return ret;
+
+		if (msg.reply_len != 1 || msg.reply[0] != SB_SUCCESS) {
+			dev_err(&rd->pdev->dev, "flash write failed at "
+				"offset 0x%04x\n", flash_offset);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ *
+ */
+static int serial_boot_enable_image(struct remoti_device *rd)
+{
+	struct rti_msg msg;
+	int ret;
+
+        /* Try to enable this image */
+	memset(&msg, 0, sizeof(msg));
+	/* the serial boot loader does not use type */
+	msg.subsys = NPI_SYS_BOOT;
+        msg.cmd = RTI_SB_ENABLE_REQ;
+	msg.custom_reply_cmd = true;
+	msg.reply_cmd = (1 << 7) | msg.cmd;
+
+	ret = remoti_send_sync_msg(rd, &msg);
+	if (ret)
+		return ret;
+
+	if (msg.reply_len != 1 || msg.reply[0] != SB_SUCCESS) {
+		dev_err(&rd->pdev->dev, "invalid serial enable image reply\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+/*
+ *
+ */
+static int serial_boot_do_handshake(struct remoti_device *rd)
+{
+	struct rti_msg msg;
+	int ret;
+
+	memset(&msg, 0, sizeof (msg));
+	/* the serial boot loader does not use type */
+	msg.subsys = NPI_SYS_BOOT;
+	msg.cmd = RTI_SB_HSK_REQ;
+	msg.custom_reply_cmd = true;
+	msg.reply_cmd = (1 << 7) | msg.cmd;
+
+	ret = remoti_send_sync_msg(rd, &msg);
+	if (ret)
+		return ret;
+
+	if (msg.reply_len != 1 || msg.reply[0] != SB_SUCCESS) {
+		dev_err(&rd->pdev->dev, "invalid serial handshake reply\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * check firmware image and extract its version
+ */
+static int fw_extract_version(const struct firmware *fw, u32 *version)
+{
+	struct remoti_fw_header *hdr;
+
+        if (fw->size < sizeof (*hdr) + RTI_FW_HDR_OFFSET) {
+		pr_err("firmware size is too small\n");
+                return 1;
+	}
+
+        if (fw->size >= REMOTI_FW_MAX_SIZE) {
+		pr_err("firmware size is too big\n");
+                return 1;
+	}
+
+        hdr = (struct remoti_fw_header *)(fw->data + RTI_FW_HDR_OFFSET);
+        if (hdr->enable_op != (uint32_t)~0) {
+		pr_err("firmware enable_op is invalid\n");
+		return 1;
+	}
+
+        *version = le32_to_cpu(hdr->version);
+	return 0;
+}
+
+/*
+ * callback when we receive assertion failed message
+ */
+static void handle_assert_ind(void *cb_priv, const struct rti_msg *msg)
+{
+	struct remoti_device *rd = (struct remoti_device *)cb_priv;
+	if (printk_ratelimit())
+		dev_err(&rd->pdev->dev, "got assertion FAILED message\n");
+}
+
+/*
+ * callback when we receive printk message
+ */
+static void handle_printk_ind(void *cb_priv, const struct rti_msg *msg)
+{
+	struct remoti_device *rd = (struct remoti_device *)cb_priv;
+	char buf[NPI_MAX_DATA_LEN + 1];
+	size_t i;
+
+	/* sanitize string */
+	memcpy(buf, msg->data, msg->data_len);
+	buf[NPI_MAX_DATA_LEN] = 0;
+
+	/* replace non printable char */
+        for (i = 0; i < sizeof (buf); i++) {
+		if (!buf[i])
+			break;
+		else if (buf[i] == '\r' || buf[i] == '\n')
+			buf[i] = ' ';
+                else if (buf[i] < ' ' || buf[i] > 127)
+                        buf[i] = '?';
+	}
+
+	dev_info(&rd->pdev->dev, "printk: %s\n", buf);
+}
+
+/*
+ * callback when we receive INIT_CNF message
+ */
+static void handle_init_cnf(void *cb_priv, const struct rti_msg *msg)
+{
+	struct remoti_device *rd = (struct remoti_device *)cb_priv;
+	complete(&rd->init_cnf_complete);
+}
+
+/*
+ *
+ */
+static const char *dev_states_str[] = {
+	[RTI_DEV_S_STOPPED]		= "stopped",
+	[RTI_DEV_S_BOOTING]		= "booting",
+	[RTI_DEV_S_BOOT_FAILED]		= "boot failed",
+	[RTI_DEV_S_OPERATIONAL]		= "operational",
+	[RTI_DEV_S_STOPPING]		= "stopping",
+	[RTI_DEV_S_DEAD]		= "dead",
+};
+
+static void __dev_set_state(struct remoti_device *rd,
+			    enum rti_dev_state state, bool silent)
+{
+	spin_lock(&rd->state_lock);
+	rd->state = state;
+	spin_unlock(&rd->state_lock);
+
+	if (!silent) {
+		dev_info(&rd->pdev->dev, "RNP state: %s\n",
+			 dev_states_str[state]);
+		remoti_call_udev_notifier(rd);
+		remoti_dev_change_sysfs(rd);
+	}
+}
+
+static void dev_set_state(struct remoti_device *rd, enum rti_dev_state state)
+{
+	return __dev_set_state(rd, state, false);
+}
+
+static void dev_set_state_silent(struct remoti_device *rd,
+				 enum rti_dev_state state)
+{
+	return __dev_set_state(rd, state, true);
+}
+
+/*
+ *
+ */
+static int boot_device(struct remoti_device *rd)
+{
+        const struct firmware *fw;
+	unsigned int timeout;
+	u32 user_fw_version, dev_fw_version, boot_flags;
+
+	/* get the firmware we are supposed to boot the RNP with from
+	 * userspace */
+	if (request_firmware(&fw, REMOTI_FW_NAME, &rd->pdev->dev)) {
+		dev_err(&rd->pdev->dev, "failed to request firmware\n");
+		return 1;
+	}
+
+	/* sanity check on this firmware & extract its version */
+	if (fw_extract_version(fw, &user_fw_version))
+		goto fail;
+
+	dev_info(&rd->pdev->dev, "required firmware version %08x\n",
+		 user_fw_version);
+
+	/* first try to boot it with its current firmare */
+	boot_flags = rd->boot_flags;
+	rd->boot_flags = 0;
+	reinit_completion(&rd->wakeup_complete);
+	reinit_completion(&rd->init_cnf_complete);
+	dev_hw_reset_cycle(rd);
+
+	/* get rnp out of sleep */
+	rd->tx_need_send_wakeup = true;
+	queue_work(rd->io_workqueue, &rd->tx_work);
+
+	/* wait a bit for wakeup char to be received, it won't be sent
+	 * if only a serial bootloader is present and we will wait for
+	 * nothing, but it's not the common case */
+	timeout = wait_for_completion_timeout(&rd->wakeup_complete,
+					      HZ * 2);
+	if (timeout != 0) {
+		dev_info(&rd->pdev->dev, "got RNP wakeup\n");
+
+		/* we got a wakeup; a firmware is running, check its
+		 * version */
+		if (send_read_fw_version(rd, &dev_fw_version)) {
+			dev_err(&rd->pdev->dev, "fail to read "
+				"current fw version\n");
+			goto fail;
+		}
+
+		/* wait for init confirm after we sent first
+		 * command */
+		timeout = wait_for_completion_timeout(&rd->init_cnf_complete,
+						      HZ * 10);
+		if (timeout == 0) {
+			dev_err(&rd->pdev->dev, "timeout waiting for RNP "
+				"init confirm\n");
+			goto fail;
+		}
+
+		/* compare with version we want to run */
+		if (!(boot_flags & RTI_BOOT_FLAGS_FORCE_UPDATE) &&
+		    dev_fw_version == user_fw_version) {
+			/* match, done */
+			rd->fw_version = dev_fw_version;
+			release_firmware(fw);
+			return 0;
+		}
+
+		if ((boot_flags & RTI_BOOT_FLAGS_FORCE_UPDATE))
+			dev_info(&rd->pdev->dev,
+				 "device fw version is %08x, "
+				 "but forcing erase as requested\n",
+				 dev_fw_version);
+		else
+			dev_info(&rd->pdev->dev,
+				 "device fw version is %08x, "
+				 "required %08x, erase\n",
+				 dev_fw_version, user_fw_version);
+
+		/* erase the current firmware and force a reboot */
+		if (send_fw_erase(rd))
+			return 1;
+
+		/* give it some time */
+		msleep(2000);
+
+	} else
+		dev_info(&rd->pdev->dev, "did not get RNP wakeup, "
+			 "assuming serial bootloader\n");
+
+	dev_info(&rd->pdev->dev, "doing serial bootloader handshake\n");
+
+	/* send handshake */
+	if (serial_boot_do_handshake(rd)) {
+		dev_err(&rd->pdev->dev, "failed to get "
+			"bootloader handshake\n");
+		goto fail;
+	}
+
+	dev_info(&rd->pdev->dev, "sending firmware...\n");
+
+	/* upgrade firmware */
+	if (serial_boot_send_firmware(rd, fw))
+		goto fail;
+
+	/* enable image */
+	dev_info(&rd->pdev->dev, "enabling image...\n");
+
+	reinit_completion(&rd->wakeup_complete);
+	reinit_completion(&rd->init_cnf_complete);
+	if (serial_boot_enable_image(rd))
+		goto fail;
+
+	/* wait for wakeup char again */
+	timeout = wait_for_completion_timeout(&rd->wakeup_complete,
+					      HZ * 2);
+	if (timeout == 0) {
+		dev_err(&rd->pdev->dev, "timeout waiting for RNP wakeup\n");
+		goto fail;
+	}
+
+	/* read version and compare  */
+	if (send_read_fw_version(rd, &dev_fw_version))
+		goto fail;
+
+	if (dev_fw_version != user_fw_version) {
+		dev_err(&rd->pdev->dev, "unexpected fw version (%08x) "
+			"should be %08x\n", dev_fw_version, user_fw_version);
+		goto fail;
+	}
+
+	timeout = wait_for_completion_timeout(&rd->init_cnf_complete,
+					      HZ * 10);
+	if (timeout == 0) {
+		dev_err(&rd->pdev->dev, "timeout waiting for RNP "
+			"init confirm\n");
+		goto fail;
+	}
+
+	/* done */
+	rd->fw_version = dev_fw_version;
+	release_firmware(fw);
+	return 0;
+
+fail:
+	dev_hw_reset_hold(rd);
+	release_firmware(fw);
+	return 1;
+}
+
+/*
+ *
+ */
+static void stop_device(struct remoti_device *rd)
+{
+	struct remoti_rx_msg *rx_msg, *rx_tmp;
+	struct remoti_cmd_callback *cb_elem, *cb_tmp;
+	unsigned int users;
+
+	/* make device as stopping, don't tell the world
+	 * yet */
+	dev_set_state_silent(rd, RTI_DEV_S_STOPPING);
+
+	/* stop tty rx */
+	stop_tty(rd->tty);
+	clear_bit(TTY_DO_WRITE_WAKEUP, &rd->tty->flags);
+	cancel_work_sync(&rd->rx_work);
+
+	/* discard all pending rx messages */
+	list_for_each_entry_safe(rx_msg, rx_tmp, &rd->rx_msg_list, next)
+		kfree(rx_msg);
+	INIT_LIST_HEAD(&rd->rx_msg_list);
+
+	/* stop current tx work, it may still be scheduled afterwards
+	 * but will return immediatly since we set stopping state,
+	 * just finish the current run */
+	cancel_work_sync(&rd->tx_work);
+
+	/* any new sendmsg call will be rejected from now on, flush
+	 * pending tx message and wakeup all senders */
+	do {
+		struct remoti_tx_msg *tx_msg, *tx_tmp;
+		bool done;
+
+		spin_lock(&rd->tx_msg_list_lock);
+		list_for_each_entry_safe(tx_msg, tx_tmp,
+					 &rd->tx_msg_list, next) {
+
+			if (atomic_read(&tx_msg->users) == 1) {
+				/* no more users */
+				list_del(&tx_msg->next);
+				kfree(tx_msg);
+			} else {
+				tx_msg->canceled = true;
+				complete(&tx_msg->complete);
+			}
+		}
+
+		done = list_empty(&rd->tx_msg_list);
+
+		spin_unlock(&rd->tx_msg_list_lock);
+		if (done)
+			break;
+
+		dev_set_state(rd, RTI_DEV_S_STOPPING);
+		msleep(100);
+
+	} while (1);
+
+	/* now wait for all users */
+	users = atomic_read(&rd->user_count);
+	if (users)
+		dev_info(&rd->pdev->dev, "waiting for %u users "
+			 "to detach\n", users);
+	do {
+		if (!atomic_read(&rd->user_count))
+			break;
+
+		/* tell the world */
+		dev_set_state(rd, RTI_DEV_S_STOPPING);
+
+		msleep(100);
+
+	} while (1);
+
+	/* flush callback list */
+	list_for_each_entry_safe(cb_elem, cb_tmp,
+				 &rd->callback_list, next)
+		kfree(cb_elem);
+	INIT_LIST_HEAD(&rd->callback_list);
+}
+
+/*
+ *
+ */
+static int fsm_need_change(struct remoti_device *rd, bool *req_state)
+{
+	mutex_lock(&rd->req_state_mutex);
+	if (!rd->req_state_changed) {
+		mutex_unlock(&rd->req_state_mutex);
+		return 0;
+	}
+
+	rd->req_state_changed = false;
+	*req_state = rd->req_state;
+	mutex_unlock(&rd->req_state_mutex);
+	return 1;
+}
+
+/*
+ * state machine for device start/booting/stop, run in private
+ * workqueue
+ */
+static void remoti_hw_fsm_work(struct work_struct *work)
+{
+	struct remoti_device *rd =
+		container_of(work, struct remoti_device, hw_fsm_work);
+	bool req_state;
+
+again:
+	switch (rd->state) {
+	case RTI_DEV_S_STOPPED:
+	case RTI_DEV_S_DEAD:
+		/* do nothing unless we have a start order */
+		if (!fsm_need_change(rd, &req_state) || !req_state)
+			break;
+
+		/* start booting device */
+		dev_set_state(rd, RTI_DEV_S_BOOTING);
+		goto again;
+
+	case RTI_DEV_S_BOOTING:
+		start_tty(rd->tty);
+		set_bit(TTY_DO_WRITE_WAKEUP, &rd->tty->flags);
+
+		/* register debug stuffs */
+		remoti_register_cmd_callback(rd, NPI_SYS_UTIL,
+					     RTI_DBG_PRINT_IND,
+					     handle_printk_ind, rd);
+		remoti_register_cmd_callback(rd, NPI_SYS_UTIL,
+					     RTI_DBG_ASSERT_IND,
+					     handle_assert_ind, rd);
+
+		/* keep init_cnf for us */
+		remoti_register_cmd_callback(rd, NPI_SYS_RCAF, RTI_INIT_CNF,
+					     handle_init_cnf, rd);
+
+		if (boot_device(rd)) {
+			stop_device(rd);
+			dev_set_state(rd, RTI_DEV_S_BOOT_FAILED);
+			dev_err(&rd->pdev->dev, "failed to boot device\n");
+			return;
+		}
+
+		dev_info(&rd->pdev->dev, "RNP firmware version: %08x\n",
+			 rd->fw_version);
+		dev_set_state(rd, RTI_DEV_S_OPERATIONAL);
+		break;
+
+	case RTI_DEV_S_BOOT_FAILED:
+		/* a start command will make us retry booting */
+		if (!fsm_need_change(rd, &req_state))
+			break;
+
+		if (req_state)
+			dev_set_state(rd, RTI_DEV_S_BOOTING);
+		else
+			dev_set_state(rd, RTI_DEV_S_STOPPED);
+		goto again;
+
+	case RTI_DEV_S_OPERATIONAL:
+		/* a stop command or a pending hw error will make stop
+		 * the device */
+		if ((!fsm_need_change(rd, &req_state) || req_state) &&
+		    !rd->timeout)
+			break;
+
+		if (rd->timeout)
+			dev_warn(&rd->pdev->dev, "stopping device after "
+				 "command timeout");
+
+		stop_device(rd);
+
+		if (rd->timeout)
+			dev_set_state(rd, RTI_DEV_S_DEAD);
+		else
+			dev_set_state(rd, RTI_DEV_S_STOPPED);
+		break;
+
+	case RTI_DEV_S_STOPPING:
+		/* transient state */
+		break;
+	}
+}
+
+
+/*
+ * called when userspace issue an ioctl on serial port using remoti
+ * ldisc
+ */
+static int remoti_tty_ioctl(struct tty_struct *tty, struct file *file,
+			    unsigned int cmd, unsigned long arg)
+{
+	struct remoti_device *rd;
+	void __user *useraddr = (void *)arg;
+
+	rd = (struct remoti_device *)tty->disc_data;
+
+	switch (cmd) {
+	case RTI_ATTACH_DEVICE:
+	{
+		bool found;
+		__u32 id;
+
+		/* make sure we are not already attached */
+		if (rd)
+			return -EBUSY;
+
+		if (copy_from_user(&id, useraddr, sizeof (id)))
+			return -EFAULT;
+
+		/* lookup device */
+		found = false;
+		spin_lock(&remoti_devs_list_lock);
+		list_for_each_entry(rd, &remoti_devs_list, next) {
+			if (rd->pdata.id == id) {
+				found = true;
+				break;
+			}
+		}
+
+		if (!found) {
+			spin_unlock(&remoti_devs_list_lock);
+			return -ENODEV;
+		}
+
+		rd->tty = tty;
+		tty->disc_data = rd;
+		spin_unlock(&remoti_devs_list_lock);
+
+		/* hack: force release of any gpio export done by
+		 * userspace */
+		gpio_free(rd->pdata.reset_gpio);
+
+		/* hold device reset and set its initial state */
+		dev_hw_reset_hold(rd);
+		rd->state = RTI_DEV_S_STOPPED;
+		break;
+	}
+
+	case RTI_GET_STATUS:
+	{
+		struct rti_dev_status st;
+
+		/* need to be attached */
+		if (!rd)
+			return -ENODEV;
+
+		memset(&st, 0, sizeof (st));
+		st.dev_state = rd->state;
+		st.fw_version = rd->fw_version;
+
+		if (copy_to_user(useraddr,&st, sizeof (st)))
+			return -EFAULT;
+
+		break;
+	}
+
+	case RTI_GET_STATS:
+		/* need to be attached */
+		if (!rd)
+			return -ENODEV;
+
+		rd = (struct remoti_device *)tty->disc_data;
+		if (copy_to_user(useraddr, &rd->stats, sizeof (rd->stats)))
+			return -EFAULT;
+		break;
+
+	case RTI_START_DEVICE:
+	case RTI_STOP_DEVICE:
+		/* need to be attached */
+		if (!rd)
+			return -ENODEV;
+
+		if (cmd == RTI_START_DEVICE) {
+			u32 boot_flags;
+
+			if (copy_from_user(&boot_flags, useraddr,
+					   sizeof (boot_flags)))
+				return -EFAULT;
+			rd->boot_flags = boot_flags;
+		}
+
+		mutex_lock(&rd->req_state_mutex);
+		rd->req_state = (cmd == RTI_START_DEVICE) ? true : false;
+		rd->req_state_changed = true;
+		mutex_unlock(&rd->req_state_mutex);
+		queue_work(rd->fsm_workqueue, &rd->hw_fsm_work);
+		break;
+
+	default:
+		return -ENOTTY;
+	}
+
+	return 0;
+}
+
+/*
+ * callback when userspace set the remoti ldisc on tty device
+ */
+static int remoti_tty_open(struct tty_struct *tty)
+{
+	/* leave unattached for now, ioctl will do it */
+	tty->disc_data = NULL;
+	tty->receive_room = 65536;
+	stop_tty(tty);
+	return 0;
+}
+
+/*
+ *
+ */
+static void remoti_tty_close(struct tty_struct *tty)
+{
+	struct remoti_device *rd;
+
+	rd = (struct remoti_device *)tty->disc_data;
+	if (!rd)
+		return;
+
+	dev_info(&rd->pdev->dev, "tty closing...\n");
+
+	/* no more ioctl possible, so we have control over device fsm,
+	 * ask it to stop device */
+	mutex_lock(&rd->req_state_mutex);
+	rd->req_state = false;
+	rd->req_state_changed = true;
+	mutex_unlock(&rd->req_state_mutex);
+	queue_work(rd->fsm_workqueue, &rd->hw_fsm_work);
+
+	while (rd->state != RTI_DEV_S_STOPPED &&
+	       rd->state != RTI_DEV_S_DEAD)
+		msleep(10);
+
+	dev_info(&rd->pdev->dev, "tty released\n");
+}
+
+static struct tty_ldisc_ops remoti_ldisc = {
+	.owner		= THIS_MODULE,
+	.magic		= TTY_LDISC_MAGIC,
+	.name		= "n_remoti",
+	.open		= remoti_tty_open,
+	.close		= remoti_tty_close,
+	.ioctl		= remoti_tty_ioctl,
+	.receive_buf	= remoti_tty_recv_buf,
+	.write_wakeup	= remoti_tty_write_resume,
+};
+
+/*
+ *
+ */
+static int remoti_probe(struct platform_device *pdev)
+{
+	struct remoti_device *rd;
+	const unsigned int *gpio_prop, *id_prop;
+	char wq_name[32];
+	int proplen;
+	int err;
+
+	/* allocated device & mark it as unattached  */
+	rd = kzalloc(sizeof (*rd), GFP_KERNEL);
+	if (!rd) {
+		dev_err(&pdev->dev, "unable to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	id_prop = of_get_property(pdev->dev.of_node, "id", &proplen);
+	if (!id_prop || proplen < 4) {
+		dev_err(&pdev->dev, "unable to get id property\n");
+		err = -ENODEV;
+		goto out_free;
+	}
+
+	gpio_prop = of_get_property(pdev->dev.of_node, "reset-gpio", &proplen);
+	if (!gpio_prop || proplen < 8) {
+		dev_err(&pdev->dev, "unable to get reset-gpio property\n");
+		err = -ENODEV;
+		goto out_free;
+	}
+
+	rd->pdata.id = be32_to_cpup(id_prop);
+	rd->pdata.reset_gpio = be32_to_cpup(gpio_prop);
+	rd->pdata.reset_polarity = be32_to_cpup(gpio_prop + 1);
+	BUG_ON(rd->pdata.reset_gpio != 100);
+	rd->pdev = pdev;
+
+	scnprintf(wq_name, sizeof (wq_name), "%s-fsm", pdev->name);
+	rd->fsm_workqueue = create_singlethread_workqueue(wq_name);
+	if (!rd->fsm_workqueue) {
+		dev_err(&pdev->dev, "unable to create workqueue\n");
+		err = -ENOMEM;
+		goto out_free;
+	}
+
+	scnprintf(wq_name, sizeof (wq_name), "%s-io", pdev->name);
+	rd->io_workqueue = create_singlethread_workqueue(wq_name);
+	if (!rd->io_workqueue) {
+		dev_err(&pdev->dev, "unable to create workqueue\n");
+		err = -ENOMEM;
+		goto out_free;
+	}
+
+	spin_lock_init(&rd->state_lock);
+
+	INIT_LIST_HEAD(&rd->tx_msg_list);
+	spin_lock_init(&rd->tx_msg_list_lock);
+
+	INIT_LIST_HEAD(&rd->rx_msg_list);
+	spin_lock_init(&rd->rx_msg_list_lock);
+
+	INIT_LIST_HEAD(&rd->callback_list);
+	spin_lock_init(&rd->callback_list_lock);
+
+	INIT_WORK(&rd->hw_fsm_work, remoti_hw_fsm_work);
+	INIT_WORK(&rd->tx_work, remoti_tx_work);
+	INIT_WORK(&rd->rx_work, remoti_rx_work);
+	init_completion(&rd->wakeup_complete);
+	init_completion(&rd->init_cnf_complete);
+	mutex_init(&rd->req_state_mutex);
+
+	platform_set_drvdata(pdev, rd);
+
+	/* create sysfs entries */
+	err = remoti_register_dev_sysfs(rd);
+	if (err)
+		goto out_free;
+
+	spin_lock(&remoti_devs_list_lock);
+	list_add_tail(&rd->next, &remoti_devs_list);
+	spin_unlock(&remoti_devs_list_lock);
+	return 0;
+
+out_free:
+	if (rd->fsm_workqueue)
+		destroy_workqueue(rd->fsm_workqueue);
+
+	if (rd->io_workqueue)
+		destroy_workqueue(rd->io_workqueue);
+
+	kfree(rd);
+	return err;
+}
+
+/*
+ *
+ */
+void __remoti_free_device(struct remoti_device *rd)
+{
+	destroy_workqueue(rd->fsm_workqueue);
+	destroy_workqueue(rd->io_workqueue);
+	kfree(rd);
+}
+
+/*
+ *
+ */
+static int remoti_remove(struct platform_device *pdev)
+{
+	struct remoti_device *rd = platform_get_drvdata(pdev);
+
+	spin_lock(&remoti_devs_list_lock);
+	list_del(&rd->next);
+	spin_unlock(&remoti_devs_list_lock);
+	platform_set_drvdata(pdev, NULL);
+
+	remoti_unregister_dev_sysfs(rd);
+	/* actual free is done from sysfs */
+	return 0;
+}
+
+static const struct of_device_id remoti_of_ids[] = {
+	{ .compatible = "ti,remoti" },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, remoti_of_ids);
+
+static struct platform_driver remoti_driver = {
+	.driver = {
+		.name	= "remoti",
+		.owner	= THIS_MODULE,
+		.of_match_table = remoti_of_ids,
+	},
+	.probe		= remoti_probe,
+	.remove		= remoti_remove,
+};
+
+/*
+ *
+ */
+static int __init remoti_init(void)
+{
+	int ret;
+
+	INIT_LIST_HEAD(&remoti_devs_list);
+	BLOCKING_INIT_NOTIFIER_HEAD(&udev_notifier);
+
+	ret = remoti_sysfs_init();
+	if (ret) {
+		pr_err("failed to register sysfs class\n");
+		goto out;
+	}
+
+	ret = platform_driver_register(&remoti_driver);
+	if (ret) {
+		pr_err("failed to register platform driver\n");
+		goto out_sysfs;
+	}
+
+	ret = tty_register_ldisc(N_REMOTI, &remoti_ldisc);
+	if (ret) {
+		pr_err("failed to register line discipline\n");
+		goto out_pdev;
+	}
+
+	return 0;
+
+out_sysfs:
+	remoti_sysfs_exit();
+
+out_pdev:
+	platform_driver_unregister(&remoti_driver);
+
+out:
+	return ret;
+}
+
+/*
+ *
+ */
+static void __exit remoti_exit(void)
+{
+	platform_driver_unregister(&remoti_driver);
+	tty_unregister_ldisc(N_REMOTI);
+	remoti_sysfs_exit();
+}
+
+module_init(remoti_init);
+module_exit(remoti_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Florian Fainelli <ffainelli@freebox.fr>");
+MODULE_DESCRIPTION("RemoTI core driver");
+MODULE_ALIAS("platform:remoti");
+MODULE_FIRMWARE(REMOTI_FW_NAME);
diff -Nruw linux-4.2-fbx/drivers/misc/remoti./core-priv.h linux-4.2-fbx/drivers/misc/remoti/core-priv.h
--- linux-4.2-fbx/drivers/misc/remoti./core-priv.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/misc/remoti/core-priv.h	2013-12-04 14:33:19.711478985 +0100
@@ -0,0 +1,229 @@
+#ifndef __REMOTI_PRIV_H
+#define __REMOTI_PRIV_H
+
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/completion.h>
+#include <linux/firmware.h>
+#include <linux/workqueue.h>
+#include <linux/sched.h>
+#include <linux/mutex.h>
+#include <linux/remoti/remoti.h>
+
+/*
+ * firmware related
+ */
+#define RTI_FW_HDR_OFFSET	0xc0
+
+struct remoti_fw_header {
+        __le32		enable_op;
+        __le16		start_addr;
+        __le32		version;
+} __packed;
+
+/*
+ * RCAF RPCs used during boot
+ */
+#define RTI_READ_ITEM		0x01
+#define RTI_SB_RELOAD		0x10
+
+#define RTI_INIT_CNF		0x01
+
+struct rti_rcaf_read_item_req {
+	u8		item;
+	u8		item_len;
+};
+
+struct rti_rcaf_read_item_resp {
+	u8		status;
+	u8		value[0];
+};
+
+#define RTI_ITEM_FW_VER		0xc4
+
+
+/*
+ * Serial bootloader RPCs
+ */
+#define RTI_SB_HSK_REQ		0x04
+#define RTI_SB_WRITE_REQ	0x01
+#define RTI_SB_READ_REQ		0x02
+#define RTI_SB_ENABLE_REQ	0x03
+
+#define RTI_SB_FLASH_WORD	4
+#define SB_SUCCESS		0
+#define SB_DATA_SIZE		64
+
+struct rti_sb_write_req {
+	__le16	addr;
+	u8	data[SB_DATA_SIZE];
+} __packed;
+
+struct rti_sb_read_req {
+	__le16 addr;
+} __packed;
+
+struct rti_sb_read_resp {
+	u8 status;
+	__le16 addr;
+	u8 data[SB_DATA_SIZE];
+} __packed;
+
+/*
+ * util RPC used
+ */
+#define RTI_DBG_PRINT_IND		0x30
+#define RTI_DBG_ASSERT_IND		0x31
+
+/*
+ * uart protocol
+ */
+#define RTI_UART_CHR_WAKEUP		0x00
+#define RTI_UART_CHR_SOF		0xFE
+
+/*
+ * len (1 byte) + subsystem (1 bytes) + command (1 byte) + data (variable)
+ */
+#define RTI_MAX_FRAME_LEN		(3 + NPI_MAX_DATA_LEN)
+
+enum remoti_tty_fsm_state {
+	RTI_TTY_FSM_SOF = 0,
+	RTI_TTY_FSM_LEN,
+	RTI_TTY_FSM_DATA,
+	RTI_TTY_FSM_FCS
+};
+
+/*
+ * message list
+ */
+enum remoti_tx_msg_state {
+	RTI_TX_MSG_S_WAITING = 0,
+	RTI_TX_MSG_S_SOF_SENT,
+	RTI_TX_MSG_S_HDR_SENT,
+	RTI_TX_MSG_S_DATA_SENT,
+	RTI_TX_MSG_S_SENT,
+	RTI_TX_MSG_S_WAIT_RX_ACK,
+};
+
+struct remoti_tx_msg {
+	struct rti_msg			*msg;
+	bool				need_rx_ack;
+	enum remoti_tx_msg_state	tx_state;
+	unsigned int			tx_data_sent;
+	u8				fcs;
+	atomic_t			users;
+	bool				canceled;
+	struct completion		complete;
+	struct list_head		next;
+};
+
+struct remoti_rx_msg {
+	struct rti_msg			msg;
+	struct list_head		next;
+};
+
+/*
+ * callback list
+ */
+struct remoti_cmd_callback {
+	u8				subsys;
+	u8				cmd;
+	/* this callback cannot sleep */
+	void				(*cb)(void *cb_priv,
+					      const struct rti_msg *msg);
+	void				*cb_priv;
+
+	struct list_head		next;
+};
+
+/*
+ * device context
+ */
+struct remoti_device {
+	struct platform_device		*pdev;
+	struct remoti_dev_pdata		pdata;
+	enum rti_dev_state		state;
+	spinlock_t			state_lock;
+	struct rti_dev_stats		stats;
+	u32				fw_version;
+	bool				timeout;
+
+	struct tty_struct		*tty;
+	enum remoti_tty_fsm_state	tty_fsm_state;
+
+	spinlock_t			callback_list_lock;
+	struct list_head		callback_list;
+
+	struct workqueue_struct		*io_workqueue;
+	struct work_struct		tx_work;
+	bool				tx_need_send_wakeup;
+	struct list_head		tx_msg_list;
+	spinlock_t			tx_msg_list_lock;
+
+	struct work_struct		rx_work;
+	u8				rx_buf[RTI_MAX_FRAME_LEN];
+	u8				rx_buf_len;
+	struct list_head		rx_msg_list;
+	spinlock_t			rx_msg_list_lock;
+
+	/* asserted when we receive WAKEUP char on uart */
+	struct completion		wakeup_complete;
+
+	/* asserted when we receive INIT_CNF on uart */
+	struct completion		init_cnf_complete;
+
+	/* device fsm manager */
+	struct workqueue_struct		*fsm_workqueue;
+	struct work_struct		hw_fsm_work;
+	u32				boot_flags;
+	struct mutex			req_state_mutex;
+	bool				req_state;
+	bool				req_state_changed;
+
+	/* high level users */
+	struct device			dev;
+	atomic_t			user_count;
+	struct list_head		next;
+};
+
+/*
+ *
+ */
+static inline bool dev_is_operational(struct remoti_device *rd)
+{
+	bool res;
+
+	spin_lock(&rd->state_lock);
+	res = (rd->state == RTI_DEV_S_OPERATIONAL);
+	spin_unlock(&rd->state_lock);
+
+	return res;
+}
+
+static inline bool dev_is_stopping(struct remoti_device *rd)
+{
+	bool res;
+
+	spin_lock(&rd->state_lock);
+	res = (rd->state == RTI_DEV_S_STOPPING);
+	spin_unlock(&rd->state_lock);
+
+	return res;
+}
+
+/*
+ * core-sysfs.c
+ */
+void remoti_dev_change_sysfs(struct remoti_device *rd);
+
+int remoti_register_dev_sysfs(struct remoti_device *rd);
+
+void remoti_unregister_dev_sysfs(struct remoti_device *rd);
+
+void __remoti_free_device(struct remoti_device *rd);
+
+int __init remoti_sysfs_init(void);
+
+void remoti_sysfs_exit(void);
+
+#endif /* !__REMOTI_PRIV_H */
diff -Nruw linux-4.2-fbx/drivers/misc/remoti./core-sysfs.c linux-4.2-fbx/drivers/misc/remoti/core-sysfs.c
--- linux-4.2-fbx/drivers/misc/remoti./core-sysfs.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/misc/remoti/core-sysfs.c	2013-12-04 14:33:19.711478985 +0100
@@ -0,0 +1,114 @@
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/kobject.h>
+#include <linux/stat.h>
+#include "core-priv.h"
+
+#define to_remoti_dev(cldev) container_of(cldev, struct remoti_device, dev)
+
+static ssize_t show_dev_id(struct device *dev,
+			   struct device_attribute *attr, char *buf)
+{
+	struct remoti_device *rd = to_remoti_dev(dev);
+	return sprintf(buf, "%d\n", rd->pdata.id);
+}
+
+static ssize_t show_dev_state(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	struct remoti_device *rd = to_remoti_dev(dev);
+	return sprintf(buf, "%i\n",
+		       dev_is_operational(rd) ? 1 : 0);
+}
+
+static DEVICE_ATTR(id, S_IRUGO, show_dev_id, NULL);
+static DEVICE_ATTR(state, S_IRUGO, show_dev_state, NULL);
+
+static struct device_attribute *remoti_attrs[] = {
+	&dev_attr_id,
+	&dev_attr_state,
+	/* FIXME: export stats too */
+};
+
+static int remoti_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+	struct remoti_device *rd;
+
+	if (!dev)
+		return -ENODEV;
+
+	rd = to_remoti_dev(dev);
+	if (!rd)
+		return -ENODEV;
+
+	if (add_uevent_var(env, "STATE=%u",
+			   dev_is_operational(rd) ? 1 : 0))
+		return -ENOMEM;
+
+	if (add_uevent_var(env, "ID=%u", rd->pdata.id))
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void remoti_release(struct device *dev)
+{
+	struct remoti_device *rd = to_remoti_dev(dev);
+	__remoti_free_device(rd);
+}
+
+static struct class remoti_class = {
+	.name		= "remoti",
+	.dev_release	= remoti_release,
+	.dev_uevent	= remoti_uevent,
+};
+
+void remoti_dev_change_sysfs(struct remoti_device *rd)
+{
+	struct device *dev = &rd->dev;
+
+	kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, NULL);
+}
+
+int remoti_register_dev_sysfs(struct remoti_device *rd)
+{
+	struct device *dev = &rd->dev;
+	int i, j, ret;
+
+	dev->class = &remoti_class;
+	dev_set_name(dev, "remoti%u", rd->pdata.id);
+	ret = device_register(dev);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < ARRAY_SIZE(remoti_attrs); i++) {
+		ret = device_create_file(dev, remoti_attrs[i]);
+		if (ret)
+			goto err;
+	}
+	return 0;
+
+err:
+	for (j = 0; j < i; j++)
+		device_remove_file(dev, remoti_attrs[j]);
+	device_del(dev);
+	return ret;
+}
+
+void remoti_unregister_dev_sysfs(struct remoti_device *rd)
+{
+	struct device *dev = &rd->dev;
+
+	device_unregister(dev);
+}
+
+int __init remoti_sysfs_init(void)
+{
+	return class_register(&remoti_class);
+}
+
+void remoti_sysfs_exit(void)
+{
+	class_unregister(&remoti_class);
+}
diff -Nruw linux-4.2-fbx/drivers/misc/remoti./Kconfig linux-4.2-fbx/drivers/misc/remoti/Kconfig
--- linux-4.2-fbx/drivers/misc/remoti./Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/misc/remoti/Kconfig	2013-12-04 14:33:19.711478985 +0100
@@ -0,0 +1,26 @@
+menu "RemoTI support"
+
+config REMOTI
+	tristate "RemoTI support"
+	depends on FBX6HD
+	---help---
+	  Texas Instruments RemoTI stack.
+
+config REMOTI_LEDS
+	tristate "RemoTI LEDS support"
+	depends on REMOTI
+	depends on LEDS_CLASS
+	---help---
+	  RemoTI LEDS class driver support.
+
+config REMOTI_GPIO
+	tristate "RemoTI gpio support"
+	depends on REMOTI
+	---help---
+	  gpiochip driver for the RemoTI RNP
+
+config REMOTI_USER
+	tristate "RemoTI userspace access"
+	depends on REMOTI
+
+endmenu
diff -Nruw linux-4.2-fbx/drivers/misc/remoti./leds.c linux-4.2-fbx/drivers/misc/remoti/leds.c
--- linux-4.2-fbx/drivers/misc/remoti./leds.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/misc/remoti/leds.c	2013-12-04 14:33:19.711478985 +0100
@@ -0,0 +1,249 @@
+/*
+ * LEDs support over RemoTI IPCs
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/leds.h>
+#include <linux/sysfs.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+
+#include <linux/remoti/remoti.h>
+#include <linux/remoti/leds.h>
+#include <linux/of.h>
+
+#define PFX	KBUILD_MODNAME ": "
+
+/* list of remoti gpio devices */
+static DEFINE_MUTEX(remoti_leds_list_mutex);
+static struct list_head remoti_leds_list;
+
+/*
+ * Util RPCs subsystem
+ */
+#define RTI_LEDS_SET		0x00
+#define RTI_LEDS_GET		0x01
+
+#define RTI_LEDS_MODE_MAX	0x01
+
+struct remoti_led_data {
+	unsigned int		rti_dev_id;
+	u8			hw_id;
+	struct led_classdev	ldev;
+	struct rti_udev		*udev;
+	struct platform_device	*pdev;
+	struct list_head	next;
+};
+
+static int send_led_set(struct remoti_led_data *led, u8 status)
+{
+	struct rti_msg msg;
+	u8 *command;
+
+	memset(&msg, 0, sizeof (msg));
+	msg.type = NPI_SREQ;
+	msg.subsys = NPI_SYS_UTIL;
+	msg.cmd = RTI_LEDS_SET;
+
+	command = msg.data;
+	command[0] = led->hw_id;
+	command[1] = status;
+	msg.data_len = 2;
+
+	return rti_send_sync_msg(led->udev, &msg);
+}
+
+/*
+ * LED stuff
+ */
+static void remoti_set_brightness(struct led_classdev *led_cdev,
+				  enum led_brightness brightness)
+{
+	struct remoti_led_data *led;
+
+	led = container_of(led_cdev, struct remoti_led_data, ldev);
+	send_led_set(led, brightness);
+}
+
+/*
+ * We support hardware blinking and flashing
+ */
+static int remoti_set_blink(struct led_classdev *led_cdev,
+			unsigned long *delay_on, unsigned long *delay_off)
+{
+	struct remoti_led_data *led;
+
+	led = container_of(led_cdev, struct remoti_led_data, ldev);
+	return send_led_set(led, 0x04);
+}
+
+static int try_register_led(struct remoti_led_data *led)
+{
+	int ret;
+
+	led->udev = rti_get_udevice(led->rti_dev_id);
+	if (!led->udev)
+		return 0;
+
+	/* register kernel led */
+	ret = led_classdev_register(&led->pdev->dev, &led->ldev);
+	if (ret) {
+		dev_err(&led->pdev->dev, "cannot register LED: %s\n",
+			led->ldev.name);
+		rti_release_udevice(led->udev);
+		led->udev = NULL;
+		return ret;
+	}
+
+	dev_info(&led->pdev->dev, "registered LED %s\n",
+		 led->ldev.name);
+	return 0;
+}
+
+
+static int rti_udev_notifier_cb(struct notifier_block *n,
+				unsigned long id, void *data)
+{
+	struct remoti_led_data *led;
+	enum rti_udev_state *st = (enum rti_udev_state *)data;
+
+	mutex_lock(&remoti_leds_list_mutex);
+
+	list_for_each_entry(led, &remoti_leds_list, next) {
+
+		if (led->rti_dev_id != id)
+			continue;
+
+		switch (*st) {
+		case RTI_UDEV_UP:
+			if (led->udev)
+				continue;
+
+			try_register_led(led);
+			break;
+
+		case RTI_UDEV_GOING_DOWN:
+			if (!led->udev)
+				continue;
+
+			led_classdev_unregister(&led->ldev);
+			rti_release_udevice(led->udev);
+			led->udev = NULL;
+			break;
+		}
+	}
+
+	mutex_unlock(&remoti_leds_list_mutex);
+	return 0;
+}
+
+static struct notifier_block rti_udev_notifier_block = {
+	.notifier_call = rti_udev_notifier_cb,
+};
+
+static int remoti_leds_probe(struct platform_device *pdev)
+{
+	struct device_node *child;
+	struct remoti_led_data *leds_data;
+	const char *leds_name[REMOTI_LEDS_COUNT];
+	unsigned int num_leds = 0;
+	int i;
+
+	for_each_child_of_node(pdev->dev.of_node, child) {
+		leds_name[num_leds] = of_get_property(child, "label", NULL);
+		if (!leds_name[num_leds])
+			continue;
+		num_leds++;
+	};
+
+	leds_data = kzalloc(num_leds * sizeof(*leds_data), GFP_KERNEL);
+	if (!leds_data) {
+		dev_err(&pdev->dev, "no memory for leds\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < num_leds; i++) {
+		struct remoti_led_data *led = &leds_data[i];
+
+		led->pdev = pdev;
+		led->hw_id = i;
+		memset(&led->ldev, 0, sizeof (led->ldev));
+		led->ldev.name = leds_name[i];
+		led->ldev.max_brightness = 1;
+		led->ldev.brightness_set = remoti_set_brightness;
+		led->ldev.blink_set = remoti_set_blink;
+		led->ldev.flags = LED_CORE_SUSPENDRESUME;
+
+		mutex_lock(&remoti_leds_list_mutex);
+		try_register_led(led);
+		list_add_tail(&led->next, &remoti_leds_list);
+		mutex_unlock(&remoti_leds_list_mutex);
+	}
+
+	platform_set_drvdata(pdev, leds_data);
+	return 0;
+}
+
+static int remoti_leds_remove(struct platform_device *pdev)
+{
+	struct remoti_led_data *leds_data =
+				platform_get_drvdata(pdev);
+	struct remoti_led_data *led;
+
+	mutex_lock(&remoti_leds_list_mutex);
+	list_for_each_entry(led, &remoti_leds_list, next) {
+		if (led->udev) {
+			led_classdev_unregister(&led->ldev);
+			rti_release_udevice(led->udev);
+		}
+	}
+	kfree(leds_data);
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+static struct of_device_id remoti_leds_of_ids[] = {
+	{ .compatible = "ti,remoti-leds" },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, remoti_leds_of_ids);
+
+static struct platform_driver remoti_leds_driver = {
+	.driver	= {
+		.name	= "remoti-leds",
+		.owner	= THIS_MODULE,
+		.of_match_table = remoti_leds_of_ids,
+	},
+	.probe	= remoti_leds_probe,
+	.remove = remoti_leds_remove,
+};
+
+static int __init remoti_leds_init(void)
+{
+	int ret;
+
+	INIT_LIST_HEAD(&remoti_leds_list);
+
+	ret = platform_driver_register(&remoti_leds_driver);
+	if (ret)
+		return ret;
+
+	rti_register_udevice_notifier(&rti_udev_notifier_block);
+	return 0;
+}
+
+static void __exit remoti_leds_exit(void)
+{
+	rti_unregister_udevice_notifier(&rti_udev_notifier_block);
+	platform_driver_unregister(&remoti_leds_driver);
+}
+
+module_init(remoti_leds_init);
+module_exit(remoti_leds_exit);
+
+MODULE_AUTHOR("Florian Fainelli <ffainelli@freebox.fr>");
+MODULE_DESCRIPTION("RemoTI LEDS class support");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:remoti-leds");
diff -Nruw linux-4.2-fbx/drivers/misc/remoti./Makefile linux-4.2-fbx/drivers/misc/remoti/Makefile
--- linux-4.2-fbx/drivers/misc/remoti./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/misc/remoti/Makefile	2013-12-04 14:33:19.711478985 +0100
@@ -0,0 +1,9 @@
+obj-$(CONFIG_REMOTI)		+= remoti.o
+obj-$(CONFIG_REMOTI_GPIO)	+= remoti-gpio.o
+obj-$(CONFIG_REMOTI_LEDS)	+= remoti-leds.o
+obj-$(CONFIG_REMOTI_USER)	+= remoti-user.o
+
+remoti-objs			:= core.o core-sysfs.o
+remoti-gpio-objs		:= gpio.o
+remoti-leds-objs		:= leds.o
+remoti-user-objs		:= user.o
diff -Nruw linux-4.2-fbx/drivers/misc/remoti./user.c linux-4.2-fbx/drivers/misc/remoti/user.c
--- linux-4.2-fbx/drivers/misc/remoti./user.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/misc/remoti/user.c	2015-09-15 19:18:37.926454663 +0200
@@ -0,0 +1,541 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/socket.h>
+#include <net/sock.h>
+#include <linux/remoti/remoti.h>
+
+struct rti_rx_msg {
+	struct rti_msg		msg;
+	struct list_head	next;
+};
+
+struct rti_sock_callback {
+	struct rti_callback	cb;
+	struct list_head	next;
+};
+
+struct rti_sock {
+	struct sock		sk;
+	unsigned int		rti_dev_id;
+
+	struct mutex		udev_mutex;
+	struct rti_udev		*udev;
+
+	struct list_head	rx_queue;
+	unsigned int		rx_queue_len;
+	spinlock_t		rx_queue_lock;
+
+	struct list_head	callback_list;
+	struct list_head	next;
+};
+
+#define RX_QUEUE_MAX_LEN	128
+
+static DEFINE_MUTEX(remoti_socks_list_mutex);
+static struct list_head remoti_socks_list;
+
+/*
+ *
+ */
+static inline struct rti_sock *to_rti_sock(const struct sock *sk)
+{
+	return container_of(sk, struct rti_sock, sk);
+}
+
+/*
+ *
+ */
+static void remoti_sock_deliver(void *cb_data, const struct rti_msg *msg)
+{
+	struct rti_sock *rti_sk = (struct rti_sock *)cb_data;
+	struct rti_rx_msg *rx_msg;
+
+	if (rti_sk->rx_queue_len > RX_QUEUE_MAX_LEN) {
+		if (printk_ratelimit())
+			printk(KERN_ERR "rti_sock: socket queue rx "
+			       "overflow, dropping\n");
+		return;
+	}
+
+	rx_msg = kmalloc(sizeof (*rx_msg), GFP_ATOMIC);
+	if (!rx_msg)
+		return;
+
+	memcpy(&rx_msg->msg, msg, sizeof (*msg));
+
+	spin_lock(&rti_sk->rx_queue_lock);
+	list_add_tail(&rx_msg->next, &rti_sk->rx_queue);
+	rti_sk->rx_queue_len++;
+	spin_unlock(&rti_sk->rx_queue_lock);
+
+	wake_up(sk_sleep(&rti_sk->sk));
+}
+
+/*
+ *
+ */
+static int remoti_sock_connect(struct socket *sock,
+			       struct sockaddr *vaddr,
+			       int sockaddr_len, int flags)
+{
+	struct sock *sk = sock->sk;
+	struct rti_sock *rti_sk = to_rti_sock(sk);
+	struct sockaddr_rti *rti_addr;
+	int ret;
+
+	lock_sock(sk);
+	ret = 0;
+
+	if (sock->state != SS_UNCONNECTED) {
+		ret = -EISCONN;
+		goto out;
+	}
+
+	if (sockaddr_len != sizeof (struct sockaddr_rti)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	rti_addr = (struct sockaddr_rti *)vaddr;
+
+	mutex_lock(&rti_sk->udev_mutex);
+	rti_sk->udev = rti_get_udevice(rti_addr->device_id);
+	if (!rti_sk->udev) {
+		mutex_unlock(&rti_sk->udev_mutex);
+		ret = -ENODEV;
+		goto out;
+	}
+
+	rti_sk->rti_dev_id = rti_addr->device_id;
+	sock->state = SS_CONNECTED;
+	mutex_unlock(&rti_sk->udev_mutex);
+
+out:
+	release_sock(sk);
+	return ret;
+}
+
+/*
+ *
+ */
+static int remoti_sock_sendmsg(struct socket *sock, struct msghdr *m,
+			       size_t total_len)
+{
+	struct rti_sock *rti_sk = to_rti_sock(sock->sk);
+	struct rti_msg msg;
+	bool async;
+	int ret;
+	struct iov_iter iter;
+
+	ret = 0;
+	mutex_lock(&rti_sk->udev_mutex);
+
+	if (sock->state != SS_CONNECTED) {
+		ret = -ENOTCONN;
+		goto out;
+	}
+
+	if (!rti_sk->udev) {
+		ret = -ECONNRESET;
+		goto out;
+	}
+
+	if (m->msg_name) {
+		ret = -EISCONN;
+		goto out;
+	}
+
+	if (total_len != sizeof (struct rti_msg)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	iter = m->msg_iter;
+	if (memcpy_from_msg(&msg, m, sizeof (msg))) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	/* use message type to know if we need to do a sync or async
+	 * send */
+	async = (msg.type == NPI_AREQ);
+
+	if (async)
+		ret = rti_send_async_msg(rti_sk->udev, &msg);
+	else
+		ret = rti_send_sync_msg(rti_sk->udev, &msg);
+
+	if (ret)
+		goto out;
+
+	if (!async) {
+		m->msg_iter = iter;
+		/* transfer reply to userspace */
+		if (memcpy_to_msg(m, &msg, sizeof (msg))) {
+			ret = -EFAULT;
+			goto out;
+		}
+	}
+	ret = sizeof (msg);
+
+out:
+	mutex_unlock(&rti_sk->udev_mutex);
+	return ret;
+}
+
+/*
+ *
+ */
+static unsigned int remoti_sock_poll(struct file *file, struct socket *sock,
+				     poll_table *wait)
+{
+	struct sock *sk = sock->sk;
+	struct rti_sock *rti_sk = to_rti_sock(sock->sk);
+	unsigned int mask = 0;
+
+	poll_wait(file, sk_sleep(sk), wait);
+
+	mutex_lock(&rti_sk->udev_mutex);
+	if (!rti_sk->udev)
+		mask |= POLLRDHUP | POLLERR;
+	mutex_unlock(&rti_sk->udev_mutex);
+
+	if (!list_empty(&rti_sk->rx_queue))
+		mask |= POLLIN;
+
+	return mask;
+}
+
+/*
+ *
+ */
+static int remoti_sock_recvmsg(struct socket *sock, struct msghdr *m,
+			       size_t total_len, int flags)
+{
+	struct sock *sk = sock->sk;
+	struct rti_sock *rti_sk = to_rti_sock(sk);
+	int nonblock = flags & MSG_DONTWAIT;
+	struct rti_rx_msg *rx_msg;
+	long timeout;
+	size_t copied;
+
+	if (sock->state != SS_CONNECTED)
+		return -ENOTCONN;
+
+	do {
+		/* make sure device is still here */
+		mutex_lock(&rti_sk->udev_mutex);
+		if (!rti_sk->udev) {
+			mutex_unlock(&rti_sk->udev_mutex);
+			return -ECONNRESET;
+		}
+		mutex_unlock(&rti_sk->udev_mutex);
+
+		/* wait for any packet */
+		timeout = sock_rcvtimeo(sk, nonblock);
+		timeout = wait_event_interruptible_timeout(
+			*sk_sleep(sk),
+			!list_empty(&rti_sk->rx_queue) ||
+			!rti_sk->udev,
+			timeout);
+
+		if (list_empty(&rti_sk->rx_queue) && timeout == 0) {
+			/* timeout elapsed */
+			return -EAGAIN;
+		}
+
+		if (signal_pending(current))
+			return -EINTR;
+
+		/* dequeue one message */
+		rx_msg = NULL;
+		spin_lock(&rti_sk->rx_queue_lock);
+		if (!list_empty(&rti_sk->rx_queue)) {
+			rx_msg = list_first_entry(&rti_sk->rx_queue,
+						  struct rti_rx_msg, next);
+			if (!(flags & MSG_PEEK)) {
+				list_del(&rx_msg->next);
+				rti_sk->rx_queue_len--;
+			}
+
+		}
+		spin_unlock(&rti_sk->rx_queue_lock);
+
+		if (!rx_msg) {
+			/* someone took it before us, resleep */
+			continue;
+		}
+
+		copied = sizeof (struct rti_msg);
+		if (total_len < sizeof (struct rti_msg)) {
+			copied = total_len;
+			m->msg_flags |= MSG_TRUNC;
+		}
+
+		/* transfer reply to userspace */
+		if (memcpy_to_msg(m, &rx_msg->msg, copied))
+			return -EFAULT;
+
+		/* done */
+		return copied;
+
+	} while (1);
+
+	return 0;
+}
+
+/*
+ *
+ */
+static int remoti_sock_setsockopt(struct socket *sock, int level, int optname,
+				  char __user *optval, unsigned int optlen)
+{
+	struct sock *sk = sock->sk;
+	struct rti_sock *rti_sk = to_rti_sock(sk);
+
+	if (level != SOL_REMOTI)
+		return -ENOPROTOOPT;
+
+	switch (optname) {
+	case REMOTI_REGISTER_CB:
+	{
+		struct rti_callback cb;
+		struct rti_sock_callback *cb_elem;
+		int ret;
+
+		if (sock->state != SS_CONNECTED)
+			return -ENOTCONN;
+
+		if (optlen != sizeof (cb))
+			return -EINVAL;
+
+		if (copy_from_user(&cb, optval, sizeof (cb)))
+			return -EFAULT;
+
+		mutex_lock(&rti_sk->udev_mutex);
+		if (!rti_sk->udev) {
+			mutex_unlock(&rti_sk->udev_mutex);
+			return -EIO;
+		}
+
+		cb_elem = kmalloc(sizeof (*cb_elem), GFP_KERNEL);
+		if (!cb_elem) {
+			mutex_unlock(&rti_sk->udev_mutex);
+			return -ENOMEM;
+		}
+
+		memcpy(&cb_elem->cb, &cb, sizeof (cb));
+
+		ret = rti_register_cmd_callback(rti_sk->udev,
+						cb.subsys, cb.cmd,
+						remoti_sock_deliver, rti_sk);
+
+		if (!ret)
+			list_add_tail(&cb_elem->next, &rti_sk->callback_list);
+		else
+			kfree(cb_elem);
+
+		mutex_unlock(&rti_sk->udev_mutex);
+		return ret;
+	}
+
+	default:
+		return -ENOPROTOOPT;
+	}
+
+	return 0;
+}
+
+
+/*
+ *
+ */
+static int remoti_sock_release(struct socket *sock)
+{
+	struct sock *sk;
+	struct rti_sock *rti_sk;
+
+	if (!sock || !sock->sk)
+		return 0;
+
+	sk = sock->sk;
+	rti_sk = to_rti_sock(sk);
+
+	sock_orphan(sk);
+	mutex_lock(&rti_sk->udev_mutex);
+	if (rti_sk->udev) {
+		struct rti_sock_callback *cb_elem, *tmp;
+
+		list_for_each_entry_safe(cb_elem, tmp, &rti_sk->callback_list,
+					 next) {
+			rti_unregister_cmd_callback(rti_sk->udev,
+						    cb_elem->cb.subsys,
+						    cb_elem->cb.cmd);
+			kfree(cb_elem);
+		}
+
+		INIT_LIST_HEAD(&rti_sk->callback_list);
+		rti_release_udevice(rti_sk->udev);
+		rti_sk->udev = NULL;
+	}
+	mutex_unlock(&rti_sk->udev_mutex);
+
+	mutex_lock(&remoti_socks_list_mutex);
+	list_del(&rti_sk->next);
+	mutex_unlock(&remoti_socks_list_mutex);
+
+	sock->sk = NULL;
+	sock_put(sk);
+
+	return 0;
+}
+
+/*
+ *
+ */
+static int rti_udev_notifier_cb(struct notifier_block *n,
+				unsigned long id, void *data)
+{
+	struct rti_sock *rti_sk;
+	enum rti_udev_state *st = (enum rti_udev_state *)data;
+
+	/* only interested in "going down" state */
+	if (*st == RTI_UDEV_UP)
+		return 0;
+
+	mutex_lock(&remoti_socks_list_mutex);
+
+	list_for_each_entry(rti_sk, &remoti_socks_list, next) {
+
+		if (rti_sk->rti_dev_id != id)
+			continue;
+
+		if (!mutex_trylock(&rti_sk->udev_mutex))
+			continue;
+
+		if (rti_sk->udev) {
+			struct rti_sock_callback *cb_elem, *tmp;
+
+			list_for_each_entry_safe(cb_elem, tmp,
+						 &rti_sk->callback_list,
+						 next)
+				kfree(cb_elem);
+
+			INIT_LIST_HEAD(&rti_sk->callback_list);
+			rti_release_udevice(rti_sk->udev);
+			rti_sk->udev = NULL;
+
+			wake_up(sk_sleep(&rti_sk->sk));
+		}
+		mutex_unlock(&rti_sk->udev_mutex);
+	}
+
+	mutex_unlock(&remoti_socks_list_mutex);
+	return 0;
+}
+
+static struct notifier_block rti_udev_notifier_block = {
+	.notifier_call = rti_udev_notifier_cb,
+};
+
+static const struct proto_ops remoti_proto_ops = {
+	.family =	PF_REMOTI,
+
+	.accept =	sock_no_accept,
+	.bind =		sock_no_bind,
+	.connect =	remoti_sock_connect,
+	.getsockopt =	sock_no_getsockopt,
+	.getname =	sock_no_getname,
+	.ioctl =	sock_no_ioctl,
+	.listen =	sock_no_listen,
+	.mmap =		sock_no_mmap,
+	.owner =	THIS_MODULE,
+	.poll =		remoti_sock_poll,
+	.recvmsg =	remoti_sock_recvmsg,
+	.release =	remoti_sock_release,
+	.setsockopt =	remoti_sock_setsockopt,
+	.sendmsg =	remoti_sock_sendmsg,
+	.shutdown =	sock_no_shutdown,
+	.socketpair =	sock_no_socketpair,
+	.sendpage =	sock_no_sendpage,
+};
+
+static struct proto remoti_proto = {
+        .name           = "remoti",
+        .owner          =  THIS_MODULE,
+        .obj_size       = sizeof (struct rti_sock),
+};
+
+static int remoti_sock_create(struct net *net, struct socket *sock,
+			      int protocol, int kern)
+{
+	struct sock *sk;
+	struct rti_sock *rti_sk;
+
+	if (sock->type != SOCK_SEQPACKET || protocol)
+		return -ESOCKTNOSUPPORT;
+
+        sk = sk_alloc(net, PF_REMOTI, GFP_KERNEL, &remoti_proto, kern);
+	if (!sk)
+		return -ENOMEM;
+
+        sock_init_data(sock, sk);
+        sock->state = SS_UNCONNECTED;
+        sock->ops = &remoti_proto_ops;
+
+	rti_sk = to_rti_sock(sk);
+	rti_sk->udev = NULL;
+	mutex_init(&rti_sk->udev_mutex);
+	INIT_LIST_HEAD(&rti_sk->callback_list);
+	INIT_LIST_HEAD(&rti_sk->rx_queue);
+	spin_lock_init(&rti_sk->rx_queue_lock);
+
+	mutex_lock(&remoti_socks_list_mutex);
+	list_add_tail(&rti_sk->next, &remoti_socks_list);
+	mutex_unlock(&remoti_socks_list_mutex);
+
+	return 0;
+}
+
+static struct net_proto_family remoti_family_ops = {
+	.family = PF_REMOTI,
+	.create = remoti_sock_create,
+	.owner = THIS_MODULE,
+};
+
+static int __init remoti_user_init(void)
+{
+	int ret;
+
+	INIT_LIST_HEAD(&remoti_socks_list);
+
+	ret = proto_register(&remoti_proto, 0);
+	if (ret)
+		return ret;
+
+	ret = sock_register(&remoti_family_ops);
+	if (ret)
+		goto fail_proto;
+
+	rti_register_udevice_notifier(&rti_udev_notifier_block);
+	return 0;
+
+fail_proto:
+	proto_unregister(&remoti_proto);
+
+	return ret;
+}
+
+static void __exit remoti_user_exit(void)
+{
+	rti_unregister_udevice_notifier(&rti_udev_notifier_block);
+	sock_unregister(PF_REMOTI);
+	proto_unregister(&remoti_proto);
+}
+
+module_init(remoti_user_init);
+module_exit(remoti_user_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_NETPROTO(PF_REMOTI);
--- /dev/null	2015-07-31 18:17:35.952031993 +0200
+++ linux-4.2-fbx/drivers/mtd/fbx6hd-mtdparts.c	2015-09-15 19:18:37.966454912 +0200
@@ -0,0 +1,245 @@
+/*
+ * MTD parser for fbx6hd, just return a static mtd partition
+ * list. optionally set all partitions to read/write if requested by
+ * config.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/mtd.h>
+
+#define PFX	"fbx6hd-mtdparts: "
+
+#define SZ_1M	(1 << 20)
+
+#define MBR_BLOCKS	(8)
+#define CEFDK_S1_BLOCKS	(8)
+#define CEFDK_S2_BLOCKS	(8 * 4)
+#define SERIAL_BLOCKS	(16)
+#define KEYS_BLOCKS	(8)
+
+
+#define BANK0_SIZE	(18 * SZ_1M)
+#define CONFIG_SIZE	(7 * SZ_1M)
+#define NEWBANK0_SIZE	BANK0_SIZE
+enum {
+	E_PART_ALL,
+	E_PART_MBR,
+	E_PART_CEFDK_S1_B0,
+	E_PART_CEFDK_S1_B1,
+	E_PART_CEFDK_S2_B0,
+	E_PART_CEFDK_S2_B1,
+	E_PART_SERIALINFO,
+	E_PART_KEYS,
+	E_PART_BANK0,
+	E_PART_CONFIG,
+	E_PART_BANK1,
+	E_PART_NEWBANK0,
+};
+
+static struct mtd_partition fbx6hd_nand_partitions[] = {
+	[E_PART_ALL] = {
+		.name		= "all",
+		.offset		= -1,
+		.size		= -1,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	[E_PART_MBR] = {
+		.name		= "mbr",
+		.offset		= -1,
+		.size		= -1,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	[E_PART_CEFDK_S1_B0] = {
+		.name		= "cefdk-stage1-bank0",
+		.offset		= -1,
+		.size		= -1,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	[E_PART_CEFDK_S1_B1] = {
+		.name		= "cefdk-stage1-bank1",
+		.offset		= -1,
+		.size		= -1,
+	},
+	[E_PART_CEFDK_S2_B0] = {
+		.name		= "cefdk-stage2-bank0",
+		.offset		= -1,
+		.size		= -1,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	[E_PART_CEFDK_S2_B1] = {
+		.name		= "cefdk-stage2-bank1",
+		.offset		= -1,
+		.size		= -1,
+	},
+	[E_PART_SERIALINFO] = {
+		.name		= "serial",
+		.offset		= -1,
+		.size		= -1,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	[E_PART_KEYS] = {
+		.name		= "keys",
+		.offset		= -1,
+		.size		= -1,
+	},
+	[E_PART_BANK0] = {
+		.name		= "bank0",
+		.offset		= -1,
+		.size		= -1,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	[E_PART_CONFIG] = {
+		.name		= "config",
+		.offset		= -1,
+		.size		= -1,
+	},
+	[E_PART_BANK1] = {
+		.name		= "bank1",
+		.offset		= -1,
+		.size		= -1,
+	},
+	[E_PART_NEWBANK0] = {
+		.name		= "newbank0",
+		.offset		= -1,
+		.size		= -1,
+	},
+};
+
+static int fbx6hd_parse_mtd_partitions(struct mtd_info *master,
+				       struct mtd_partition **pparts,
+				       struct mtd_part_parser_data *pdata)
+{
+	struct mtd_partition *bank1;
+	struct mtd_partition *newbank0;
+	struct mtd_partition *cur_part;
+	u32 cur_offset;
+
+	/*
+	 * make all partition cover the whole flash.
+	 */
+	cur_part = &fbx6hd_nand_partitions[E_PART_ALL];
+	cur_part->offset = 0;
+	cur_part->size = master->size;
+
+	/*
+	 * start filling partition offset/size one by one.
+	 */
+	cur_offset = 0;
+	cur_part = &fbx6hd_nand_partitions[E_PART_MBR];
+	cur_part->offset = cur_offset;
+	cur_part->size = MBR_BLOCKS * master->erasesize;
+
+	/*
+	 * CEFDK stage1 partitions
+	 */
+	cur_offset += cur_part->size;
+	cur_part = &fbx6hd_nand_partitions[E_PART_CEFDK_S1_B0];
+	cur_part->offset = cur_offset;
+	cur_part->size = CEFDK_S1_BLOCKS * master->erasesize;
+
+	cur_offset += cur_part->size;
+	cur_part = &fbx6hd_nand_partitions[E_PART_CEFDK_S1_B1];
+	cur_part->offset = cur_offset;
+	cur_part->size = CEFDK_S1_BLOCKS * master->erasesize;
+
+	/*
+	 * CEFDK stage2 partitions
+	 */
+	cur_offset += cur_part->size;
+	cur_part = &fbx6hd_nand_partitions[E_PART_CEFDK_S2_B0];
+	cur_part->offset = cur_offset;
+	cur_part->size = CEFDK_S2_BLOCKS * master->erasesize;
+
+	cur_offset += cur_part->size;
+	cur_part = &fbx6hd_nand_partitions[E_PART_CEFDK_S2_B1];
+	cur_part->offset = cur_offset;
+	cur_part->size = CEFDK_S2_BLOCKS * master->erasesize;
+
+	/*
+	 * Freebox specific
+	 */
+	cur_offset += cur_part->size;
+	cur_part = &fbx6hd_nand_partitions[E_PART_SERIALINFO];
+	cur_part->offset = cur_offset;
+	cur_part->size = SERIAL_BLOCKS * master->erasesize;
+
+	cur_offset += cur_part->size;
+	cur_part = &fbx6hd_nand_partitions[E_PART_KEYS];
+	cur_part->offset = cur_offset;
+	cur_part->size = KEYS_BLOCKS * master->erasesize;
+
+	cur_offset += cur_part->size;
+	cur_part = &fbx6hd_nand_partitions[E_PART_BANK0];
+	cur_part->offset = cur_offset;
+	cur_part->size = BANK0_SIZE;
+
+	cur_offset += cur_part->size;
+	cur_part = &fbx6hd_nand_partitions[E_PART_CONFIG];
+	cur_part->offset = cur_offset;
+	cur_part->size = CONFIG_SIZE;
+
+	cur_offset += cur_part->size;
+	cur_part = &fbx6hd_nand_partitions[E_PART_BANK1];
+	cur_part->offset = cur_offset;
+	cur_part->size = master->size - cur_offset;
+
+	/*
+	 * newbank0 starts inside bank1 partition and ends at the end
+	 * of the flash.
+	 */
+	cur_offset = master->size - NEWBANK0_SIZE;
+	cur_part = &fbx6hd_nand_partitions[E_PART_NEWBANK0];
+	cur_part->offset = cur_offset;
+	cur_part->size = NEWBANK0_SIZE;
+
+	/*
+	 * some basic sanity checks before to avoid botched partitiont
+	 * table.
+	 */
+	bank1 = &fbx6hd_nand_partitions[E_PART_BANK1];
+	newbank0 = &fbx6hd_nand_partitions[E_PART_NEWBANK0];
+	if (bank1->offset > master->size) {
+		printk(KERN_CRIT PFX "bank1 partition starts after flash "
+		       "end: use a bigger flash.\n");
+		return -ENOSPC;
+	}
+
+	if (newbank0->offset < bank1->offset) {
+		printk(KERN_CRIT PFX "newbank0 starts before bank1: use a "
+		       "bigger flash.\n");
+		return -ENOSPC;
+	}
+
+	printk(KERN_INFO PFX "%llu MiB available for bank1.\n",
+	       bank1->size >> 20);
+
+#ifdef CONFIG_MTD_FBX6HD_PARTS_WRITE_ALL
+	int i;
+	for (i = 0; i < ARRAY_SIZE(fbx6hd_nand_partitions); ++i)
+		fbx6hd_nand_partitions[i].mask_flags &= ~MTD_WRITEABLE;
+#endif
+
+	*pparts = kmemdup(fbx6hd_nand_partitions,
+			  sizeof (fbx6hd_nand_partitions), GFP_KERNEL);
+	return ARRAY_SIZE(fbx6hd_nand_partitions);
+}
+
+struct mtd_part_parser fbx6hd_mtd_parser = {
+	.owner		= THIS_MODULE,
+	.parse_fn	= fbx6hd_parse_mtd_partitions,
+	.name		= "fbx6hd-mtdparts",
+};
+
+static int __init fbx6hd_parser_init(void)
+{
+	register_mtd_parser(&fbx6hd_mtd_parser);
+	return 0;
+}
+
+module_init(fbx6hd_parser_init);
+
+
+MODULE_AUTHOR("Nicolas Schichan <nschichan@freebox.fr>");
+MODULE_LICENSE("GPL");
--- /dev/null	2015-07-31 18:17:35.952031993 +0200
+++ linux-4.2-fbx/drivers/mtd/nand/denali_nand.c	2015-09-15 19:18:37.974454962 +0200
@@ -0,0 +1,1067 @@
+/*
+ * denali nand controller driver.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+
+#include <linux/mtd/nand.h>
+#include <linux/mtd/mtd.h>
+
+#include <linux/mtd/partitions.h>
+
+#define PFX	"denali_nand: "
+
+#include "denali_nand.h"
+
+static const char *parts_parsers[] = { "fbx6hd-mtdparts", NULL };
+
+static int max_mode __read_mostly = 4;
+module_param(max_mode, int, 0);
+MODULE_PARM_DESC(max_mode, "Maximum ONFI timing mode supported (default: 4)");
+
+static int map_mode __read_mostly;
+module_param(map_mode, int, 0);
+MODULE_PARM_DESC(map_mode, "MAP mode to use (01, 10, 11)");
+
+static int dnl_reset_bank(struct denali_nand_priv *priv);
+
+/*
+ * register accessors
+ */
+static inline u32 dnl_reg_readl(struct denali_nand_priv *priv, u32 addr)
+{
+	return readl(priv->regs + addr);
+}
+
+static inline void dnl_reg_writel(struct denali_nand_priv *priv, u32 val,
+				  u32 addr)
+{
+	writel(val, priv->regs + addr);
+}
+
+/*
+ * mem accessors.
+ */
+static inline u32 dnl_mem_readl(struct denali_nand_priv *priv, u32 addr)
+{
+	return readl(priv->mem + addr);
+}
+
+static inline void dnl_mem_writel(struct denali_nand_priv *priv, u32 val,
+				  u32 addr)
+{
+	writel(val, priv->mem + addr);
+}
+
+/*
+ * read/write to/from a map.
+ */
+static uint32_t dnl_map_read(struct denali_nand_priv *priv, u32 map_ctl)
+{
+	dnl_mem_writel(priv, map_ctl, DNL_MAP_CTL_REG);
+	return dnl_mem_readl(priv, DNL_MAP_DATA_REG);
+}
+
+static void dnl_map_write(struct denali_nand_priv *priv, u32 data,
+				 u32 map_ctl)
+{
+	dnl_mem_writel(priv, map_ctl, DNL_MAP_CTL_REG);
+	dnl_mem_writel(priv, data, DNL_MAP_DATA_REG);
+}
+
+/*
+ * write_buf: support only map11 write, direct NAND bus access.
+ */
+static void dnl_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
+{
+	struct nand_chip *nand;
+	struct denali_nand_priv *priv;
+	int i;
+	u32 map_ctl;
+
+	nand = mtd->priv;
+	priv = nand->priv;
+
+	map_ctl = DNL_MAP_11_MASK;
+	map_ctl |= priv->chip_num << DNL_CHIP_SHIFT;
+	map_ctl |= DNL_MAP_11_DATA_MASK;
+
+	dnl_mem_writel(priv, map_ctl, DNL_MAP_CTL_REG);
+
+	for (i = 0; i < len; ++i)
+		dnl_mem_writel(priv, buf[i], DNL_MAP_DATA_REG);
+}
+
+static u8 dnl_read_map11_byte(struct denali_nand_priv *priv)
+{
+	u8 ret;
+	u32 map_ctl;
+
+	map_ctl = DNL_MAP_11_MASK;
+	map_ctl |= priv->chip_num << DNL_CHIP_SHIFT;
+	map_ctl |= DNL_MAP_11_DATA_MASK;
+
+	ret =  dnl_map_read(priv, map_ctl);
+	return ret;
+}
+
+static u8 dnl_read_byte(struct mtd_info *mtd)
+{
+	struct nand_chip *nand;
+	struct denali_nand_priv *priv;
+
+	nand = mtd->priv;
+	priv = nand->priv;
+
+	if (priv->buf_mode != E_BUFMODE_MAP11) {
+		printk(KERN_ERR PFX "read_byte() when not in MAP11 mode is "
+		       "not supported.\n");
+		return 0xff;
+	}
+
+	return dnl_read_map11_byte(priv);
+}
+
+/*
+ * map11 read_buf: all accesses will generate a data read on the NAND
+ * bus.
+ */
+static void dnl_read_map11_buf(struct denali_nand_priv *priv,
+			       uint8_t *buf, int len)
+{
+	int i;
+	u32 map_ctl;
+
+	map_ctl = DNL_MAP_11_MASK;
+	map_ctl |= priv->chip_num << DNL_CHIP_SHIFT;
+	map_ctl |= DNL_MAP_11_DATA_MASK;
+
+	dnl_mem_writel(priv, map_ctl, DNL_MAP_CTL_REG);
+
+	for (i = 0; i < len; ++i)
+		buf[i] = dnl_mem_readl(priv, DNL_MAP_DATA_REG);
+}
+
+static void dnl_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+	struct nand_chip *nand;
+	struct denali_nand_priv *priv;
+
+	nand = mtd->priv;
+	priv = nand->priv;
+
+	dnl_read_map11_buf(priv, buf, len);
+}
+
+/*
+ * enable/disable DMA helpers. DMA MUST be enabled before issuing the
+ * MAP10 four command sequence.
+ */
+static void dnl_enable_dma(struct denali_nand_priv *priv)
+{
+	dnl_reg_writel(priv, 1, DNL_DMA_ENABLE);
+	dnl_reg_readl(priv, DNL_DMA_ENABLE);
+}
+
+static void dnl_disable_dma(struct denali_nand_priv *priv)
+{
+	dnl_reg_writel(priv, 0, DNL_DMA_ENABLE);
+	dnl_reg_readl(priv, DNL_DMA_ENABLE);
+}
+
+/*
+ * used before and after reading/writing OOB.
+ */
+static void dnl_set_transfer_mode(struct denali_nand_priv *priv,
+				  int page, int mode)
+{
+	u32 map_ctl;
+	u32 data;
+
+	map_ctl = DNL_MAP_10_MASK;
+	map_ctl |= (priv->chip_num << DNL_CHIP_SHIFT);
+	map_ctl |= page;
+	data = mode;
+
+	dnl_map_write(priv, data, map_ctl);
+}
+
+static void dnl_clear_all_interrupts(struct denali_nand_priv *priv)
+{
+	u32 reg_offset;
+
+	reg_offset = DNL_0_INTR_STATUS_REG + (priv->chip_num * 0x14) * 4;
+	dnl_reg_writel(priv, 0xffff, reg_offset);
+}
+
+/*
+ * configure a DMA access using the mapped dma buffer in priv. this is
+ * done by issuing the 4 command sequence described in the
+ * documentation, chapter7, page 52.
+ */
+static void dnl_setup_dma(struct denali_nand_priv *priv,
+			  u32 page_addr, int access_mode)
+{
+	uint32_t map_ctl;
+	uint32_t data;
+	uint16_t addr_hi;
+	uint16_t addr_lo;
+
+	addr_hi = ((u32)priv->read_buf_dma >> 16) & 0xffff;
+	addr_lo = (u32)priv->read_buf_dma & 0xffff;
+
+	map_ctl = DNL_MAP_10_MASK | (priv->chip_num << DNL_CHIP_SHIFT);
+
+	/*
+	 * first step, transmit page_addr, select between program or
+	 * read..
+	 */
+	if (access_mode == DNL_E_DMA_PROGRAM)
+		data = DNL_MAP10_DMA_WRITE_PAGE;
+	else
+		data = DNL_MAP10_DMA_READ_PAGE;
+	dnl_map_write(priv, data, map_ctl | page_addr);
+
+	/*
+	 * second step, transmit addr_hi
+	 */
+	dnl_map_write(priv, DNL_MAP10_DMA_SET_ADDR_HI,
+		      map_ctl | (addr_hi << 8));
+
+	/*
+	 * third step, transmit addr_lo
+	 */
+	dnl_map_write(priv, DNL_MAP10_DMA_SET_ADDR_LO,
+		      map_ctl | (addr_lo << 8));
+
+	/*
+	 * fourth step, raise interrupt when complete, 64byte burst.
+	 */
+	dnl_map_write(priv, DNL_MAP10_DMA_SET_PARAMS,
+		      map_ctl | DNL_DMA_PARAM_GEN_INT | DNL_DMA_BURST_64);
+}
+
+/*
+ * wait for specific interrupt flag to be set by hardware. wait at
+ * most for 2 seconds for this to happen or timeout.
+ *
+ * more than one bit can be set in the status_mask (for instance to
+ * watch program_complete and program_failed interrupt events). the
+ * status that caused this function to return is set in *res_status
+ * for the caller layer to sort out.
+ */
+static int dnl_spin_for_mask(struct denali_nand_priv *priv,
+			     u32 status_mask, u32 *res_status)
+{
+	u32 count;
+	u32 status;
+	u32 reg_offset;
+
+	/*
+	 * select the status register of the chip we want to spin on.
+	 */
+	reg_offset = DNL_0_INTR_STATUS_REG + (priv->chip_num * 0x14) * 4;
+
+	/*
+	 * wait, use a two second timeout, should yield a confortable
+	 * margin for any expected irq bit to be set.
+	 */
+	count = 200000;
+	while (count) {
+		status = dnl_reg_readl(priv, reg_offset);
+		if (status & status_mask) {
+			dnl_reg_writel(priv, status_mask, reg_offset);
+			*res_status = status;
+			return 0;
+		}
+		cpu_relax();
+		--count;
+	}
+
+	printk(KERN_ERR PFX "timedout waiting for %08x: status %08x\n",
+	       status_mask, status);
+	return -ETIMEDOUT;
+}
+
+/*
+ * read a page using DMA.
+ */
+static int dnl_read_page_raw(struct mtd_info *mtd, struct nand_chip *nand,
+			     uint8_t *buf, int oob_required, int page)
+{
+	struct denali_nand_priv *priv = nand->priv;
+	u32 status;
+
+	dma_sync_single_for_device(&priv->dev->dev, priv->read_buf_dma,
+				   priv->read_buf_size, DMA_FROM_DEVICE);
+
+	dnl_enable_dma(priv);
+	dnl_setup_dma(priv, page, DNL_E_DMA_READ);
+
+	if (dnl_spin_for_mask(priv,
+			      DNL_INT_DMA_DATA_CMD_COMPLETE |
+			      DNL_INT_BAD_CMD_SEQ,
+			      &status) < 0) {
+		printk(KERN_ERR PFX "timedout waiting for DMA.\n");
+		return -ETIMEDOUT;
+	}
+	udelay(20);
+
+	/*
+	 * disable and sync dma before considering status.
+	 */
+	dnl_disable_dma(priv);
+	dma_sync_single_for_cpu(&priv->dev->dev, priv->read_buf_dma,
+				priv->read_buf_size, DMA_FROM_DEVICE);
+
+	if (status & DNL_INT_BAD_CMD_SEQ) {
+		printk(KERN_ERR PFX "controller reported a bad command "
+		       "sequence.\n");
+		return -EIO;
+	}
+
+	memcpy(buf, priv->read_buf, mtd->writesize);
+	if (oob_required)
+		memcpy(nand->oob_poi, priv->read_buf + mtd->writesize,
+		       mtd->oobsize);
+
+	return 0;
+}
+
+/*
+ * access oob zone using MAP01 command and no DMA.
+ */
+static int dnl_read_oob(struct mtd_info *mtd, struct nand_chip *nand,
+			int page)
+{
+	struct denali_nand_priv *priv = nand->priv;
+	u32 map_ctl;
+	u32 pos;
+	u32 *buf32;
+	u32 status;
+
+	dnl_clear_all_interrupts(priv);
+
+	/*
+	 * tell the hardware to read only spare in MAP01 mode.
+	 */
+	dnl_set_transfer_mode(priv, page, DNL_XFER_SPARE_ONLY);
+
+	/*
+	 * select the page to read oob from.
+	 */
+	map_ctl = DNL_MAP_01_MASK | page;
+	dnl_mem_writel(priv, map_ctl, DNL_MAP_CTL_REG);
+
+	/*
+	 * read oob.
+	 */
+	buf32 = (u32*)nand->oob_poi;
+	for (pos = 0; pos < mtd->oobsize; pos += 4)
+		buf32[pos / 4] = dnl_mem_readl(priv, DNL_MAP_DATA_REG);
+
+	/*
+	 * ok, we already have the data in nand->oob_poi, so I guess
+	 * this is in the original driver just to be sure that we have
+	 * not read crap from the controller.
+	 */
+	if (dnl_spin_for_mask(priv, DNL_INT_LOAD_COMPLETE, &status) < 0) {
+		printk("timeouted waiting for oob load completion.\n");
+		return -ETIMEDOUT;
+	}
+
+	/*
+	 * switch back to MAIN + SPARE mode.
+	 */
+	dnl_set_transfer_mode(priv, page, DNL_XFER_SPARE_AND_MAIN);
+
+	return 0;
+}
+
+/*
+ * write oob zone of given page. use MAP01 command, no DMA.
+ */
+static int dnl_write_oob(struct mtd_info *mtd, struct nand_chip *nand, int page)
+{
+	struct denali_nand_priv *priv = nand->priv;
+	u32 map_ctl;
+	u32 *buf32;
+	u32 pos;
+	u32 status;
+
+	dnl_clear_all_interrupts(priv);
+
+	/*
+	 * tell the hardware to read only spare in MAP01 mode.
+	 */
+	dnl_set_transfer_mode(priv, page, DNL_XFER_SPARE_ONLY);
+
+	/*
+	 * select the page to write oob from.
+	 */
+	map_ctl = DNL_MAP_01_MASK | page;
+	dnl_mem_writel(priv, map_ctl, DNL_MAP_CTL_REG);
+
+	/*
+	 * write the oob data to the controller.
+	 */
+	buf32 = (u32*)nand->oob_poi;
+	for (pos = 0; pos < mtd->oobsize; pos += 4)
+		dnl_mem_writel(priv, buf32[pos / 4], DNL_MAP_DATA_REG);
+
+	if (dnl_spin_for_mask(priv,
+			      DNL_INT_PROGRAM_COMPLETE |
+			      DNL_INT_PROGRAM_FAIL,
+			      &status) < 0) {
+		printk(KERN_ERR PFX "timeouted waiting for OOB program.\n");
+		return -ETIMEDOUT;
+	}
+
+
+	/*
+	 * switch back to MAIN + SPARE mode.
+	 */
+	dnl_set_transfer_mode(priv, page, DNL_XFER_SPARE_AND_MAIN);
+
+	if (status & DNL_INT_PROGRAM_FAIL) {
+		printk(KERN_ERR PFX "controller reported a bad OOB program.\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+
+/*
+ * issue an erase command using MAP10 command and wait for command
+ * completion.
+ */
+static int dnl_erase(struct mtd_info *mtd, int page)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct denali_nand_priv *priv = nand->priv;
+	u32 map_ctl;
+	u32 data;
+	u32 status;
+
+	dnl_clear_all_interrupts(priv);
+
+	map_ctl = DNL_MAP_10_MASK | page;
+	data = DNL_MAP10_ERASE_COMMAND;
+	dnl_map_write(priv, data, map_ctl);
+
+	if (dnl_spin_for_mask(priv,
+			      DNL_INT_ERASE_FAILED | DNL_INT_ERASE_COMPLETE,
+			      &status) < 0) {
+		printk(KERN_ERR PFX "timeouted waiting for erase on page "
+		       "%u.\n", page);
+		return NAND_STATUS_FAIL;
+	}
+
+	if (status & DNL_INT_ERASE_FAILED) {
+		printk(KERN_ERR PFX "controller reported erase failed on "
+		       "block %i\n", page);
+		return NAND_STATUS_FAIL;
+	}
+
+	return 0;
+}
+
+/*
+ * start a page write, use DMA.
+ */
+static int dnl_write_page_raw(struct mtd_info *mtd, struct nand_chip *nand,
+			      const uint8_t *buf, int oob_required)
+{
+	struct denali_nand_priv *priv = nand->priv;
+	u32 status;
+
+	if (!oob_required)
+		dnl_set_transfer_mode(priv, priv->page, DNL_XFER_MAIN_ONLY);
+	else
+		dnl_set_transfer_mode(priv, priv->page,
+				      DNL_XFER_SPARE_AND_MAIN);
+
+	/*
+	 * build buffer for DMA with oob tightly following data.
+	 */
+	memcpy(priv->read_buf, buf, mtd->writesize);
+	if (oob_required)
+		memcpy(priv->read_buf + mtd->writesize, nand->oob_poi,
+		       mtd->oobsize);
+
+	dma_sync_single_for_device(&priv->dev->dev, priv->read_buf_dma,
+				   priv->read_buf_size, DMA_TO_DEVICE);
+
+	dnl_clear_all_interrupts(priv);
+	dnl_enable_dma(priv);
+	dnl_setup_dma(priv, priv->page, DNL_E_DMA_PROGRAM);
+
+	if (dnl_spin_for_mask(priv,
+			      DNL_INT_DMA_DATA_CMD_COMPLETE |
+			      DNL_INT_PROGRAM_FAIL |
+			      DNL_INT_BAD_CMD_SEQ,
+			      &status) < 0) {
+		printk(KERN_ERR PFX "timedout waiting for program completion "
+		       "on page %u\n", priv->page);
+		return -1;
+	}
+
+	dnl_disable_dma(priv);
+	dma_sync_single_for_cpu(&priv->dev->dev, priv->read_buf_dma,
+				priv->read_buf_size, DMA_TO_DEVICE);
+
+	if (status & DNL_INT_PROGRAM_FAIL) {
+		printk(KERN_ERR PFX "controller reported a program failure "
+		       "on page %u\n", priv->page);
+		return -1;
+	}
+
+	if (status & DNL_INT_BAD_CMD_SEQ) {
+		printk(KERN_ERR PFX "controller reported a bad command "
+		       "sequence.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
+ * command control: a NAND bus access will be generated with this
+ * function (command, address, or data).
+ */
+static void dnl_cmd_ctrl(struct mtd_info *mtd, int command,
+			 unsigned int ctrl)
+{
+	struct nand_chip *nand;
+	struct denali_nand_priv *priv;
+	u32 map_ctl;
+
+	nand = mtd->priv;
+	priv = nand->priv;
+
+	map_ctl = DNL_MAP_11_MASK;
+	map_ctl |= priv->chip_num << DNL_CHIP_SHIFT;
+
+	if (command == NAND_CMD_NONE)
+		return ;
+
+	/*
+	 * depending on address, or command cycle, set map_ctl with the
+	 * correct bits.
+	 */
+	if (ctrl & NAND_CLE)
+		map_ctl |= DNL_MAP_11_CMD_MASK;
+	else if (ctrl & NAND_ALE)
+		map_ctl |= DNL_MAP_11_ADDR_MASK;
+	else
+		BUG();
+
+	dnl_map_write(priv, command & 0xff, map_ctl);
+}
+
+/*
+ * generate needed address cycles to output column and page to the NAND
+ * bus.
+ */
+static void dnl_shift_addresses(struct mtd_info *mtd,
+				int column, int page)
+{
+	struct nand_chip *nand;
+
+	nand = mtd->priv;
+
+	if (column != -1) {
+		nand->cmd_ctrl(mtd, column, NAND_ALE);
+		nand->cmd_ctrl(mtd, column >> 8, NAND_ALE);
+	}
+
+	if (page != -1) {
+		nand->cmd_ctrl(mtd, page, NAND_ALE);
+		nand->cmd_ctrl(mtd, page >> 8, NAND_ALE);
+		if (nand->chipsize > (128 << 20))
+			nand->cmd_ctrl(mtd, page >> 16, NAND_ALE);
+	}
+}
+
+/*
+ * our cmdfunc callback. this duplicates some code from the upper
+ * layer nand_command_lp() function. page READ (NAND_CMD_READ0
+ * commands) are issued using MAP01/MAP10 commands which are faster.
+ */
+static void dnl_cmdfunc(struct mtd_info *mtd, unsigned int command,
+			int column, int page_addr)
+{
+	struct nand_chip *nand;
+	struct denali_nand_priv *priv;
+
+	nand = mtd->priv;
+	priv = nand->priv;
+
+	switch (command) {
+	case NAND_CMD_RESET:
+		dnl_reset_bank(priv);
+		break;
+
+	case NAND_CMD_READID:
+		/*
+		 * read id page. set bufmode to map11 so that upper
+		 * layer can read the result using the correct method.
+		 */
+		nand->cmd_ctrl(mtd, NAND_CMD_READID, NAND_CLE);
+		dnl_shift_addresses(mtd, column, page_addr);
+		udelay(35);
+		priv->buf_mode = E_BUFMODE_MAP11;
+		break;
+
+	case NAND_CMD_PARAM:
+		nand->cmd_ctrl(mtd, NAND_CMD_PARAM, NAND_CLE);
+		dnl_shift_addresses(mtd, column, page_addr);
+		udelay(35);
+		break;
+
+	case NAND_CMD_SEQIN:
+	case NAND_CMD_READ0:
+		priv->page = page_addr;
+		priv->page = page_addr;
+		break;
+
+	case NAND_CMD_STATUS:
+		/*
+		 * issue status register read command, and tell
+		 * read_buf/read_byte to use MAP11.
+		 */
+		nand->cmd_ctrl(mtd, NAND_CMD_STATUS, NAND_CLE);
+		priv->buf_mode = E_BUFMODE_MAP11;
+		break;
+
+
+	case NAND_CMD_PAGEPROG:
+		break;
+
+	default:
+		printk("warning: unhandled command %x (please report)\n",
+		       command);
+		return ;
+	}
+
+	ndelay(100);
+}
+
+static inline u32 ceil_div(u32 x, u32 y)
+{
+	if (x % y)
+		return x / y + 1;
+	else
+		return x / y;
+}
+
+#define CLK_X		5
+#define CLK_MULTI	4
+
+/*
+ * calculate ONFI timings for given onfi mode. copied from spectra
+ * driver, should yield the same timings.
+ */
+static void dnl_calc_onfi_timings(struct denali_nand_priv *priv,
+			       int onfi_mode)
+{
+	static const u8 Trea[6]	 = { 40, 30, 25, 20, 20, 16 };
+	static const u8 Trp[6]	 = { 50, 25, 17, 15, 12, 10 };
+	static const u8 Treh[6]	 = { 30, 15, 15, 10, 10, 7 };
+	static const u8 Trc[6]	 = { 100, 50, 35, 30, 25, 20 };
+	static const u8 Trhoh[6] = { 0, 15, 15, 15, 15, 15 };
+	static const u8 Trloh[6] = { 0, 0, 0, 0, 5, 5 };
+	static const u8 Tcea[6]	 = { 100, 45, 30, 25, 25, 25 };
+	static const u8 Tadl[6]	 = { 200, 100, 100, 100, 70, 70 };
+	static const u8 Trhw[6]	 = { 200, 100, 100, 100, 100, 100 };
+	static const u8 Trhz[6]	 = { 200, 100, 100, 100, 100, 100 };
+	static const u8 Twhr[6]	 = { 120, 80, 80, 60, 60, 60 };
+	static const u8 Tcs[6]	 = { 70, 35, 25, 25, 20, 15 };
+
+	u16 en_lo, en_hi;
+	u16 acc_clks;
+	u16 dv_window = 0;
+	u16 addr_2_data;
+	u16 re_2_we;
+	u16 re_2_re;
+	u16 we_2_re;
+	u16 cs_cnt;
+
+	en_lo = ceil_div(Trp[onfi_mode], CLK_X);
+	en_hi = ceil_div(Treh[onfi_mode], CLK_X);
+
+	if (en_hi * CLK_X < Treh[onfi_mode] + 2)
+		++en_hi;
+	if (CLK_X * (en_lo + en_hi) < Trc[onfi_mode] + 2)
+		en_lo += ceil_div(Trc[onfi_mode] - (en_lo + en_hi) * CLK_X,
+				  CLK_X);
+
+	if (en_lo + en_hi < CLK_MULTI)
+		en_lo += CLK_MULTI - en_lo - en_hi;
+
+	while (1) {
+		u16 data_invalid_rhoh, data_invalid_rloh, data_invalid;
+
+		data_invalid_rhoh = en_lo * CLK_X + Trhoh[onfi_mode];
+		data_invalid_rloh = (en_lo + en_hi) * CLK_X + Trloh[onfi_mode];
+		data_invalid = min(data_invalid_rhoh, data_invalid_rloh);
+
+		dv_window = data_invalid - Trea[onfi_mode];
+		if (dv_window >= 8)
+			break;
+		++en_lo;
+	}
+
+	acc_clks = ceil_div(Trea[onfi_mode], CLK_X);
+	while (acc_clks * CLK_X - Trea[onfi_mode] < 3)
+		++acc_clks;
+
+	addr_2_data = ceil_div(Tadl[onfi_mode], CLK_X);
+	re_2_we = ceil_div(Trhw[onfi_mode], CLK_X);
+	re_2_re = ceil_div(Trhz[onfi_mode], CLK_X);
+	we_2_re = ceil_div(Twhr[onfi_mode], CLK_X);
+	cs_cnt = ceil_div(Tcs[onfi_mode] - Trp[onfi_mode], CLK_X);
+	if (cs_cnt == 0)
+		cs_cnt = 1;
+
+	if (Tcea[onfi_mode])
+		while (cs_cnt * CLK_X + Trea[onfi_mode] < Tcea[onfi_mode])
+			cs_cnt++;
+
+	/*
+	 * apply calculated timings.
+	 */
+	dnl_reg_writel(priv, acc_clks, DNL_ACC_CLKS_REG);
+	dnl_reg_writel(priv, re_2_we, DNL_RE_2_WE_REG);
+	dnl_reg_writel(priv, re_2_re, DNL_RE_2_RE_REG);
+	dnl_reg_writel(priv, we_2_re, DNL_WE_2_RE_REG);
+	dnl_reg_writel(priv, addr_2_data, DNL_ADDR_2_DATA_REG);
+	dnl_reg_writel(priv, en_lo, DNL_EN_LO_CNT_REG);
+	dnl_reg_writel(priv, en_hi, DNL_EN_HI_CNT_REG);
+	dnl_reg_writel(priv, cs_cnt, DNL_CS_SETUP_CNT_REG);
+}
+
+static void dnl_set_slowest_timings(struct denali_nand_priv *priv)
+{
+	priv->buf_mode = E_BUFMODE_MAP11;
+
+	/*
+	 * use slowest and safest timing possible to read ONFI
+	 * parameter page. we will stay in this mode if we cannot read
+	 * the ONFI parameter page.
+	 */
+	dnl_calc_onfi_timings(priv, 0);
+}
+
+static int dnl_configure_timings(struct denali_nand_priv *priv)
+{
+	struct mtd_info *mtd;
+	struct nand_chip *nand;
+	u16 timing_modes;
+	int mode;
+
+	mtd = priv->mtd;
+	nand = mtd->priv;
+
+	timing_modes = le16_to_cpu(nand->onfi_params.async_timing_mode);
+
+	/*
+	 * walk bitfield storing supported ONFI timings, use the
+	 * highest available mode. start from fastest possible mode
+	 * (mode 5) and go down until we found one mode that is
+	 * supported.
+	 */
+	for (mode = max_mode; mode > 0; --mode) {
+		if (timing_modes & (1 << mode))
+			break;
+	}
+	printk(KERN_INFO PFX "using ONFI timing mode %i\n", mode);
+	dnl_calc_onfi_timings(priv, mode);
+
+	return 0;
+}
+
+static int dnl_reset_bank(struct denali_nand_priv *priv)
+{
+	u32 reg;
+	u32 status;
+
+	dnl_clear_all_interrupts(priv);
+
+	/*
+	 * reset controller.
+	 */
+	reg = dnl_reg_readl(priv, DNL_DEVICE_RESET_REG);
+	reg |= (1 << priv->chip_num);
+	dnl_reg_writel(priv, reg, DNL_DEVICE_RESET_REG);
+
+	/*
+	 * wait for reset completion.
+	 */
+	if (dnl_spin_for_mask(priv, DNL_INT_RESET_DONE | DNL_INT_WDOG_TIMEOUT,
+			      &status) < 0) {
+		printk("timeouted waiting for device reset.\n");
+		return -ETIMEDOUT;
+	}
+
+	if (status & DNL_INT_WDOG_TIMEOUT) {
+		printk("internal hardware watchdog triggered.\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	int err;
+	struct mtd_info *mtd;
+	struct nand_chip *nand;
+	struct denali_nand_priv *priv;
+
+	err = pci_enable_device(dev);
+	if (err) {
+		printk(KERN_ERR PFX "unable to enable pci device: %i.\n", err);
+		return err;
+	}
+
+	priv = kzalloc(sizeof (*priv), GFP_KERNEL);
+	if (!priv) {
+		err = -ENOMEM;
+		goto out_disable_device;
+	}
+	dev_set_drvdata(&dev->dev, priv);
+	priv->dev = dev;
+
+	/*
+	 * mem zone is on the first pci resource, map xx access is done here.
+	 */
+	priv->mem_phys = pci_resource_start(dev, 0);
+	priv->mem_size = pci_resource_end(dev, 0) - priv->mem_phys + 1;
+
+	/*
+	 * registers are on the second pci resource.
+	 */
+	priv->regs_phys = pci_resource_start(dev, 1);
+	priv->regs_size = pci_resource_end(dev, 1) - priv->regs_phys + 1;
+
+	priv->mem = ioremap(priv->mem_phys, priv->mem_size);
+	if (!priv->mem) {
+		err = -ENOMEM;
+		goto out_free_priv;
+	}
+
+	priv->regs = ioremap(priv->regs_phys, priv->regs_size);
+	if (!priv->regs) {
+		err = -ENOMEM;
+		goto out_unmap_mem;
+	}
+
+	mtd = kzalloc(sizeof (*mtd), GFP_KERNEL);
+	if (!mtd) {
+		err = -ENOMEM;
+		goto out_unmap_regs;
+	}
+	priv->mtd = mtd;
+
+	nand = kzalloc(sizeof (*nand), GFP_KERNEL);
+	if (!nand) {
+		err = -ENOMEM;
+		goto out_free_mtd;
+	}
+
+	mtd->priv = nand;
+	mtd->owner = THIS_MODULE;
+
+	/*
+	 * the chip may support it but the controller makes it a pain
+	 * to handle.
+	 */
+	nand->options = NAND_NO_RNDOUT;
+
+	nand->priv = priv;
+	nand->read_byte = dnl_read_byte;
+	nand->write_buf = dnl_write_buf;
+	nand->read_buf = dnl_read_buf;
+	nand->cmd_ctrl = dnl_cmd_ctrl;
+
+	if (map_mode == 11) {
+		/*
+	 	* always use MAP11 accesses, will be slower, but may be
+	 	* usefull for debug.
+	 	*/
+		printk(KERN_INFO PFX "using MAP11 for ALL accesses (slow).\n");
+		priv->buf_mode = E_BUFMODE_MAP11;
+		nand->ecc.mode = NAND_ECC_SOFT;
+		nand->chip_delay = 35;
+
+	} else {
+		/*
+	 	 * use our provided cmdfunc, with the ->ecc callbacks
+	 	 * along, things will go much more faster.
+	 	 */
+		nand->cmdfunc = dnl_cmdfunc;
+
+		nand->ecc.mode = NAND_ECC_SOFT;
+		nand->ecc.read_page_raw = dnl_read_page_raw;
+		nand->ecc.write_page_raw = dnl_write_page_raw;
+		nand->ecc.read_oob = dnl_read_oob;
+		nand->ecc.write_oob = dnl_write_oob;
+		nand->erase = dnl_erase;
+	}
+
+	dnl_clear_all_interrupts(priv);
+	dnl_reset_bank(priv);
+	dnl_set_slowest_timings(priv);
+
+	/*
+	 * enable prefetch on page read, to speed up things.
+	 */
+	dnl_reg_writel(priv, 1, DNL_PREFETCH_MODE);
+
+	/*
+	 * disable ECC verification/generation on page read/write.
+	 */
+	dnl_reg_writel(priv, 0, DNL_ECC_ENABLE_REG);
+
+	/*
+	 * allocate read buffer: size should be main size + oob
+	 * size. we do not have the mtd fields populated yet with
+	 * these values, but controller registers do already have them
+	 * populated.
+	 */
+	priv->read_buf_size = dnl_reg_readl(priv, DNL_MAIN_SIZE_REG) +
+		dnl_reg_readl(priv, DNL_SPARE_SIZE_REG);
+	priv->read_buf = kmalloc(2 * 4096, GFP_KERNEL);
+	if (!priv->read_buf) {
+		goto out_free_nand;
+		err = -ENOMEM;
+	}
+
+	if (pci_set_dma_mask(dev, DMA_BIT_MASK(32)) < 0) {
+		printk(KERN_ERR PFX "32bit dma not supported.\n");
+		goto out_free_read_buf;
+	}
+	priv->read_buf_dma = dma_map_single(&dev->dev, priv->read_buf,
+					    priv->read_buf_size,
+					    DMA_BIDIRECTIONAL);
+	if (dma_mapping_error(&dev->dev, priv->read_buf_dma)) {
+		printk(PFX KERN_ERR "unable to map read_buf for dma.\n");
+		goto out_free_read_buf;
+	}
+
+	/*
+	 * FIXME: 4 chips can be supported
+	 */
+	err = nand_scan_ident(mtd, 1, NULL);
+	if (err < 0)
+		goto out_pci_unmap_single;
+
+	if (map_mode != 11)
+		/*
+		 * FIXME: nand_scan_ident does not preserve our
+		 * erase_cmd.
+		 */
+		nand->erase = dnl_erase;
+
+
+
+	err = nand_scan_tail(mtd);
+	if (err < 0)
+		goto out_pci_unmap_single;
+
+
+	if (nand->onfi_version)
+		dnl_configure_timings(priv);
+
+	mtd->name = "denali_nand";
+	err = mtd_device_parse_register(mtd, parts_parsers, 0, NULL, 0);
+	if (err) {
+		printk(KERN_WARNING PFX "unable to register MTD dev.\n");
+		goto out_pci_unmap_single;
+	}
+
+	return 0;
+
+out_pci_unmap_single:
+	pci_unmap_single(dev, priv->read_buf_dma, priv->read_buf_size,
+			 PCI_DMA_BIDIRECTIONAL);
+out_free_read_buf:
+	kfree(priv->read_buf);
+out_free_nand:
+	kfree(nand);
+out_free_mtd:
+	kfree(mtd);
+out_unmap_regs:
+	iounmap(priv->regs);
+out_unmap_mem:
+	iounmap(priv->mem);
+out_free_priv:
+	kfree(priv);
+out_disable_device:
+	pci_disable_device(dev);
+	return err;
+}
+
+static void denali_pci_remove(struct pci_dev *dev)
+{
+	struct denali_nand_priv *priv;
+
+	priv = dev_get_drvdata(&dev->dev);
+
+	mtd_device_unregister(priv->mtd);
+	pci_unmap_single(dev, priv->read_buf_dma, priv->read_buf_size,
+			 PCI_DMA_BIDIRECTIONAL);
+	kfree(priv->read_buf);
+	kfree(priv->mtd->priv);
+	kfree(priv->mtd);
+
+	iounmap(priv->regs);
+	iounmap(priv->mem);
+
+	kfree(priv);
+	pci_disable_device(dev);
+}
+
+const struct pci_device_id denali_pci_table[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0701) },
+	{ 0, },
+};
+
+struct pci_driver	denali_nand_pci_driver =
+{
+	.name		= "denali_nand",
+	.id_table	= denali_pci_table,
+	.probe		= denali_pci_probe,
+	.remove		= denali_pci_remove,
+};
+
+static int __init denali_nand_init(void)
+{
+	int err;
+
+	err = pci_register_driver(&denali_nand_pci_driver);
+	if (err) {
+		printk(KERN_ERR PFX "pci_register_driver failed: %i.\n", err);
+		return err;
+	}
+	return 0;
+}
+
+static void __exit denali_nand_exit(void)
+{
+	pci_unregister_driver(&denali_nand_pci_driver);
+}
+
+module_init(denali_nand_init);
+module_exit(denali_nand_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Nicolas Schichan <nschichan@freebox.fr>");
+MODULE_DESCRIPTION("Denali NAND driver");
--- /dev/null	2015-07-31 18:17:35.952031993 +0200
+++ linux-4.2-fbx/drivers/mtd/nand/denali_nand.h	2010-08-04 16:42:32.987933944 +0200
@@ -0,0 +1,165 @@
+
+#ifndef __DENALI_NAND_H
+# define __DENALI_NAND_H
+
+struct mtd_info;
+
+enum
+{
+	E_BUFMODE_MAP01,
+	E_BUFMODE_MAP11,
+};
+
+struct denali_nand_priv
+{
+	int		chip_num;
+	unsigned long	regs_phys;
+	unsigned long	regs_size;
+
+	unsigned long	mem_phys;
+	unsigned long	mem_size;
+
+	void __iomem	*regs;
+	void __iomem	*mem;
+
+	u8		*read_buf;
+	int		read_buf_size;
+	int		read_buf_offset;
+	int		page;
+
+
+	int		buf_mode;
+
+	dma_addr_t	read_buf_dma;
+
+	struct pci_dev *dev;
+	struct mtd_info	*mtd;
+};
+
+#define DNL_DEVICE_RESET_REG		0x0
+
+#define DNL_XFER_SPARE_REG		(0x4 * 4)
+
+#define DNL_CE_REG			(0x34 * 4)
+#define  DNL_CE_DISABLE			(1 << 0)
+
+#define DNL_RB_PIN_ENABLED_REG		(0x18 * 4)
+# define DNL_RB_PIN_B0_EN		(1 << 0)
+# define DNL_RB_PIN_B1_EN		(1 << 1)
+# define DNL_RB_PIN_B2_EN		(1 << 2)
+# define DNL_RB_PIN_B3_EN		(1 << 3)
+
+#define DNL_PREFETCH_MODE		(0x30 * 4)
+#define DNL_ECC_ENABLE_REG		(0x38 * 4)
+
+#define DNL_INT_ENABLE_REG		(0x3c * 4)
+# define DNL_INT_ENABLE			(1 << 0)
+
+#define DNL_MAIN_SIZE_REG		(0x5c * 4)
+#define DNL_SPARE_SIZE_REG		(0x60 * 4)
+
+#define DNL_0_INTR_STATUS_REG		(0x104 * 4)
+#define DNL_0_INTR_EN_REG		(0x108 * 4)
+#define DNL_0_PAGE_COUNT_REG		(0x10c * 4)
+#define DNL_0_ERR_ADDR_REG		(0x110 * 4)
+#define DNL_0_ERR_BLOCK_REG		(0x114 * 4)
+
+#define DNL_1_INTR_STATUS_REG		(0x118 * 4)
+#define DNL_1_INTR_EN_REG		(0x11c * 4)
+#define DNL_1_PAGE_COUNT_REG		(0x120 * 4)
+#define DNL_1_ERR_ADDR_REG		(0x124 * 4)
+#define DNL_1_ERR_BLOCK_REG		(0x128 * 4)
+
+#define DNL_2_INTR_STATUS_REG		(0x12c * 4)
+#define DNL_2_INTR_EN_REG		(0x130 * 4)
+#define DNL_2_PAGE_COUNT_REG		(0x134 * 4)
+#define DNL_2_ERR_ADDR_REG		(0x138 * 4)
+#define DNL_2_ERR_BLOCK_REG		(0x13c * 4)
+
+#define DNL_3_INTR_STATUS_REG		(0x140 * 4)
+#define DNL_3_INTR_EN_REG		(0x144 * 4)
+#define DNL_3_PAGE_COUNT_REG		(0x148 * 4)
+#define DNL_3_ERR_ADDR_REG		(0x14c * 4)
+#define DNL_3_ERR_BLOCK_REG		(0x150 * 4)
+
+/*
+ * interrupt cause bits valid for all 4 controllers.
+ */
+#define DNL_INT_DMA_DATA_CMD_COMPLETE	(1 << 2)
+#define DNL_INT_WDOG_TIMEOUT		(1 << 3)
+#define DNL_INT_PROGRAM_FAIL		(1 << 4)
+#define DNL_INT_ERASE_FAILED		(1 << 5)
+#define DNL_INT_LOAD_COMPLETE		(1 << 6)
+#define DNL_INT_PROGRAM_COMPLETE	(1 << 7)
+#define DNL_INT_ERASE_COMPLETE		(1 << 8)
+#define DNL_INT_BAD_CMD_SEQ		(1 << 11)
+#define DNL_INT_RESET_DONE		(1 << 13)
+
+
+#define DNL_SKIP_BYTE_REG		(0x8c * 4)
+#define DNL_SPACE_AREA_MARKER_REG	(0x90 * 4)
+
+#define DNL_MANUFACTURER_REG		(0xc0 * 4)
+
+#define DNL_PAGE_SIZE			(0xd4 * 4)
+#define DNL_SPARE_SIZE			(0xd8 * 4)
+
+/*
+ * timing configuration registers
+ */
+#define DNL_WE_2_RE_REG			(0x40 * 4)
+#define DNL_ADDR_2_DATA_REG		(0x44 * 4)
+#define DNL_RE_2_WE_REG			(0x48 * 4)
+#define DNL_ACC_CLKS_REG		(0x4c * 4)
+
+#define DNL_EN_LO_CNT_REG		(0x7c * 4)
+#define DNL_EN_HI_CNT_REG		(0x80 * 4)
+#define DNL_CS_SETUP_CNT_REG		(0x88 * 4)
+#define DNL_RE_2_RE_REG			(0xa4 * 4)
+
+#define DNL_XFER_MODE			(0x100 * 4)
+
+#define DNL_DMA_ENABLE			(0x1c0 * 4)
+
+/*
+ * map xx indirect read/write accessors
+ */
+#define DNL_MAP_01_MASK		0x04000000
+#define DNL_MAP_10_MASK		0x08000000
+#define DNL_MAP_11_MASK		0x0c000000
+
+#define DNL_CHIP_MASK		0x03000000
+#define DNL_CHIP_SHIFT		(24)
+#define DNL_MAP_11_CMD_MASK	(0x0)
+#define DNL_MAP_11_ADDR_MASK	(0x1)
+#define DNL_MAP_11_DATA_MASK	(0x2)
+
+#define DNL_MAP_CTL_REG		0x00
+#define DNL_MAP_DATA_REG	0x10
+
+#define DNL_XFER_SPARE_ONLY		0x41
+#define DNL_XFER_MAIN_ONLY		0x42
+#define DNL_XFER_SPARE_AND_MAIN		0x43
+
+#define DNL_MAP10_READAHEAD_ONCE	0x2001
+
+enum {
+	DNL_E_DMA_READ,
+	DNL_E_DMA_PROGRAM,
+};
+
+#define DNL_MAP10_ERASE_COMMAND		0x1
+
+/*
+ * DMA command sequence.
+ */
+#define DNL_MAP10_DMA_READ_PAGE		0x2001
+#define DNL_MAP10_DMA_WRITE_PAGE	0x2101
+#define DNL_MAP10_DMA_SET_ADDR_HI	0x2200
+#define DNL_MAP10_DMA_SET_ADDR_LO	0x2300
+#define DNL_MAP10_DMA_SET_PARAMS	0x2400
+
+#define DNL_DMA_PARAM_GEN_INT		(1 << 16)
+#define DNL_DMA_BURST_64		(0x40 << 8)
+
+#endif /* !__DENALI_NAND_H */
diff -Nruw linux-4.2-fbx/drivers/net/ethernet/sigma./Kconfig linux-4.2-fbx/drivers/net/ethernet/sigma/Kconfig
--- linux-4.2-fbx/drivers/net/ethernet/sigma./Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/net/ethernet/sigma/Kconfig	2015-09-15 19:18:38.266456783 +0200
@@ -0,0 +1,21 @@
+#
+# Marvell device configuration
+#
+
+config NET_VENDOR_SIGMA
+	bool "Sigma Design devices"
+	default y
+	depends on TANGO2
+
+if NET_VENDOR_SIGMA
+
+config TANGO2_ENET
+	tristate "SMP863x Builtin Ethernet support"
+	select MII
+	select CRC32
+	help
+	 This option adds support for the SMP863x integrated Ethernet
+	 controller.  This driver uses NAPI and generic Linux MII
+	 support.
+
+endif # NET_VENDOR_SIGMA
diff -Nruw linux-4.2-fbx/drivers/net/ethernet/sigma./Makefile linux-4.2-fbx/drivers/net/ethernet/sigma/Makefile
--- linux-4.2-fbx/drivers/net/ethernet/sigma./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/net/ethernet/sigma/Makefile	2015-09-15 19:18:38.266456783 +0200
@@ -0,0 +1 @@
+obj-$(CONFIG_TANGO2_ENET) += tango2_enet/tango2_enet.o
diff -Nruw linux-4.2-fbx/drivers/net/ethernet/wintegra./Kconfig linux-4.2-fbx/drivers/net/ethernet/wintegra/Kconfig
--- linux-4.2-fbx/drivers/net/ethernet/wintegra./Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/net/ethernet/wintegra/Kconfig	2013-12-04 14:33:20.027478990 +0100
@@ -0,0 +1,10 @@
+config NET_VENDOR_WINTEGRA
+	bool
+
+config WINTEGRA_WINPATH3_ETH
+	tristate "Wintegra Winpath3 internal mac support"
+	depends on WINTEGRA_WINPATH3
+	select NET_VENDOR_WINTEGRA
+	select NET_CORE
+	select MII
+	select PHYLIB
diff -Nruw linux-4.2-fbx/drivers/net/ethernet/wintegra./Makefile linux-4.2-fbx/drivers/net/ethernet/wintegra/Makefile
--- linux-4.2-fbx/drivers/net/ethernet/wintegra./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/net/ethernet/wintegra/Makefile	2013-12-04 14:33:20.027478990 +0100
@@ -0,0 +1 @@
+obj-$(CONFIG_WINTEGRA_WINPATH3_ETH) += wp3_eth.o
diff -Nruw linux-4.2-fbx/drivers/platform/intelce./dfx.c linux-4.2-fbx/drivers/platform/intelce/dfx.c
--- linux-4.2-fbx/drivers/platform/intelce./dfx.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/platform/intelce/dfx.c	2013-12-04 14:33:20.395478996 +0100
@@ -0,0 +1,286 @@
+/*
+ * Intel CE DFX fuse SysFS export
+ *
+ * Copyright (C) 2009, Florian Fainelli <ffainelli@freebox.fr>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/sysfs.h>
+
+#define DFX_IO_SIZE	(64 * 1024)
+#define PFX		KBUILD_MODNAME
+
+#define DFX_ID_CODE	0x24
+#define DFX_SKU		0x28
+#define DFX_SN1		0x40
+#define DFX_SN2		0x44
+#define DFX_VCFG	0x64
+
+#define CW_CFG_BASE	0xA0000010
+#define DDR_SPEED	0x4
+
+#define CW_BRD_MASK	0x3
+#define CW_SEC_BOOT	7
+#define CW_VDAC_CAL	14
+
+#define DDR_SPEED_MASK	0x7
+
+static void __iomem *dfx_base;
+static void __iomem *cw_cfg_base;
+
+static ssize_t show_fuse_id_code(struct device *dev, struct device_attribute
+		      *devattr, char *buf)
+{
+	return sprintf(buf, "%04x\n",
+			ioread32(dfx_base + DFX_ID_CODE) >> 19 & 0xf);
+}
+
+static ssize_t show_sku_id(struct device *dev, struct device_attribute
+			*devattr, char *buf)
+{
+	return sprintf(buf, "%06x\n", ioread32(dfx_base + DFX_SKU) & 0x7f);
+}
+
+static ssize_t show_dev_serial1(struct device *dev, struct device_attribute
+			*devattr, char *buf)
+{
+	return sprintf(buf, "%08x\n", ioread32(dfx_base + DFX_SN1));
+}
+
+static ssize_t show_dev_serial2(struct device *dev, struct device_attribute
+			*devattr, char *buf)
+{
+	return sprintf(buf, "%08x\n", ioread32(dfx_base + DFX_SN2));
+}
+
+static ssize_t show_ca_vendor_cfg(struct device *dev, struct device_attribute
+			*devattr, char *buf)
+{
+	u32 vcfg = ioread32(dfx_base + DFX_VCFG);
+
+	return sprintf(buf, "%2x%2x\n", (vcfg >> 10) & 0xff, vcfg & 0xff);
+}
+
+static DEVICE_ATTR(fuse_id_code, S_IRUGO, show_fuse_id_code, NULL);
+static DEVICE_ATTR(sku_id, S_IRUGO, show_sku_id, NULL);
+static DEVICE_ATTR(dev_serial1, S_IRUGO, show_dev_serial1, NULL);
+static DEVICE_ATTR(dev_serial2, S_IRUGO, show_dev_serial2, NULL);
+static DEVICE_ATTR(ca_vendor_cfg, S_IRUGO, show_ca_vendor_cfg, NULL);
+
+#define CW_SHOW_ATTR(_name, _bit)					\
+static ssize_t show_##_name(struct device *dev, struct device_attribute \
+			*devattr, char *buf)				\
+{									\
+	return sprintf(buf, "%d\n", (readl(cw_cfg_base) &		\
+				(1 << _bit)) >> _bit);			\
+}									\
+static DEVICE_ATTR(_name, S_IRUGO, show_##_name, NULL);			\
+
+CW_SHOW_ATTR(trusted_mode, CW_SEC_BOOT);
+CW_SHOW_ATTR(vdac_cal, CW_VDAC_CAL);
+
+static ssize_t show_board_model(struct device *dev, struct device_attribute
+			*devattr, char *buf)
+{
+	u32 val = readl(cw_cfg_base) & CW_BRD_MASK;
+	const char *board;
+
+	switch (val) {
+	case 0:
+		board = "GoldenBeach";
+		break;
+	case 1:
+		board = "ChesapeakeBay";
+		break;
+	case 2:
+		board = "FalconFalls";
+		break;
+	case 3:
+		board = "PowerHouseLake";
+		break;
+	default:
+		board = "unknown";
+		break;
+	}
+
+	return sprintf(buf, "%s\n", board);
+}
+
+static DEVICE_ATTR(board_model, S_IRUGO, show_board_model, NULL);
+
+static ssize_t show_ddr_type(struct device *dev, struct device_attribute
+			*devattr, char *buf)
+{
+	u32 speed = (readl(cw_cfg_base + DDR_SPEED) >> 6) & DDR_SPEED_MASK;
+	const char *type;
+	const char *freq;
+
+	if (speed >= 4)
+		type = "DDR2";
+	else
+		type = "DDR3";
+
+	switch (speed) {
+	case 0:
+		freq = "800";
+		break;
+	case 1:
+		freq = "1066";
+		break;
+	case 2:
+		freq = "1333";
+		break;
+	case 3:
+		freq = "1600";
+		break;
+	case 4:
+		freq = "800";
+		break;
+	default:
+		freq = "unknown";
+		break;
+	}
+
+	return sprintf(buf, "%s (%s Mhz)\n", type, freq);
+}
+
+static DEVICE_ATTR(ddr_type, S_IRUGO, show_ddr_type, NULL);
+
+static struct attribute *intelce_dfx_attributes[] = {
+	&dev_attr_fuse_id_code.attr,
+	&dev_attr_sku_id.attr,
+	&dev_attr_dev_serial1.attr,
+	&dev_attr_dev_serial2.attr,
+	&dev_attr_ca_vendor_cfg.attr,
+	&dev_attr_trusted_mode.attr,
+	&dev_attr_vdac_cal.attr,
+	&dev_attr_board_model.attr,
+	&dev_attr_ddr_type.attr,
+	NULL
+};
+
+static const struct attribute_group intelce_dfx_group = {
+	.name = "intelce-dfx",
+	.attrs = intelce_dfx_attributes,
+};
+
+static int intelce_dfx_probe(struct pci_dev *pdev,
+			     const struct pci_device_id *id)
+{
+	int err;
+	int bar = 0;
+
+	err = pci_enable_device(pdev);
+	if (err)
+		goto err_out;
+
+	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+	if (err) {
+		printk(KERN_ERR PFX ": 32-bit PCI DMA addresses"
+				"not supported by the card\n");
+		goto err_out;
+	}
+
+	err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+	if (err) {
+		printk(KERN_ERR PFX ": 32-bit PCI DMA addresses"
+				"not supported by the card\n");
+		goto err_out;
+	}
+
+	if (pci_resource_len(pdev, bar) < DFX_IO_SIZE) {
+		printk(KERN_ERR PFX ": Insufficient PCI resources, aborting\n");
+		err = -EIO;
+		goto err_out;
+	}
+
+	pci_set_master(pdev);
+
+	err = pci_request_regions(pdev, PFX);
+	if (err) {
+		printk(KERN_ERR PFX ": could not request PCI regions\n");
+		err = -EIO;
+		goto err_out;
+	}
+
+	dfx_base = pci_iomap(pdev, bar, DFX_IO_SIZE);
+	if (!dfx_base) {
+		printk(KERN_ERR PFX ": ioremap failed for device: %s\n",
+				pci_name(pdev));
+		err = -ENOMEM;
+		goto err_release_regions;
+	}
+
+	cw_cfg_base = ioremap(CW_CFG_BASE, 0x7);
+	if (!cw_cfg_base) {
+		printk(KERN_ERR PFX ": ioremap for CW[] failed\n");
+		err = -ENOMEM;
+		goto err_iounmap;
+	}
+
+	pci_set_drvdata(pdev, dfx_base);
+
+	err = sysfs_create_group(&pdev->dev.kobj, &intelce_dfx_group);
+	if (err) {
+		printk(KERN_ERR PFX ": unable to create sysfs group\n");
+		goto err_iounmap;
+	}
+
+	dev_info(&pdev->dev, "at 0x%p\n", dfx_base);
+
+	return 0;
+
+err_iounmap:
+	iounmap(cw_cfg_base);
+	pci_iounmap(pdev, dfx_base);
+err_release_regions:
+	pci_release_regions(pdev);
+err_out:
+	return err;
+}
+
+static void __exit intelce_dfx_remove(struct pci_dev *pdev)
+{
+	sysfs_remove_group(&pdev->dev.kobj, &intelce_dfx_group);
+	iounmap(cw_cfg_base);
+	pci_iounmap(pdev, dfx_base);
+	pci_set_drvdata(pdev, NULL);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+}
+
+static struct pci_device_id intelce_dfx_id_tbl[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e6d) },
+	{ 0 }
+};
+
+static struct pci_driver intelce_dfx_driver = {
+	.name		= "intelce-dfx",
+	.id_table	= intelce_dfx_id_tbl,
+	.probe		= intelce_dfx_probe,
+	.remove		= intelce_dfx_remove,
+};
+
+static int __init intelce_dfx_init(void)
+{
+	return pci_register_driver(&intelce_dfx_driver);
+}
+
+static void __exit intelce_dfx_exit(void)
+{
+	pci_unregister_driver(&intelce_dfx_driver);
+}
+
+module_init(intelce_dfx_init);
+module_exit(intelce_dfx_exit);
+
+MODULE_AUTHOR("Florian Fainelli <ffainelli@freebox.fr>");
+MODULE_DESCRIPTION("Intel CE 3100/4100 sysfs fuse reporting");
+MODULE_VERSION("0.1");
+MODULE_LICENSE("GPL");
diff -Nruw linux-4.2-fbx/drivers/platform/intelce./gpio-intelce.c linux-4.2-fbx/drivers/platform/intelce/gpio-intelce.c
--- linux-4.2-fbx/drivers/platform/intelce./gpio-intelce.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/platform/intelce/gpio-intelce.c	2013-12-04 14:33:20.395478996 +0100
@@ -0,0 +1,590 @@
+/*
+ * GPIO bus driver for the Intel CE3100/4100 SoC
+ *
+ * Copyright (C) 2009, Florian Fainelli <ffainelli@freebox.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/gpio.h>
+
+#define DRV_NAME		"intelce-gpio"
+#define DRV_VERSION		"0.1"
+
+#define GEN3_GPIO_IO_BASE	0x1080
+#define GEN3_GPIO_IO_SIZE	0x40
+#define GEN3_NUM_GPIO_PINS	26
+
+#define NR_BUILTIN_GPIO		GEN3_NUM_GPIO_PINS
+#define GEN3_GPIO_GROUPS	4
+
+/* Starting point for the different GPIO groups on intel_gen3 */
+#define GEN3_GPIO_GROUP_ZERO    0
+#define GEN3_GPIO_GROUP_ONE     12
+#define GEN3_GPIO_GROUP_TWO     15
+#define GEN3_GPIO_GROUP_THREE   22
+
+/* GPIO Group 0 */
+#define GEN3_GPIO0_GPOUTR	0x00
+#define GEN3_GPIO0_GPOER	0x04
+#define GEN3_GPIO0_GPINR	0x08
+#define GEN3_GPIO0_GPSTR	0x0C
+#define GEN3_GPIO0_GPIT1R0	0x10
+#define GEN3_GPIO0_INT		0x14
+#define GEN3_GPIO0_GPIT1R1	0x18
+#define GEN3_GPIO0_MUX_CNTL	0x1C
+
+/* GPIO Group 1*/
+#define GEN3_GPIO1_CGEN		0x00
+#define GEN3_GPIO1_CGIO		0x04
+#define GEN3_GPIO1_CGLV		0x08
+#define GEN3_GPIO1_CGTPE	0x0C
+#define GEN3_GPIO1_CGTNE	0x10
+#define GEN3_GPIO1_CGGPE	0x14
+#define GEN3_GPIO1_CGSMI	0x18
+#define GEN3_GPIO1_CGTS		0x1C
+
+/* GPIO Group 2 */
+#define GEN3_GPIO2_CGEN		0x00
+#define GEN3_GPIO2_CGIO		0x04
+#define GEN3_GPIO2_CGLV		0x08
+#define GEN3_GPIO2_CGTPE	0x0C
+#define GEN3_GPIO2_CGTNE	0x10
+#define GEN3_GPIO2_CGGPE	0x14
+#define GEN3_GPIO2_CGSMI	0x18
+#define GEN3_GPIO2_CGTS		0x1C
+#define GEN3_GPIO2_MUX_CNTL	0x1C
+
+/* GPIO Group 3 */
+#define GEN3_GPIO3_CGEN		0x20
+#define GEN3_GPIO3_CGIO		0x24
+#define GEN3_GPIO3_CGLV		0x28
+#define GEN3_GPIO3_CGTPE	0x2C
+#define GEN3_GPIO3_CGTNE	0x30
+#define GEN3_GPIO3_CGGPE	0x34
+#define GEN3_GPIO3_CGSMI	0x38
+#define GEN3_GPIO3_CGTS		0x3C
+
+/* Controller limits */
+#define INTELCE_GPIO_IO_SIZE	256
+
+#define GEN3_TYPE_PCI		0
+#define GEN3_TYPE_IOPORT	1
+
+/* gpio adapter private structure */
+struct intelce_gpio {
+	struct gpio_chip	chip;
+	struct pci_dev		*pdev;
+	void __iomem		*base;
+	u32			ioport;
+	unsigned int		type:1;
+};
+
+/* Group 0 GPIO helpers */
+static void intelce_gpio0_set_direction(struct gpio_chip *chip,
+				unsigned offset, int direction)
+{
+	u32 mask;
+	struct intelce_gpio *gpch;
+	gpch = container_of(chip, struct intelce_gpio, chip);
+
+	mask = ioread32(gpch->base + GEN3_GPIO0_GPOER);
+	if (direction)
+		mask |= (1 << offset);
+	else
+		mask &= ~(1 << offset);
+	iowrite32(mask, gpch->base + GEN3_GPIO0_GPOER);
+}
+
+static void intelce_gpio0_set_alt_func(struct gpio_chip *chip,
+				unsigned offset, int func)
+{
+	struct intelce_gpio *gpch;
+	unsigned bit;
+	u32 mask;
+	gpch = container_of(chip, struct intelce_gpio, chip);
+
+	if (offset <= 5)
+		bit = 0;
+	else if (offset <= 7)
+		bit = 1;
+	else
+		bit = 2;
+
+	/* Set functionnality */
+	mask = ioread32(gpch->base + GEN3_GPIO0_MUX_CNTL);
+	if (func)
+		mask |= (1 << bit);
+	else
+		mask &= ~(1 << bit);
+	iowrite32(mask, gpch->base + GEN3_GPIO0_MUX_CNTL);
+}
+
+/*
+ * GPIO lib stubs
+ * Note that you should call the direction
+ * helpers first which will set the muxing
+ * correctly
+ */
+static void intelce_gpio0_set_dataout(struct gpio_chip *chip,
+				unsigned offset, int value)
+{
+	u32 mask;
+	struct intelce_gpio *gpch;
+	gpch = container_of(chip, struct intelce_gpio, chip);
+
+	mask = ioread32(gpch->base + GEN3_GPIO0_GPOUTR);
+	if (value)
+		mask |= (1 << offset);
+	else
+		mask &= ~(1 << offset);
+	iowrite32(mask, gpch->base + GEN3_GPIO0_GPOUTR);
+}
+
+static int intelce_gpio0_get_datain(struct gpio_chip *chip,
+				unsigned offset)
+{
+	struct intelce_gpio *gpch;
+	gpch = container_of(chip, struct intelce_gpio, chip);
+
+	return ioread32(gpch->base + GEN3_GPIO0_GPINR) & (1 << offset);
+}
+
+static int intelce_gpio0_set_direction_input(struct gpio_chip *chip,
+				unsigned offset)
+{
+	/* Disable GPIO muxing */
+	intelce_gpio0_set_alt_func(chip, offset, 0);
+	intelce_gpio0_set_direction(chip, offset, 0);
+	return 0;
+}
+
+static int intelce_gpio0_set_direction_output(struct gpio_chip *chip,
+				unsigned offset, int value)
+{
+	/* Disable GPIO muxing */
+	intelce_gpio0_set_alt_func(chip, offset, 0);
+	intelce_gpio0_set_direction(chip, offset, 1);
+	intelce_gpio0_set_dataout(chip, offset, value);
+	return 0;
+}
+
+/* Group 1 GPIO helpers */
+static int intelce_gpio1_get_datain(struct gpio_chip *chip,
+				unsigned offset)
+{
+	struct intelce_gpio *gpch;
+	gpch = container_of(chip, struct intelce_gpio, chip);
+
+	return inl(gpch->ioport + GEN3_GPIO1_CGLV) & (1 << offset);
+}
+
+static void intelce_gpio1_set_dataout(struct gpio_chip *chip,
+				unsigned offset, int value)
+{
+	u32 mask;
+	struct intelce_gpio *gpch;
+	gpch = container_of(chip, struct intelce_gpio, chip);
+
+	mask = inl(gpch->ioport + GEN3_GPIO1_CGLV);
+	if (value)
+		mask |= (1 << offset);
+	else
+		mask &= ~(1 << offset);
+	outl(mask, gpch->ioport + GEN3_GPIO1_CGLV);
+}
+
+static void intelce_gpio1_set_direction(struct gpio_chip *chip,
+				unsigned offset, int direction)
+{
+	u32 mask;
+	struct intelce_gpio *gpch;
+	gpch = container_of(chip, struct intelce_gpio, chip);
+
+	/* Set the correct GPIO mode (no muxing) */
+	mask = inl(gpch->ioport + GEN3_GPIO1_CGEN);
+	mask |= (1 << offset);
+	outl(mask, gpch->ioport + GEN3_GPIO1_CGEN);
+
+	/* Set direction (0 = input, 1 = output) */
+	mask = inl(gpch->ioport + GEN3_GPIO1_CGIO);
+	if (direction)
+		mask &= ~(1 << offset);
+	else
+		mask |= (1 << offset);
+	outl(mask, gpch->ioport + GEN3_GPIO1_CGIO);
+}
+
+static int intelce_gpio1_set_direction_input(struct gpio_chip *chip,
+					unsigned offset)
+{
+	intelce_gpio1_set_direction(chip, offset, 0);
+	return 0;
+}
+
+static int intelce_gpio1_set_direction_output(struct gpio_chip *chip,
+				unsigned offset, int value)
+{
+	intelce_gpio1_set_direction(chip, offset, 1);
+	intelce_gpio1_set_dataout(chip, offset, value);
+	return 0;
+}
+
+/* Group 2 GPIO helpers */
+static void intelce_gpio2_set_dataout(struct gpio_chip *chip,
+				unsigned offset, int value)
+{
+	/* Rework base to call GPIO group 1 functions */
+	offset += chip->base - GEN3_GPIO_GROUP_ONE;
+	intelce_gpio1_set_dataout(chip, offset, value);
+}
+
+static int intelce_gpio2_get_datain(struct gpio_chip *chip,
+				unsigned offset)
+{
+	/* Rework base to call GPIO group 1 functions */
+	offset += chip->base - GEN3_GPIO_GROUP_ONE;
+	return intelce_gpio1_get_datain(chip, offset);
+}
+
+/*
+ * set a gpio offset to alternate function (func = 1)
+ * or gpio mode (func = 0)
+ */
+static void intelce_gpio2_set_alt_func(struct gpio_chip *chip,
+				unsigned offset, int func)
+{
+	u32 mask, bit_num;
+	struct intelce_gpio *gpch;
+	gpch = container_of(chip, struct intelce_gpio, chip);
+
+	/* Clear or set the port GPIO mode */
+	mask = inl(gpch->ioport + GEN3_GPIO2_CGEN);
+	if (func)
+		mask &= ~(1 << offset);
+	else
+		mask |= (1 << offset);
+	outl(mask, gpch->ioport + GEN3_GPIO2_CGEN);
+
+	/* Set alternate function,
+	 * we need to recompute the base number */
+	offset += (chip->base + 3);
+	if (offset <= 4)
+		bit_num = 3;
+	else if (offset <= 7)
+		bit_num = 4;
+	else if (offset == 8)
+		bit_num = 5;
+	else
+		bit_num = 6;
+
+	mask = inl(gpch->ioport + GEN3_GPIO2_MUX_CNTL);
+	if (func)
+		mask |= (1 << bit_num);
+	else
+		mask &= ~(1 << bit_num);
+	outl(mask, gpch->ioport + GEN3_GPIO2_MUX_CNTL);
+}
+
+static void intelce_gpio2_set_direction(struct gpio_chip *chip,
+					unsigned offset, int direction)
+{
+	/* Set to no alternate function */
+	intelce_gpio2_set_alt_func(chip, offset, 0);
+	/* Use GPIO group 1 method here */
+	offset += chip->base  - GEN3_GPIO_GROUP_ONE;
+	intelce_gpio1_set_direction(chip, offset, direction);
+}
+
+static int intelce_gpio2_set_direction_input(struct gpio_chip *chip,
+					unsigned offset)
+{
+	intelce_gpio2_set_direction(chip, offset, 0);
+	return 0;
+}
+
+static int intelce_gpio2_set_direction_output(struct gpio_chip *chip,
+					unsigned offset, int value)
+{
+	intelce_gpio2_set_direction(chip, offset, 1);
+	intelce_gpio2_set_dataout(chip, offset, value);
+	return 0;
+}
+
+/* Group 3 GPIO helpers */
+static void intelce_gpio3_set_dataout(struct gpio_chip *chip,
+					unsigned offset, int value)
+{
+	u32 mask;
+	struct intelce_gpio *gpch;
+	gpch = container_of(chip, struct intelce_gpio, chip);
+
+	mask = inl(gpch->ioport + GEN3_GPIO3_CGLV);
+	if (value)
+		mask |= (1 << offset);
+	else
+		mask &= ~(1 << offset);
+	outl(mask, gpch->ioport + GEN3_GPIO3_CGLV);
+}
+
+static int intelce_gpio3_get_datain(struct gpio_chip *chip,
+					unsigned offset)
+{
+	struct intelce_gpio *gpch;
+	gpch = container_of(chip, struct intelce_gpio, chip);
+
+	return inl(gpch->ioport + GEN3_GPIO3_CGLV) & (1 << offset);
+}
+
+static void intelce_gpio3_set_direction(struct gpio_chip *chip,
+					unsigned offset, int direction)
+{
+	u32 mask;
+	struct intelce_gpio *gpch;
+	gpch = container_of(chip, struct intelce_gpio, chip);
+
+	/* Set GPIO mode */
+	mask = inl(gpch->ioport + GEN3_GPIO3_CGEN);
+	mask |= (1 << offset);
+	outl(mask, gpch->ioport + GEN3_GPIO3_CGEN);
+
+	/* Set direction */
+	mask = inl(gpch->ioport + GEN3_GPIO3_CGIO);
+	if (direction)
+		mask &= ~(1 << offset);
+	else
+		mask |= (1 << offset);
+	outl(mask, gpch->ioport + GEN3_GPIO3_CGIO);
+}
+
+static int intelce_gpio3_set_direction_input(struct gpio_chip *chip,
+					unsigned offset)
+{
+	intelce_gpio3_set_direction(chip, offset, 0);
+	return 0;
+}
+
+static int intelce_gpio3_set_direction_output(struct gpio_chip *chip,
+					unsigned offset, int value)
+{
+	intelce_gpio3_set_direction(chip, offset, 1);
+	intelce_gpio3_set_dataout(chip, offset, value);
+	return 0;
+}
+
+/* Array of gpio chips */
+static struct intelce_gpio intelce_gpio_chips[] = {
+	/* GPIO group 0 */
+	{
+		.chip	= {
+			.label			= "intelce-gpio0",
+			.set			= intelce_gpio0_set_dataout,
+			.get			= intelce_gpio0_get_datain,
+			.direction_input 	= intelce_gpio0_set_direction_input,
+			.direction_output 	= intelce_gpio0_set_direction_output,
+			.base			= GEN3_GPIO_GROUP_ZERO,
+			.ngpio			= GEN3_GPIO_GROUP_ONE,
+		}
+	},
+	/* GPIO group 1 */
+	{
+		.chip	= {
+			.label			= "intelce-gpio1",
+			.set			= intelce_gpio1_set_dataout,
+			.get			= intelce_gpio1_get_datain,
+			.direction_input	= intelce_gpio1_set_direction_input,
+			.direction_output	= intelce_gpio1_set_direction_output,
+			.base			= GEN3_GPIO_GROUP_ONE,
+			.ngpio			= GEN3_GPIO_GROUP_TWO - GEN3_GPIO_GROUP_ONE,
+		}
+	},
+	/* GPIO group 2 */
+	{
+		.chip	= {
+			.label			= "intelce-gpio2",
+			.set			= intelce_gpio2_set_dataout,
+			.get			= intelce_gpio2_get_datain,
+			.direction_input	= intelce_gpio2_set_direction_input,
+			.direction_output	= intelce_gpio2_set_direction_output,
+			.base			= GEN3_GPIO_GROUP_TWO,
+			.ngpio			= GEN3_GPIO_GROUP_THREE - GEN3_GPIO_GROUP_TWO,
+		}
+	},
+	/* GPIO group 3 */
+	{
+		.chip	= {
+			.label			= "intelce-gpio3",
+			.set			= intelce_gpio3_set_dataout,
+			.get			= intelce_gpio3_get_datain,
+			.direction_input	= intelce_gpio3_set_direction_input,
+			.direction_output	= intelce_gpio3_set_direction_output,
+			.base			= GEN3_GPIO_GROUP_THREE,
+			.ngpio			= GEN3_NUM_GPIO_PINS - GEN3_GPIO_GROUP_THREE,
+		}
+	},
+};
+
+/* We match on a PCI bus device even to driver GPIO at 0x1080 */
+static int intelce_gpio_probe(struct pci_dev *pdev,
+			      const struct pci_device_id *ent)
+{
+	int err, io_size = INTELCE_GPIO_IO_SIZE;
+	int bar = 0, i;
+	void __iomem *ioaddr;
+
+	err = pci_enable_device(pdev);
+	if (err)
+		goto err_out;
+
+	/* this should always be supported */
+	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+	if (err) {
+		printk(KERN_ERR DRV_NAME ": 32-bit PCI DMA addresses"
+				"not supported by the card\n");
+		goto err_out;
+	}
+
+	err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+	if (err) {
+		printk(KERN_ERR DRV_NAME ": 32-bit PCI DMA addresses"
+				"not supported by the card\n");
+		goto err_out;
+	}
+
+	/* IO Size check */
+	if (pci_resource_len(pdev, bar) < io_size) {
+		printk(KERN_ERR DRV_NAME ": Insufficient PCI resources, aborting\n");
+		err = -EIO;
+		goto err_out;
+	}
+
+	pci_set_master(pdev);
+
+	err = pci_request_regions(pdev, DRV_NAME);
+	if (err) {
+		printk(KERN_ERR DRV_NAME ": failed to request PCI region\n");
+		goto err_out;
+	}
+
+	ioaddr = pci_iomap(pdev, bar, io_size);
+	if (!ioaddr) {
+		printk(KERN_ERR DRV_NAME ": ioremap failed for device: %s\n",
+					pci_name(pdev));
+		err = -ENOMEM;
+		goto err_release_pci_region;
+	}
+
+	if (!request_region(GEN3_GPIO_IO_BASE, GEN3_GPIO_IO_SIZE, DRV_NAME)) {
+		printk(KERN_ERR DRV_NAME ": failed to request IO port region\n");
+		err = -ENOMEM;
+		goto err_release_pci_region;
+	}
+
+	pci_set_drvdata(pdev, intelce_gpio_chips);
+
+	intelce_gpio_chips[0].base = ioaddr;
+	intelce_gpio_chips[0].pdev = pdev;
+
+	/* Register our gpio chips */
+	for (i = 0; i < GEN3_GPIO_GROUPS; i++) {
+		/* Set IO base for gpio chips 1 to 3 */
+		if (i > 0) {
+			intelce_gpio_chips[i].ioport = GEN3_GPIO_IO_BASE;
+			intelce_gpio_chips[i].pdev = pdev;
+			intelce_gpio_chips[i].type = GEN3_TYPE_IOPORT;
+		}
+
+		/* Register our gpio chip */
+		err = gpiochip_add(&intelce_gpio_chips[i].chip);
+		if (err) {
+			printk(KERN_ERR DRV_NAME ": failed to register chip %d\n", i);
+			goto err_drvdata;
+		}
+		printk(KERN_INFO DRV_NAME ": registered %s at 0x%08x (%s, %d GPIOs)\n",
+		       intelce_gpio_chips[i].chip.label,
+		       intelce_gpio_chips[i].type ?
+		       intelce_gpio_chips[i].ioport :
+		       (u32)intelce_gpio_chips[i].base,
+		       intelce_gpio_chips[i].type ? "IO port" : "PCI",
+		       intelce_gpio_chips[i].chip.ngpio);
+	}
+
+	return 0;
+
+err_drvdata:
+	pci_set_drvdata(pdev, NULL);
+	pci_iounmap(pdev, ioaddr);
+	release_region(GEN3_GPIO_IO_BASE, GEN3_GPIO_IO_SIZE);
+err_release_pci_region:
+	pci_release_regions(pdev);
+err_out:
+	return err;
+}
+
+static void __exit intelce_gpio_remove(struct pci_dev *pdev)
+{
+	int i;
+
+	for (i = 0; i < GEN3_GPIO_GROUPS; i++)
+		gpiochip_remove(&intelce_gpio_chips[i].chip);
+
+	release_region(GEN3_GPIO_IO_BASE, GEN3_GPIO_IO_SIZE);
+	pci_iounmap(pdev, intelce_gpio_chips[0].base);
+	pci_set_drvdata(pdev, NULL);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+}
+
+static struct pci_device_id intelce_gpio_id_tbl[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e67) },
+	{ 0 }
+};
+
+static struct pci_driver intelce_gpio_driver = {
+	.name		= DRV_NAME,
+	.id_table	= intelce_gpio_id_tbl,
+	.probe		= intelce_gpio_probe,
+	.remove		= intelce_gpio_remove,
+};
+
+static int __init intelce_gpio_init(void)
+{
+	return pci_register_driver(&intelce_gpio_driver);
+}
+
+static void __exit intelce_gpio_exit(void)
+{
+	pci_unregister_driver(&intelce_gpio_driver);
+}
+
+module_init(intelce_gpio_init);
+module_exit(intelce_gpio_exit);
+
+MODULE_AUTHOR("Florian Fainelli <ffainelli@freebox.fr>");
+MODULE_DESCRIPTION("GPIO driver for the Intel CE3100/4100 SoC");
+MODULE_VERSION(DRV_VERSION);
+MODULE_LICENSE("GPL");
diff -Nruw linux-4.2-fbx/drivers/platform/intelce./Kconfig linux-4.2-fbx/drivers/platform/intelce/Kconfig
--- linux-4.2-fbx/drivers/platform/intelce./Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/platform/intelce/Kconfig	2013-12-04 14:33:20.395478996 +0100
@@ -0,0 +1,18 @@
+#
+# IntelCE devices configuration
+#
+
+menu "IntelCE devices"
+
+config INTELCE_GPIO
+	tristate "GPIO support"
+	select ARCH_REQUIRE_GPIOLIB
+	---help---
+	  IntelCE 3100/4100 GPIO support.
+
+config INTELCE_DFX
+	tristate "DFX reporting support"
+	---help---
+	  IntelCE 3100/4100 DFX fuse reporting support.
+
+endmenu
diff -Nruw linux-4.2-fbx/drivers/platform/intelce./Makefile linux-4.2-fbx/drivers/platform/intelce/Makefile
--- linux-4.2-fbx/drivers/platform/intelce./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/platform/intelce/Makefile	2013-12-04 14:33:20.395478996 +0100
@@ -0,0 +1,2 @@
+obj-$(CONFIG_INTELCE_GPIO)	+= gpio-intelce.o
+obj-$(CONFIG_INTELCE_DFX)	+= dfx.o
diff -Nruw linux-4.2-fbx/drivers/platform/tango2./Kconfig linux-4.2-fbx/drivers/platform/tango2/Kconfig
--- linux-4.2-fbx/drivers/platform/tango2./Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/platform/tango2/Kconfig	2010-02-25 15:41:08.481139782 +0100
@@ -0,0 +1,30 @@
+#
+# TANGO2 devices configuration
+#
+
+menu "Tango2 devices"
+	depends on TANGO2
+
+config TANGO2_FIP
+	tristate "Front panel support"
+	select INPUT
+	---help---
+	  Tango2 FIP front panel support.
+
+config TANGO2_GPIO
+	tristate "GPIO sysfs support"
+	---help---
+	  Export GPIO attributes in sysfs.
+
+config TANGO2_IR
+	tristate "IR support"
+	---help---
+	  Tango2 IR (NEC/RC5/RC6) support.
+
+config TANGO2_FB
+	tristate "Framebuffer support"
+	depends on FB
+	---help---
+	  Tango2 framebuffer support.
+
+endmenu
diff -Nruw linux-4.2-fbx/drivers/platform/tango2./Makefile linux-4.2-fbx/drivers/platform/tango2/Makefile
--- linux-4.2-fbx/drivers/platform/tango2./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/drivers/platform/tango2/Makefile	2010-02-25 15:41:08.481139782 +0100
@@ -0,0 +1,6 @@
+# Makefile for the TANGO2 device drivers
+
+obj-$(CONFIG_TANGO2_FIP) += fip.o
+obj-$(CONFIG_TANGO2_GPIO) += gpio.o
+obj-$(CONFIG_TANGO2_IR) += ir.o
+obj-$(CONFIG_TANGO2_FB) += fb.o
diff -Nruw linux-4.2-fbx/fs/exfat./bitmap.c linux-4.2-fbx/fs/exfat/bitmap.c
--- linux-4.2-fbx/fs/exfat./bitmap.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/fs/exfat/bitmap.c	2014-06-25 11:22:30.373677444 +0200
@@ -0,0 +1,600 @@
+/*
+ * bitmap.c for exfat
+ * Created by <nschichan@freebox.fr> on Thu Aug  8 19:21:05 2013
+ */
+
+#include <linux/buffer_head.h>
+#include <linux/fs.h>
+
+#include "exfat.h"
+#include "exfat_fs.h"
+
+
+static inline sector_t exfat_bitmap_sector(struct exfat_sb_info *sbi,
+					   u32 cluster)
+{
+	return sbi->first_bitmap_sector + ((cluster / 8) >> sbi->sectorbits);
+}
+
+static inline u32 exfat_bitmap_off(struct exfat_sb_info *sbi,
+				   u32 cluster)
+{
+	return (cluster / 8) & sbi->sectormask;
+}
+
+static inline u32 exfat_bitmap_shift(u32 cluster)
+{
+	return cluster & 7;
+}
+
+static int __find_get_free_cluster(struct inode *inode, u32 *out_cluster)
+{
+	struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb);
+
+	while (1) {
+		sector_t sect = exfat_bitmap_sector(sbi,
+						    sbi->cur_bitmap_cluster);
+		u32 off = exfat_bitmap_off(sbi, sbi->cur_bitmap_cluster);
+		u32 shift = exfat_bitmap_shift(sbi->cur_bitmap_cluster);
+
+		/* disk is full */
+		if (!sbi->free_clusters)
+			break;
+
+		if (!sbi->cur_bitmap_bh ||
+		    sect != sbi->cur_bitmap_sector) {
+			if (sbi->cur_bitmap_bh)
+				brelse(sbi->cur_bitmap_bh);
+			sbi->cur_bitmap_bh = sb_bread(inode->i_sb, sect);
+			sbi->cur_bitmap_sector = sect;
+			if (!sbi->cur_bitmap_bh) {
+				exfat_msg(inode->i_sb, KERN_ERR,
+					  "unable to read bitmap sector "
+					  "at %llu", sect);
+				return -EIO;
+			}
+		}
+
+		if (!(sbi->cur_bitmap_bh->b_data[off] & (1 << shift))) {
+			sbi->cur_bitmap_bh->b_data[off] |= (1 << shift);
+			*out_cluster = sbi->cur_bitmap_cluster;
+			goto found;
+		}
+
+		++sbi->cur_bitmap_cluster;
+		if (sbi->cur_bitmap_cluster == sbi->cluster_count)
+			sbi->cur_bitmap_cluster = 0;
+	}
+	return -ENOSPC;
+
+found:
+	sbi->prev_free_cluster = *out_cluster;
+	--sbi->free_clusters;
+	mark_buffer_dirty(sbi->cur_bitmap_bh);
+	return 0;
+}
+
+static int __put_cluster(struct inode *inode, u32 cluster)
+{
+	struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb);
+	sector_t sect = exfat_bitmap_sector(sbi, cluster);
+	u32 off = exfat_bitmap_off(sbi, cluster);
+	u32 shift = exfat_bitmap_shift(cluster);
+
+
+	if (!sbi->cur_bitmap_bh || sect != sbi->cur_bitmap_sector) {
+		if (sbi->cur_bitmap_bh)
+			brelse(sbi->cur_bitmap_bh);
+		sbi->cur_bitmap_bh = sb_bread(inode->i_sb, sect);
+		if (!sbi->cur_bitmap_bh) {
+			exfat_msg(inode->i_sb, KERN_ERR,
+				  "unable to read bitmap sector at %llu", sect);
+			return -EIO;
+		}
+		sbi->cur_bitmap_sector = sect;
+		sbi->cur_bitmap_cluster = cluster;
+	}
+	if ((sbi->cur_bitmap_bh->b_data[off] & (1 << shift)) == 0) {
+		exfat_fs_error(inode->i_sb, "put_cluster: cluster %u "
+			  "already free.", cluster);
+		return -EIO;
+	}
+
+	++sbi->free_clusters;
+	sbi->cur_bitmap_bh->b_data[off] &= ~(1 << shift);
+	sbi->prev_free_cluster = cluster;
+	mark_buffer_dirty(sbi->cur_bitmap_bh);
+	/* sync_dirty_buffer(sbi->cur_bitmap_bh); */
+	return 0;
+}
+
+/*
+ * setup search to start at given cluster.
+ */
+static void __exfat_reset_bitmap(struct exfat_sb_info *sbi, u32 cluster)
+{
+	sector_t sect;
+
+	if (cluster >= sbi->cluster_count)
+		cluster = 0;
+
+	sect = exfat_bitmap_sector(sbi, cluster);
+	if (sbi->cur_bitmap_sector != sect) {
+		sbi->cur_bitmap_sector = sect;
+		if (sbi->cur_bitmap_bh) {
+			brelse(sbi->cur_bitmap_bh);
+			sbi->cur_bitmap_bh = NULL;
+		}
+	}
+	sbi->cur_bitmap_cluster = cluster;
+}
+
+static bool all_contiguous(u32 *clusters, u32 nr)
+{
+	u32 i;
+
+	for (i = 0; i < nr - 1; ++i) {
+		if (clusters[i] != clusters[i + 1] - 1)
+			return false;
+	}
+	return true;
+}
+
+/*
+ * hint must be the immediately after the last allocated cluster of
+ * the inode.
+ */
+int exfat_alloc_clusters(struct inode *inode, u32 hint, u32 *clusters, u32 nr)
+{
+	struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb);
+	struct exfat_inode_info *info = EXFAT_I(inode);
+	u32 i;
+
+	mutex_lock(&sbi->bitmap_mutex);
+	__exfat_reset_bitmap(sbi, hint - 2);
+	for (i = 0; i < nr; ++i) {
+		u32 new;
+		int error;
+
+		error = __find_get_free_cluster(inode, &new);
+		if (error) {
+			mutex_unlock(&sbi->bitmap_mutex);
+			return error;
+		}
+
+		clusters[i] = new + 2;
+	}
+	mutex_unlock(&sbi->bitmap_mutex);
+
+	/*
+	 * all clusters found: now see if we need to update/create a
+	 * fat chain.
+	 */
+	if (info->first_cluster == 0) {
+		info->first_cluster = clusters[0];
+		if (all_contiguous(clusters, nr)) {
+			/*
+			 * first cluster alloc on inode and all
+			 * clusters are contiguous.
+			 */
+			info->flags |= EXFAT_I_FAT_INVALID;
+		} else {
+			/*
+			 * first alloc and already fragmented.
+			 */
+			return exfat_write_fat(inode, 0, clusters, nr);
+		}
+	} else {
+		int error;
+		if ((info->flags & EXFAT_I_FAT_INVALID) &&
+		    (clusters[0] != hint || !all_contiguous(clusters, nr))) {
+			/*
+			 * must now use fat chain instead of bitmap.
+			 */
+			info->flags &= ~(EXFAT_I_FAT_INVALID);
+
+			/*
+			 * write the contiguous chain that would
+			 * previously be accessed without the FAT
+			 * chain.
+			 */
+			error = exfat_write_fat_contiguous(inode,
+						  info->first_cluster,
+						  hint - info->first_cluster);
+			if (error)
+				return error;
+		}
+
+		if ((info->flags & EXFAT_I_FAT_INVALID) == 0) {
+			/*
+			 * link the allocated clusters after hint.
+			 */
+			error = exfat_write_fat(inode, hint - 1, clusters, nr);
+			if (error)
+				return  error;
+		}
+
+	}
+
+	/*
+	 * update i_blocks.
+	 */
+	inode->i_blocks += nr << (sbi->clusterbits - 9);
+	info->allocated_clusters += nr;
+
+	/*
+	 * caller must call mark_inode_dirty so that inode
+	 * first_cluster and inode flags get written to the disk.
+	 * caller must update inode size (directory and regular file
+	 * have different rules).
+	 */
+	return 0;
+}
+
+
+static int exfat_free_clusters_contiguous(struct inode *inode,
+					  u32 start, u32 nr)
+{
+	u32 cluster;
+	struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb);
+	int error = 0;
+
+	mutex_lock(&sbi->bitmap_mutex);
+	for (cluster = start; cluster < start + nr; ++cluster) {
+		error = __put_cluster(inode, cluster - 2);
+		if (error)
+			break;
+	}
+	mutex_unlock(&sbi->bitmap_mutex);
+	return error;
+}
+
+static int exfat_free_clusters_fat(struct inode *inode,
+				   u32 fcluster_start, u32 nr)
+{
+	struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb);
+	u32 fcluster;
+	int error = 0;
+
+	mutex_lock(&sbi->bitmap_mutex);
+	for (fcluster = fcluster_start; fcluster < fcluster_start + nr;
+	     ++fcluster) {
+		u32 dcluster;
+		int error;
+
+		error = exfat_get_fat_cluster(inode, fcluster, &dcluster);
+		if (error)
+			break;
+
+		error = __put_cluster(inode, dcluster - 2);
+		if (error)
+			break;
+	}
+	mutex_unlock(&sbi->bitmap_mutex);
+
+	/*
+	 * per-inode file cluster to disk cluster translation cache
+	 * mostly now holds entries to the zone we just truncated, so
+	 * they must not be kept (this could lead to FS corruption).
+	 */
+	exfat_inode_cache_drop(inode);
+
+	return error;
+}
+
+int exfat_free_clusters_inode(struct inode *inode, u32 fcluster_start)
+{
+	struct exfat_inode_info *info = EXFAT_I(inode);
+	int error;
+	u32 nr_to_free = info->allocated_clusters - fcluster_start;
+
+	if (info->first_cluster == 0 || nr_to_free == 0)
+		/*
+		 * no clusters allocated, or nothing to do
+		 */
+		return 0;
+
+	if (info->flags & EXFAT_I_FAT_INVALID)
+		error = exfat_free_clusters_contiguous(inode,
+				       info->first_cluster + fcluster_start,
+				       nr_to_free);
+	else
+		error = exfat_free_clusters_fat(inode, fcluster_start,
+					nr_to_free);
+	if (error)
+		return error;
+
+	info->allocated_clusters -= nr_to_free;
+	inode->i_blocks = EXFAT_I(inode)->allocated_clusters <<
+		(EXFAT_SB(inode->i_sb)->clusterbits - 9);
+
+	/*
+	 * update inode info, caller must call mark_inode_dirty and
+	 * update inode->i_size.
+	 */
+	if (fcluster_start == 0) {
+		info->first_cluster = 0;
+		info->flags &= ~(EXFAT_I_FAT_INVALID);
+	}
+	return 0;
+}
+
+static u32 count_clusters_bh(struct buffer_head *bh, u32 count)
+{
+	u8 *ptr = bh->b_data;
+	u32 ret = 0;
+	u8 val;
+
+	while (count >= sizeof (u64) * 8) {
+		u64 val = *(u64*)ptr;
+
+		ret += hweight64(~val);
+		count -= sizeof (u64) * 8;
+		ptr += sizeof (u64);
+	}
+	if (count >= sizeof (u32) * 8) {
+		u32 val = *(u32*)ptr;
+
+		ret += hweight32(~val);
+		count -= sizeof (u32) * 8;
+		ptr += sizeof (u32);
+	}
+	if (count >= sizeof (u16) * 8) {
+		u16 val = *(u16*)ptr;
+
+		ret += hweight16(~val);
+		count -= sizeof (u16) * 8;
+		ptr += sizeof (u16);
+	}
+	while (count >= sizeof (u8) * 8) {
+		u8 val = *ptr;
+
+		ret += hweight8(~val);
+		count -= sizeof (u8) * 8;
+		ptr += sizeof (u8);
+	}
+	val = *ptr;
+	while (count) {
+		ret += (~val & 1);
+		val >>= 1;
+		--count;
+	}
+	return ret;
+}
+
+/*
+ * only called during mount, so taking sbi->bitmap_mutex should not be
+ * needed.
+ */
+static int exfat_get_free_cluster_count(struct super_block *sb, u32 *out_count)
+{
+	struct exfat_sb_info *sbi = EXFAT_SB(sb);
+	u32 clusters_per_sector = 8 * sbi->sectorsize;
+	u32 cluster;
+
+	*out_count = 0;
+	for (cluster = 0; cluster < sbi->cluster_count;
+	     cluster += clusters_per_sector) {
+		sector_t sect = exfat_bitmap_sector(sbi, cluster);
+		struct buffer_head *bh;
+		u32 count = clusters_per_sector;
+
+		if (cluster + clusters_per_sector > sbi->cluster_count)
+			count = sbi->cluster_count - cluster;
+
+		bh = sb_bread(sb, sect);
+		if (!bh) {
+			exfat_msg(sb, KERN_ERR,
+				  "unable to read bitmap sector at %llu", sect);
+			return -EIO;
+		}
+		*out_count += count_clusters_bh(bh, count);
+		brelse(bh);
+	}
+	return 0;
+}
+
+/*
+ * setup a bitmap context, preload a bh from the requested starting
+ * cluster.
+ */
+int exfat_init_bitmap_context(struct super_block *sb,
+			      struct exfat_bitmap_ctx *ctx,
+			      u32 cluster)
+{
+	memset(ctx, 0, sizeof (*ctx));
+	ctx->sb = sb;
+
+	cluster -= 2;
+	if (cluster >= EXFAT_SB(sb)->cluster_count)
+		return -ENOSPC;
+
+	ctx->cur_sector = exfat_bitmap_sector(EXFAT_SB(sb), cluster);
+	ctx->bh = sb_bread(ctx->sb, ctx->cur_sector);
+
+	if (!ctx->bh) {
+		exfat_msg(sb, KERN_ERR, "unable to read bitmap sector at %llu",
+			  ctx->cur_sector);
+		return -EIO;
+	}
+	return 0;
+}
+
+/*
+ * release bh in an already setup bitmap context.
+ */
+void exfat_exit_bitmap_context(struct exfat_bitmap_ctx *ctx)
+{
+	if (ctx->bh)
+		brelse(ctx->bh);
+}
+
+/*
+ * test a specific cluster usage in the bitmap. reuse the bh in the
+ * exfat_bitmap_ctx or read a new one if starting cluster is outside
+ * the current one.
+ */
+static int exfat_test_bitmap_cluster(struct exfat_bitmap_ctx *ctx,
+				     uint32_t cluster, bool *cluster_in_use)
+{
+	sector_t sect;
+	uint32_t off = exfat_bitmap_off(EXFAT_SB(ctx->sb), cluster);
+	int shift = exfat_bitmap_shift(cluster);
+
+	sect = exfat_bitmap_sector(EXFAT_SB(ctx->sb), cluster);
+	if (sect != ctx->cur_sector) {
+		ctx->cur_sector = sect;
+		ctx->bh = sb_bread(ctx->sb, ctx->cur_sector);
+		if (!ctx->bh) {
+			exfat_msg(ctx->sb, KERN_ERR,
+				  "unable to read bitmap sector at %llu", sect);
+			return -EIO;
+		}
+	}
+
+	*cluster_in_use = !!(ctx->bh->b_data[off] & (1 << shift));
+	return 0;
+}
+
+/*
+ * update first_in_use and nr_in_use with the first zone of used
+ * clusters starting from start_cluster.
+ */
+int exfat_test_bitmap(struct exfat_bitmap_ctx *ctx, uint32_t start_cluster,
+		      uint32_t *first_in_use, uint32_t *nr_in_use)
+{
+	bool in_use = false;
+	int error = 0;
+	struct exfat_sb_info *sbi = EXFAT_SB(ctx->sb);
+
+	start_cluster -= 2;
+
+	/*
+	 * scan bitmap until we find a cluster that is in use.
+	 */
+	while (1) {
+		if (start_cluster == sbi->cluster_count) {
+			/*
+			 * readched end of disk: no more in use
+			 * cluster found.
+			 */
+			*first_in_use = sbi->cluster_count;
+			*nr_in_use = 0;
+			return 0;
+		}
+		error = exfat_test_bitmap_cluster(ctx, start_cluster, &in_use);
+		if (error)
+			return error;
+		if (in_use)
+			break;
+		++start_cluster;
+	}
+
+
+	/*
+	 * update first_in_use, and scan until a free cluster is
+	 * found.
+	 */
+	*first_in_use = start_cluster + 2;
+	*nr_in_use = 0;
+	while (1) {
+		error = exfat_test_bitmap_cluster(ctx, start_cluster, &in_use);
+		if (error)
+			return error;
+		if (!in_use)
+			break;
+		++(*nr_in_use);
+		++start_cluster;
+	}
+	return 0;
+}
+
+int exfat_init_bitmap(struct inode *root)
+{
+	struct exfat_sb_info *sbi = EXFAT_SB(root->i_sb);
+	struct exfat_bitmap_entry *be;
+	struct exfat_dir_ctx dctx;
+	u32 first_bitmap_cluster;
+	u32 last_bitmap_cluster;
+
+	int error;
+
+	mutex_init(&sbi->bitmap_mutex);
+
+	error = exfat_init_dir_ctx(root, &dctx, 0);
+	if (error)
+		return error;
+
+try_bitmap:
+	error = -ENOENT;
+	be = __exfat_dentry_next(&dctx, E_EXFAT_BITMAP, 0xff, true, NULL);
+	if (!be) {
+		exfat_msg(root->i_sb, KERN_ERR, "root directory does not "
+			  "have a bitmap entry.");
+		goto fail;
+	}
+
+	if (exfat_bitmap_nr(be->flags) != 0)
+		/*
+		 * not expected to find a second bitmap entry here
+		 * since we checked during superblock fill that we
+		 * were not on a texFAT volume ...
+		 */
+		goto try_bitmap;
+
+
+	error = -EINVAL;
+	if (__le64_to_cpu(be->length) * 8 < sbi->cluster_count) {
+		exfat_msg(root->i_sb, KERN_INFO, "bitmap does not cover "
+			  "the whole cluster heap.");
+		goto fail;
+	}
+
+	first_bitmap_cluster = __le32_to_cpu(be->cluster_addr);
+	last_bitmap_cluster = first_bitmap_cluster +
+		(__le32_to_cpu(be->length) >> sbi->clusterbits);
+
+	/*
+	 * check that bitmap start and end clusters are inside the
+	 * disk.
+	 */
+	error = -ERANGE;
+	if (first_bitmap_cluster < 2 &&
+	    first_bitmap_cluster >= sbi->cluster_count) {
+		exfat_msg(root->i_sb, KERN_ERR, "bitmap start cluster is "
+			  "outside disk limits.");
+		goto fail;
+	}
+	if (last_bitmap_cluster < 2 &&
+	    last_bitmap_cluster >= sbi->cluster_count) {
+		exfat_msg(root->i_sb, KERN_ERR, "bitmap last cluster is "
+			  "outside disk limits.");
+		goto fail;
+	}
+
+	sbi->bitmap_length = __le32_to_cpu(be->length);
+	sbi->first_bitmap_sector = exfat_cluster_sector(sbi,
+					__le32_to_cpu(be->cluster_addr));
+	sbi->last_bitmap_sector = sbi->first_bitmap_sector +
+		DIV_ROUND_UP(sbi->bitmap_length, sbi->sectorsize);
+
+	error = exfat_get_free_cluster_count(root->i_sb, &sbi->free_clusters);
+	if (error)
+		goto fail;
+
+	sbi->prev_free_cluster = 0;
+
+	exfat_cleanup_dir_ctx(&dctx);
+	return 0;
+fail:
+	exfat_cleanup_dir_ctx(&dctx);
+	return error;
+}
+
+void exfat_exit_bitmap(struct super_block *sb)
+{
+	struct exfat_sb_info *sbi = EXFAT_SB(sb);
+
+	if (sbi->cur_bitmap_bh)
+		brelse(sbi->cur_bitmap_bh);
+}
diff -Nruw linux-4.2-fbx/fs/exfat./dir.c linux-4.2-fbx/fs/exfat/dir.c
--- linux-4.2-fbx/fs/exfat./dir.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/fs/exfat/dir.c	2013-12-04 14:33:22.527479030 +0100
@@ -0,0 +1,400 @@
+/*
+ * dir.c for exfat
+ * Created by <nschichan@freebox.fr> on Tue Aug 20 11:42:46 2013
+ */
+
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/buffer_head.h>
+#include <linux/slab.h>
+#include <linux/nls.h>
+
+#include "exfat.h"
+#include "exfat_fs.h"
+
+/*
+ * setup an exfat_dir_ctx structure so that __exfat_dentry_next can
+ * work with it.
+ */
+int exfat_init_dir_ctx(struct inode *inode, struct exfat_dir_ctx *ctx,
+		       off_t start)
+{
+	u32 cluster = EXFAT_I(inode)->first_cluster;
+
+	memset(ctx, 0, sizeof (*ctx));
+
+	if (cluster == 0) {
+		ctx->empty = true;
+		ctx->sb = inode->i_sb;
+		return 0;
+	}
+
+	if (cluster < EXFAT_CLUSTER_FIRSTVALID ||
+	    cluster > EXFAT_CLUSTER_LASTVALID) {
+		exfat_msg(inode->i_sb, KERN_ERR, "exfat_init_dir_ctx: invalid "
+			  "cluster %u", cluster);
+		return -EINVAL;
+	}
+
+	start &= ~(0x20 - 1);
+	if (start == 0)
+		ctx->off = -1;
+	else
+		ctx->off = start - 0x20;
+
+	ctx->sb = inode->i_sb;
+	ctx->inode = inode;
+
+	return 0;
+}
+
+void exfat_cleanup_dir_ctx(struct exfat_dir_ctx *dctx)
+{
+	if (dctx->bh)
+		brelse(dctx->bh);
+}
+
+/*
+ * calculate the checksum for the current direntry. fields containing
+ * the checksum for the first entry is not part of the checksum
+ * calculation.
+ */
+u16 exfat_direntry_checksum(void *data, u16 checksum, bool first)
+{
+	u8 *ptr = data;
+	int i;
+
+	for (i = 0; i < 0x20; ++i) {
+		if (first && (i == 2 || i == 3))
+			continue ;
+		checksum = ((checksum << 15) | (checksum >> 1)) + (u16)ptr[i];
+	}
+	return checksum;
+}
+
+u32 exfat_dctx_fpos(struct exfat_dir_ctx *dctx)
+{
+	return dctx->off;
+}
+
+u64 exfat_dctx_dpos(struct exfat_dir_ctx *dctx)
+{
+	struct exfat_sb_info *sbi = EXFAT_SB(dctx->sb);
+
+	return (dctx->sector << sbi->sectorbits) +
+		(dctx->off & sbi->sectormask);
+}
+
+static int exfat_get_dctx_disk_cluster(struct exfat_dir_ctx *dctx,
+				       u32 file_cluster, u32 *disk_cluster)
+{
+	struct exfat_inode_info *info = EXFAT_I(dctx->inode);
+
+	if (info->flags & EXFAT_I_FAT_INVALID) {
+		*disk_cluster = info->first_cluster + file_cluster;
+		return 0;
+	} else {
+		return exfat_get_fat_cluster(dctx->inode, file_cluster,
+					     disk_cluster);
+	}
+}
+
+/*
+ * get the next typed dentry in the exfat_dir_ctx structure. can_skip
+ * indicates whether the entry must be immediately there in the entry
+ * stream. *end indicates whether end of directory entry stream is
+ * reached or not.
+ *
+ * only one buffer_head is kept at a time. subsequent calls to
+ * __exfat_dentry_next can invalidate pointers from previous calls due
+ * to that.
+ */
+void *__exfat_dentry_next(struct exfat_dir_ctx *dctx, int type, int mask,
+			  bool can_skip, bool *end)
+{
+	struct exfat_sb_info *sbi = EXFAT_SB(dctx->sb);
+
+	if (dctx->empty) {
+		if (end)
+			*end = true;
+		return NULL;
+	}
+
+	if (end)
+		*end = false;
+
+	if (dctx->off == -1)
+		dctx->off = 0;
+	else
+		dctx->off += 0x20;
+
+	for (;;) {
+		sector_t wanted_sector;
+		u32 file_cluster = dctx->off >> sbi->clusterbits;
+		u32 disk_cluster;
+		int error;
+		int sector_offset;
+		sector_t sector_in_cluster;
+
+		if (dctx->off >= dctx->inode->i_size) {
+			*end = true;
+			return NULL;
+		}
+
+
+		error = exfat_get_dctx_disk_cluster(dctx, file_cluster,
+						    &disk_cluster);
+		if (error)
+			return NULL;
+
+		sector_in_cluster = (dctx->off >> sbi->sectorbits) %
+			sbi->sectors_per_cluster;
+
+		wanted_sector = exfat_cluster_sector(sbi, disk_cluster) +
+			sector_in_cluster;
+		if (wanted_sector != dctx->sector || !dctx->bh) {
+			/*
+			 * need to fetch a new sector from the current
+			 * cluster.
+			 */
+			dctx->sector = wanted_sector;
+			if (dctx->bh)
+				brelse(dctx->bh);
+			dctx->bh = sb_bread(dctx->sb, dctx->sector);
+			if (!dctx->bh)
+				return NULL;
+		}
+
+		sector_offset = dctx->off & sbi->sectormask;
+		if ((dctx->bh->b_data[sector_offset] & mask) == (type & mask))
+			/*
+			 * return pointer to entry if type matches the
+			 * one given.
+			 */
+			return dctx->bh->b_data + sector_offset;
+
+		if (dctx->bh->b_data[sector_offset] == 0 && end)
+			/*
+			 * set end if no more entries in this directory.
+			 */
+			*end = true;
+
+		if (dctx->bh->b_data[sector_offset] == 0 || !can_skip)
+			/*
+			 * handle can_skip / end of directory.
+			 */
+			return NULL;
+
+		/*
+		 * move to next entry.
+		 */
+		dctx->off += 0x20;
+	}
+	return NULL;
+}
+
+/*
+ * helper around __exfat_dentry_next that copies the content of the
+ * found entry in a user supplied buffer.
+ */
+int exfat_dentry_next(void *out, struct exfat_dir_ctx *dctx,
+			     int type, bool can_skip)
+{
+	bool end;
+
+	void *ptr = __exfat_dentry_next(dctx, type, 0xff, can_skip, &end);
+
+	if (!ptr) {
+		if (end)
+			return -ENOENT;
+		else {
+			exfat_msg(dctx->sb, KERN_INFO, "no ptr and "
+				  "end not reached: "
+				  "type %02x, can_skip %s\n", type,
+				  can_skip ? "true" : "false");
+			return -EIO;
+		}
+	}
+	memcpy(out, ptr, 0x20);
+	return 0;
+}
+
+/*
+ * extract name by parsing consecutive E_EXFAT_FILENAME entries in a
+ * caller provided buffer. also update the checksum on the fly.
+ *
+ * no utf16 to utf8 conversion is performed.
+ */
+int __exfat_get_name(struct exfat_dir_ctx *dctx, u32 name_length,
+			    __le16 *name, u16 *calc_checksum,
+			    struct exfat_iloc *iloc)
+{
+	__le16 *ptr;
+	int error;
+	int nr;
+
+	ptr = name;
+
+	error = -EIO;
+	nr = 0;
+	while (name_length) {
+		struct exfat_filename_entry *e;
+		u32 len = 15;
+
+		e = __exfat_dentry_next(dctx, E_EXFAT_FILENAME, 0xff,
+					false, NULL);
+		if (!e)
+			goto fail;
+		*calc_checksum = exfat_direntry_checksum(e, *calc_checksum,
+							 false);
+
+		if (iloc)
+			iloc->disk_offs[nr + 2] = exfat_dctx_dpos(dctx);
+		if (name_length < 15)
+			len = name_length;
+
+		memcpy(ptr, e->name_frag, len * sizeof (__le16));
+		name_length -= len;
+		ptr += len;
+		nr++;
+	}
+	return 0;
+
+fail:
+	return error;
+}
+
+/*
+ * walk the directory and invoke filldir on all found entries.
+ */
+static int __exfat_iterate(struct exfat_dir_ctx *dctx, struct file *file,
+			   struct dir_context *ctx)
+{
+	int error;
+	char *name = __getname();
+	__le16 *utf16name = __getname();
+
+	if (!name)
+		return -ENOMEM;
+	if (!utf16name) {
+		__putname(name);
+		return -ENOMEM;
+	}
+
+	for (;;) {
+		struct exfat_filedir_entry *efd;
+		struct exfat_stream_extension_entry *esx;
+		int dtype = DT_REG;
+		int name_length;
+		bool end;
+		u16 calc_checksum;
+		u16 expect_checksum;
+
+		/*
+		 * get the next filedir entry, we are allowed to skip
+		 * entries for that.
+		 */
+		error = -EIO;
+		efd = __exfat_dentry_next(dctx, E_EXFAT_FILEDIR, 0xff,
+					  true, &end);
+		if (!efd) {
+			if (end)
+				break;
+			else
+				goto fail;
+		}
+		expect_checksum = __le16_to_cpu(efd->set_checksum);
+		calc_checksum = exfat_direntry_checksum(efd, 0, true);
+
+		if (__le16_to_cpu(efd->attributes & E_EXFAT_ATTR_DIRECTORY))
+			dtype = DT_DIR;
+
+		/*
+		 * get immediate stream extension entry.
+		 */
+		esx = __exfat_dentry_next(dctx, E_EXFAT_STREAM_EXT, 0xff, false,
+					  NULL);
+		if (!esx)
+			goto fail;
+		calc_checksum = exfat_direntry_checksum(esx, calc_checksum,
+							false);
+
+		/*
+		 * get immediate name.
+		 */
+		error = __exfat_get_name(dctx, esx->name_length, utf16name,
+					 &calc_checksum, NULL);
+		if (error) {
+			exfat_msg(dctx->sb, KERN_INFO, "__exfat_get_name "
+				  "has failed with %i", error);
+			goto fail;
+		}
+
+		if (calc_checksum != expect_checksum) {
+			exfat_msg(dctx->sb, KERN_INFO, "checksum: "
+				  "calculated %04x, expect %04x",
+				  calc_checksum, expect_checksum);
+			error = -EIO;
+			goto fail;
+		}
+
+		/*
+		 * convert utf16 to utf8 for kernel filldir callback.
+		 */
+		name_length = utf16s_to_utf8s(utf16name, esx->name_length,
+						   UTF16_LITTLE_ENDIAN,
+						   name, NAME_MAX + 2);
+		if (name_length < 0) {
+			error = name_length;
+			goto fail;
+		}
+		if (name_length > 255) {
+			error = -ENAMETOOLONG;
+			goto fail;
+		}
+
+		/*
+		 * tell the kernel we have an entry by calling
+		 * dir_emit
+		 */
+		if (dir_emit(ctx, name, name_length, 1, dtype))
+			ctx->pos = 2 + exfat_dctx_fpos(dctx);
+		else
+			goto fail;
+	}
+	__putname(name);
+	__putname(utf16name);
+	ctx->pos = file_inode(file)->i_size + 2;
+	return 0;
+fail:
+	__putname(name);
+	__putname(utf16name);
+	return error;
+}
+
+/*
+ * readdir callback for VFS. fill "." and "..", then invoke
+ * __exfat_iterate.
+ */
+int exfat_iterate(struct file *file, struct dir_context *ctx)
+{
+	struct exfat_dir_ctx dctx;
+	int error;
+	struct inode *inode = file_inode(file);
+
+	switch (ctx->pos) {
+	case 0:
+		return dir_emit_dots(file, ctx);
+	default:
+		if (ctx->pos >= inode->i_size + 2)
+			return 0;
+		error = exfat_init_dir_ctx(inode, &dctx, ctx->pos - 2);
+		if (error)
+			return error;
+		exfat_lock_super(inode->i_sb);
+		error = __exfat_iterate(&dctx, file, ctx);
+		exfat_unlock_super(inode->i_sb);
+		exfat_cleanup_dir_ctx(&dctx);
+		return error;
+	}
+}
diff -Nruw linux-4.2-fbx/fs/exfat./exfat_fs.h linux-4.2-fbx/fs/exfat/exfat_fs.h
--- linux-4.2-fbx/fs/exfat./exfat_fs.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/fs/exfat/exfat_fs.h	2013-12-04 14:33:22.527479030 +0100
@@ -0,0 +1,200 @@
+/*
+ * exfat_fs.h for exfat
+ * Created by <nschichan@freebox.fr> on Mon Jul 29 15:06:38 2013
+ */
+
+#ifndef __EXFAT_FS_H
+# define __EXFAT_FS_H
+
+/*
+ * exfat on disk structures and constants
+ */
+
+#include <linux/types.h>
+
+struct exfat_vbr {
+	u8	jump[3];
+	u8	fsname[8];
+	u8	reserved1[53];
+
+	__le64	partition_offset;
+	__le64	volume_length;
+
+	__le32	fat_offset;
+	__le32	fat_length;
+
+	__le32	cluster_heap_offset;
+	__le32	cluster_count;
+	__le32	cluster_root_dir;
+
+	__le32	serial_number;
+
+	__le16	fs_rev;
+	__le16	volume_flags;
+
+	u8	bytes_per_sector;
+	u8	sectors_per_cluster;
+
+	u8	fat_num;
+	u8	drive_select;
+	u8	heap_use_percent;
+
+	u8	reserved2[7];
+	u8	boot_code[390];
+
+	u8	boot_sig[2];
+};
+
+enum {
+	EXFAT_CLUSTER_FIRSTVALID	= 0x00000002,
+	EXFAT_CLUSTER_LASTVALID		= 0xfffffff6,
+	EXFAT_CLUSTER_BADBLK		= 0xfffffff7,
+	EXFAT_CLUSTER_MEDIATYPE		= 0xfffffff8,
+	EXFAT_CLUSTER_EOF		= 0xffffffff,
+};
+
+enum {
+	EXFAT_ACTIVEFAT_MASK = (1 << 0),
+	EXFAT_FLAG_DIRTY = (1 << 1),
+	EXFAT_FLAG_MEDIA_FAILURE = (1 << 2),
+};
+
+static inline int exfat_active_fat(u16 flags)
+{
+	return flags & EXFAT_ACTIVEFAT_MASK;
+}
+
+#define EXFAT_CHECKSUM_SECTORS	11
+
+enum {
+	EXFAT_I_ALLOC_POSSIBLE = (1 << 0),
+	EXFAT_I_FAT_INVALID = (1 << 1),
+};
+
+/*
+ * directory cluster content
+ */
+
+/*
+ * entry types
+ */
+enum {
+	E_EXFAT_EOD		= 0x00,
+	E_EXFAT_VOLUME_LABEL	= 0x83,
+	E_EXFAT_BITMAP		= 0x81,
+	E_EXFAT_UPCASE_TABLE	= 0x82,
+	E_EXFAT_GUID		= 0xa0,
+	E_EXFAT_PADDING		= 0xa1,
+	E_EXFAT_ACL		= 0xe2,
+	E_EXFAT_FILEDIR		= 0x85,
+	E_EXFAT_STREAM_EXT	= 0xc0,
+	E_EXFAT_FILENAME	= 0xc1,
+};
+
+/*
+ * file attributes in exfat_filedir_entry
+ */
+enum {
+	E_EXFAT_ATTR_RO		= (1 << 0),
+	E_EXFAT_ATTR_HIDDEN	= (1 << 1),
+	E_EXFAT_ATTR_SYSTEM	= (1 << 2),
+	/* bit 3 reserved */
+	E_EXFAT_ATTR_DIRECTORY	= (1 << 4),
+	E_EXFAT_ATTR_ARCHIVE	= (1 << 5),
+	/* bits 6-15 reserved */
+};
+
+/* type 0x83 */
+struct exfat_volume_label_entry {
+	u8 type;
+	u8 charcount;
+	__u16 label[11];
+	u8 reserved1[8];
+};
+
+static inline int exfat_bitmap_nr(u8 flags)
+{
+	return flags & 1;
+}
+
+/* type 0x81 */
+struct exfat_bitmap_entry {
+	u8 type;
+	u8 flags;
+	u8 reserved1[18];
+	__le32 cluster_addr;
+	__le64 length;
+};
+
+/* type 0x82 */
+struct exfat_upcase_entry {
+	u8 type;
+	u8 reserved1[3];
+	__le32 checksum;
+	u8 reserved2[12];
+	__le32 cluster_addr;
+	__le64 length;
+};
+
+/* type 0xa0 */
+struct exfat_guid_entry {
+	u8 type;
+	u8 secondary_count;
+	__le16 set_checksum;
+	__le16 flags;
+	u8 guid[16];
+	u8 reserved1[10];
+};
+
+/* type 0xa1 */
+struct exfat_padding_entry {
+	u8 type;
+	u8 reserved1[31];
+};
+
+/* type 0xe2 */
+struct exfat_acl_entry {
+	u8 type;
+	u8 reserved1[31];
+};
+
+/* type 0x85 */
+struct exfat_filedir_entry {
+	u8 type;
+	u8 secondary_count;
+	__le16 set_checksum;
+	__le16 attributes;
+	u8 reserved1[2];
+	__le32 create;
+	__le32 modified;
+	__le32 accessed;
+	u8 create_10ms;
+	u8 modified_10ms;
+	s8 create_tz_offset;
+	s8 modified_tz_offset;
+	s8 accessed_tz_offset;
+	u8 reserved2[7];
+};
+
+/* 0xc0 */
+struct exfat_stream_extension_entry {
+	u8 type;
+	u8 flags;
+	u8 reserved1;
+	u8 name_length;
+	__le16 name_hash;
+	u8 reserved2[2];
+	__le64 valid_data_length;
+	u8 reserved3[4];
+	__le32 first_cluster;
+	__le64 data_length;
+};
+
+/* 0xc1 */
+struct exfat_filename_entry {
+	u8 type;
+	u8 flags;
+	__le16 name_frag[15];
+};
+
+#endif /*! __EXFAT_FS_H */
diff -Nruw linux-4.2-fbx/fs/exfat./exfat.h linux-4.2-fbx/fs/exfat/exfat.h
--- linux-4.2-fbx/fs/exfat./exfat.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/fs/exfat/exfat.h	2014-06-25 11:22:30.373677444 +0200
@@ -0,0 +1,325 @@
+/*
+ * exfat.h for exfat
+ * Created by <nschichan@freebox.fr> on Tue Jul 23 12:37:12 2013
+ */
+
+#ifndef __EXFAT_H
+# define __EXFAT_H
+
+#define EXFAT_HASH_BITS	(8)
+#define EXFAT_HASH_SIZE	(1 << EXFAT_HASH_BITS)
+
+/*
+ * special inode number for root directory.
+ */
+#define EXFAT_ROOT_INO	1
+
+enum {
+	EXFAT_ERROR_ACTION_CONTINUE,
+	EXFAT_ERROR_ACTION_REMOUNT_RO,
+	EXFAT_ERROR_ACTION_PANIC,
+};
+
+struct exfat_sb_options {
+	kuid_t	uid;
+	kgid_t	gid;
+	mode_t	dmask;
+	mode_t	fmask;
+	int	time_offset;
+	int	time_offset_set;
+	int	error_action;
+};
+
+struct exfat_sb_info {
+	struct exfat_sb_options options;
+
+	struct buffer_head *sb_bh;
+	struct exfat_vbr *vbr;
+	bool dirty;
+
+	u32 sectorsize; /* in bytes*/
+	u32 clustersize; /* in bytes */
+	u32 sectors_per_cluster;
+	int sectorbits;
+	int clusterbits;
+	u32 sectormask;
+	u32 clustermask;
+
+	u32 fat_offset;
+	u32 fat_length;
+
+	u32 root_dir_cluster;
+	u32 cluster_heap_offset;
+	u32 cluster_count;
+
+	__le16	*upcase_table;
+	u32	upcase_len;
+
+	/*
+	 * bitmap fields
+	 */
+	struct mutex		bitmap_mutex;
+	u32			bitmap_length;
+	sector_t		first_bitmap_sector;
+	sector_t		last_bitmap_sector;
+	sector_t		cur_bitmap_sector;
+	u32			cur_bitmap_cluster;
+	struct buffer_head	*cur_bitmap_bh;
+	u32			free_clusters;
+	u32			prev_free_cluster;
+
+	/*
+	 * inode hash fields
+	 */
+	spinlock_t		inode_hash_lock;
+	struct hlist_head	inode_hash[EXFAT_HASH_SIZE];
+
+	struct mutex		sb_mutex;
+};
+
+struct exfat_cache_entry {
+	struct list_head list;
+	u32 file_cluster;
+	u32 disk_cluster;
+	u32 nr_contig;
+};
+
+struct exfat_cache {
+	struct mutex		mutex;
+	struct list_head	entries;
+	u32			nr_entries;
+};
+
+struct exfat_iloc {
+	u8 nr_secondary;
+	u32 file_off;
+	u64 disk_offs[19];
+};
+
+struct exfat_inode_info {
+	u8			flags;
+	u16			attributes;
+	u32			first_cluster;
+	u32			allocated_clusters;
+	loff_t			mmu_private;
+	struct exfat_iloc	iloc;
+	struct hlist_node	hash_list;
+
+	struct exfat_cache	exfat_cache;
+	struct inode		vfs_inode;
+};
+
+static inline struct exfat_sb_info *EXFAT_SB(struct super_block *sb)
+{
+	return sb->s_fs_info;
+}
+
+static inline struct exfat_inode_info *EXFAT_I(struct inode *inode)
+{
+	return container_of(inode, struct exfat_inode_info, vfs_inode);
+}
+
+loff_t exfat_dir_links(struct inode *inode);
+
+int exfat_write_fat_contiguous(struct inode *inode, u32 first_cluster,
+			       u32 nr_clusters);
+int exfat_write_fat(struct inode *inode, u32 prev_cluster, u32 *clusters,
+		    u32 nr_clusters);
+
+__printf(3, 4) void exfat_msg(struct super_block *sb, const char *level,
+			      const char *fmt, ...);
+__printf(2, 3) void exfat_fs_error(struct super_block *sb,
+				   const char *fmt, ...);
+int exfat_get_fat_cluster(struct inode *inode, u32 fcluster, u32 *dcluster);
+int __exfat_get_fat_cluster(struct inode *inode, u32 fcluster, u32 *dcluster,
+			    bool eof_is_fatal);
+
+void exfat_inode_cache_init(struct inode *inode);
+void exfat_inode_cache_drop(struct inode *inode);
+
+int exfat_init_fat(struct super_block *sb);
+
+int exfat_init_bitmap(struct inode *root);
+void exfat_exit_bitmap(struct super_block *sb);
+int exfat_alloc_clusters(struct inode *inode, u32 hint_cluster,
+			 u32 *cluster, u32 nr);
+int exfat_free_clusters_inode(struct inode *inode, u32 start);
+
+
+/*
+ * read only bitmap accessors: used by EXFAT_IOCGETBITMAP ioctl.
+ */
+struct exfat_bitmap_ctx {
+	struct super_block *sb;
+	struct buffer_head *bh;
+	sector_t cur_sector;
+};
+
+int exfat_init_bitmap_context(struct super_block *sb,
+			      struct exfat_bitmap_ctx *ctx, u32 cluster);
+void exfat_exit_bitmap_context(struct exfat_bitmap_ctx *ctx);
+int exfat_test_bitmap(struct exfat_bitmap_ctx *ctx, uint32_t start_cluster,
+		      uint32_t *first_in_use, uint32_t *nr_in_use);
+
+
+/*
+ * return the physical sector address for a given cluster.
+ */
+static inline sector_t exfat_cluster_sector(struct exfat_sb_info *sbi,
+					    u32 cluster)
+{
+	return (sector_t)sbi->cluster_heap_offset + (cluster - 2) *
+		(sector_t)sbi->sectors_per_cluster;
+}
+
+/*
+ * in dir.c
+ */
+struct exfat_dir_ctx {
+	struct super_block	*sb;
+	struct inode		*inode;
+	struct buffer_head	*bh;
+
+	off_t			off; /* from beginning of directory */
+	sector_t		sector;
+	bool empty;
+};
+
+int exfat_init_dir_ctx(struct inode *inode, struct exfat_dir_ctx *ctx,
+		       off_t off);
+void exfat_cleanup_dir_ctx(struct exfat_dir_ctx *dctx);
+int exfat_get_cluster_hint(struct inode *inode, u32 *out_hint);
+int exfat_dentry_next(void *, struct exfat_dir_ctx *, int, bool);
+void *__exfat_dentry_next(struct exfat_dir_ctx *dctx, int type, int mask,
+			  bool can_skip, bool *end);
+u16 exfat_direntry_checksum(void *data, u16 checksum, bool first);
+u32 exfat_dctx_fpos(struct exfat_dir_ctx *dctx);
+u64 exfat_dctx_dpos(struct exfat_dir_ctx *dctx);
+int __exfat_get_name(struct exfat_dir_ctx *dctx, u32 name_length, __le16 *name,
+		     u16 *calc_checksum, struct exfat_iloc *iloc);
+
+/*
+ * in namei.c
+ */
+
+/*
+ * hold a pointer to an exfat dir entry, with the corresponding bh.
+ */
+struct dir_entry_buffer {
+	struct buffer_head *bh;
+	u32 off; /* in bytes, inside the buffer_head b_data array */
+	void *start;
+};
+
+int exfat_get_dir_entry_buffers(struct inode *dir, struct exfat_iloc *iloc,
+				struct dir_entry_buffer *entries,
+				size_t nr_entries);
+u16 exfat_dir_entries_checksum(struct dir_entry_buffer *entries, u32 nr);
+void exfat_dirty_dir_entries(struct dir_entry_buffer *entries,
+			     size_t nr_entries, bool sync);
+void exfat_write_time(struct exfat_sb_info *sbi, struct timespec *ts,
+		      __le32 *datetime, u8 *time_cs, u8 *tz_offset);
+
+/*
+ * in inode.c
+ */
+
+int exfat_init_inodes(void);
+void exfat_exit_inodes(void);
+
+struct inode *exfat_iget(struct super_block *sb, loff_t disk_pos);
+void exfat_insert_inode_hash(struct inode *inode);
+void exfat_remove_inode_hash(struct inode *inode);
+int __exfat_write_inode(struct inode *inode, bool sync);
+
+/*
+ * in upcase.c
+ */
+int exfat_upcase_init(struct inode *root);
+static inline __le16 exfat_upcase_convert(struct super_block *sb, __le16 _c)
+{
+	u16 c = __le16_to_cpu(_c);
+
+	if (c >= EXFAT_SB(sb)->upcase_len)
+		return _c;
+	return EXFAT_SB(sb)->upcase_table[c];
+}
+
+/*
+ * superblock operations
+ */
+struct inode *exfat_alloc_inode(struct super_block *sb);
+void exfat_destroy_inode(struct inode *_inode);
+int exfat_drop_inode(struct inode *inode);
+void exfat_evict_inode(struct inode *inode);
+
+/*
+ * file operations
+ */
+int exfat_iterate(struct file *f, struct dir_context *ctx);
+long exfat_ioctl(struct file *, unsigned int, unsigned long);
+int exfat_truncate_blocks(struct inode *inode, loff_t newsize);
+
+/*
+ * inode operations
+ */
+struct dentry *exfat_inode_lookup(struct inode *, struct dentry *,
+				  unsigned int);
+int exfat_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+		       bool excl);
+int exfat_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);
+
+mode_t exfat_make_mode(struct exfat_sb_info *sbi, mode_t mode, u16 attrs);
+
+int exfat_write_inode(struct inode *inode, struct writeback_control *wbc);
+
+int exfat_inode_unlink(struct inode *inode, struct dentry *dentry);
+
+int exfat_inode_rmdir(struct inode *inode, struct dentry *dentry);
+
+int exfat_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+int exfat_setattr(struct dentry *, struct iattr *);
+int exfat_rename(struct inode *, struct dentry *,
+		 struct inode *, struct dentry *);
+
+/*
+ * address space operations
+ */
+int exfat_readpage(struct file *file, struct page *page);
+int exfat_readpages(struct file *file, struct address_space *mapping,
+		    struct list_head *pages, unsigned nr_pages);
+int exfat_write_begin(struct file *file, struct address_space *mapping,
+		      loff_t pos, unsigned len, unsigned flags,
+		      struct page **pagep, void **fsdata);
+int exfat_write_end(struct file *file, struct address_space *mapping,
+		    loff_t pos, unsigned len, unsigned copied,
+		    struct page *page, void *fsdata);
+int exfat_writepage(struct page *page, struct writeback_control *wbc);
+int exfat_writepages(struct address_space *, struct writeback_control *);
+
+
+extern const struct inode_operations exfat_dir_inode_operations;
+extern const struct inode_operations exfat_file_inode_operations;
+extern const struct file_operations exfat_dir_operations;
+extern const struct file_operations exfat_file_operations;
+extern const struct address_space_operations exfat_address_space_operations;
+
+/*
+ * time functions
+ */
+void exfat_time_2unix(struct timespec *ts, u32 datetime, u8 time_cs,
+		      s8 tz_offset);
+void exfat_time_2exfat(struct exfat_sb_info *sbi, struct timespec *ts,
+		       u32 *datetime, u8 *time_cs, s8 *tz_offset);
+
+static inline void exfat_lock_super(struct super_block *sb)
+{
+	mutex_lock(&EXFAT_SB(sb)->sb_mutex);
+}
+
+static inline void exfat_unlock_super(struct super_block *sb)
+{
+	mutex_unlock(&EXFAT_SB(sb)->sb_mutex);
+}
+
+#endif /*! __EXFAT_H */
diff -Nruw linux-4.2-fbx/fs/exfat./fat.c linux-4.2-fbx/fs/exfat/fat.c
--- linux-4.2-fbx/fs/exfat./fat.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/fs/exfat/fat.c	2014-06-25 11:22:30.377677444 +0200
@@ -0,0 +1,424 @@
+/*
+ * fat.c for exfat
+ * Created by <nschichan@freebox.fr> on Mon Jul 29 19:43:38 2013
+ */
+
+#include <linux/fs.h>
+#include <linux/buffer_head.h>
+#include <linux/slab.h>
+
+#include "exfat.h"
+#include "exfat_fs.h"
+
+#define MAX_CACHED_FAT	16
+
+/*
+ * helpers for exfat_next_fat_cluster.
+ */
+
+/*
+ * get the sector number in the fat where the next requested cluster
+ * number is to be found.
+ */
+static inline sector_t cluster_sector(struct exfat_sb_info *sbi, u32 cluster)
+{
+	return sbi->fat_offset + (((u64)cluster * sizeof (u32)) >> sbi->sectorbits);
+}
+
+/*
+ * get the offset in the fat sector where the next requested cluster
+ * number is to be found.
+ */
+static inline off_t cluster_offset(struct exfat_sb_info *sbi, u32 cluster)
+{
+	return (cluster * sizeof (u32)) & sbi->sectormask;
+}
+
+/*
+ * walk one step in the fat chain.
+ */
+static int exfat_next_fat_cluster(struct super_block *sb, u32 *cluster)
+{
+	struct exfat_sb_info *sbi = EXFAT_SB(sb);
+	sector_t sect = cluster_sector(sbi, *cluster);
+	off_t off = cluster_offset(sbi, *cluster);
+	struct buffer_head *bh;
+
+	bh = sb_bread(sb, sect);
+	if (!bh) {
+		exfat_msg(sb, KERN_ERR, "unable to read FAT sector at %llu",
+			  sect);
+		return -EIO;
+	}
+
+	*cluster = __le32_to_cpu(*(u32*)&bh->b_data[off]);
+	brelse(bh);
+	return 0;
+}
+
+/*
+ * setup inode cache
+ */
+void exfat_inode_cache_init(struct inode *inode)
+{
+	mutex_init(&EXFAT_I(inode)->exfat_cache.mutex);
+	EXFAT_I(inode)->exfat_cache.nr_entries = 0;
+	INIT_LIST_HEAD(&EXFAT_I(inode)->exfat_cache.entries);
+}
+
+/*
+ * drop inode cache content
+ */
+void exfat_inode_cache_drop(struct inode *inode)
+{
+	struct exfat_cache *cache = &EXFAT_I(inode)->exfat_cache;
+	struct exfat_cache_entry *e, *tmp;
+
+	mutex_lock(&cache->mutex);
+	list_for_each_entry_safe (e, tmp, &cache->entries, list) {
+		kfree(e);
+	}
+	INIT_LIST_HEAD(&cache->entries);
+	cache->nr_entries = 0;
+	mutex_unlock(&cache->mutex);
+}
+
+/*
+ * move the entry to the head of the list, this will make it less
+ * likely to be the victim in when caching new entries.
+ *
+ * caller must hold cache->mutex.
+ */
+static void __exfat_fat_lru(struct exfat_cache *cache,
+			  struct exfat_cache_entry *e)
+{
+	if (cache->entries.next != &e->list)
+		list_move(&e->list, &cache->entries);
+}
+
+/*
+ * find a cache entry that is close to the wanted fcluster (ideally
+ * spanning over the requested file cluster).
+ *
+ * caller must hold cache->mutex.
+ */
+static struct exfat_cache_entry *__exfat_cache_lookup(struct exfat_cache *cache,
+						      u32 fcluster)
+{
+	struct exfat_cache_entry *e;
+	struct exfat_cache_entry *best = NULL;
+
+	list_for_each_entry (e, &cache->entries, list) {
+		if (e->file_cluster <= fcluster &&
+		    e->file_cluster + e->nr_contig >= fcluster)
+			return e;
+
+		if (!best && e->file_cluster < fcluster)
+			best = e;
+		if (best && best->file_cluster < e->file_cluster &&
+		    e->file_cluster < fcluster)
+			best = e;
+	}
+	return best;
+}
+
+/*
+ * caller must hold cache->mutex.
+ */
+static int __exfat_cache_cluster(struct exfat_cache *cache,
+			       struct exfat_cache_entry *nearest,
+			       u32 fcluster, u32 dcluster)
+{
+	struct exfat_cache_entry *e;
+
+	/*
+	 * see if we can merge with the nearest entry. in the ideal
+	 * case, all cluster in the chain are contiguous, and only
+	 * one entry is needed for a single file.
+	 */
+	if (nearest &&
+	    nearest->file_cluster + nearest->nr_contig + 1 == fcluster &&
+	    nearest->disk_cluster + nearest->nr_contig + 1 == dcluster) {
+		list_move(&nearest->list, &cache->entries);
+		nearest->nr_contig++;
+		return 0;
+	}
+
+	/*
+	 * allocate a new entry or reuse an existing one if the number
+	 * of cached entries is too hihc.
+	 */
+	if (cache->nr_entries < MAX_CACHED_FAT) {
+		e = kmalloc(sizeof (*e), GFP_NOFS);
+		list_add(&e->list, &cache->entries);
+		++cache->nr_entries;
+	} else {
+		e = list_entry(cache->entries.prev, struct exfat_cache_entry,
+			       list);
+		list_move(&e->list, &cache->entries);
+	}
+
+	if (!e)
+		return -ENOMEM;
+
+	e->file_cluster = fcluster;
+	e->disk_cluster = dcluster;
+	e->nr_contig = 0;
+
+	return 0;
+}
+
+int __exfat_get_fat_cluster(struct inode *inode, u32 fcluster, u32 *dcluster,
+			    bool eof_is_fatal)
+{
+	struct exfat_inode_info *info = EXFAT_I(inode);
+	struct exfat_cache *cache = &info->exfat_cache;
+	int error;
+	struct exfat_cache_entry *e;
+	u32 fcluster_start;
+
+	/*
+	 * intial translation: first file cluster is found in the
+	 * inode info.
+	 */
+	if (fcluster == 0) {
+		*dcluster = info->first_cluster;
+		return 0;
+	}
+
+	mutex_lock(&cache->mutex);
+	/*
+	 * try to find a cached entry either covering the file cluster
+	 * we want or at least close to the file cluster.
+	 */
+	e = __exfat_cache_lookup(cache, fcluster);
+	if (e && e->file_cluster <= fcluster &&
+	    e->file_cluster + e->nr_contig >= fcluster) {
+		/*
+		 * perfect match, entry zone covers the requested file
+		 * cluster.
+		 */
+		__exfat_fat_lru(cache, e);
+		*dcluster = e->disk_cluster + (fcluster - e->file_cluster);
+		mutex_unlock(&cache->mutex);
+		return 0;
+	}
+
+	if (e) {
+		/*
+		 * we have an entry, hopefully close enough, setup
+		 * cluster walk from there.
+		 */
+		*dcluster = e->disk_cluster + e->nr_contig;
+		fcluster_start = e->file_cluster + e->nr_contig;
+	} else {
+		/*
+		 * no entry, walk the FAT chain from the start of the
+		 * file.
+		 */
+		fcluster_start = 0;
+		*dcluster = info->first_cluster;
+	}
+
+	/*
+	 * walk fhe FAT chain the number of time required to get the
+	 * disk cluster corresponding to the file cluster.
+	 */
+	while (fcluster_start != fcluster) {
+		error = exfat_next_fat_cluster(inode->i_sb, dcluster);
+		if (error) {
+			mutex_unlock(&cache->mutex);
+			return error;
+		}
+		if (*dcluster == EXFAT_CLUSTER_EOF) {
+			if (eof_is_fatal)
+				/*
+				 * exfat_fill_root uses
+				 * __exfat_get_fat_cluster with
+				 * eof_is_fatal set to false, as the
+				 * root inode does not have a size
+				 * field and thus requires a complete
+				 * FAT walk to compute the size.
+				 */
+				exfat_fs_error(inode->i_sb, "premature EOF in FAT "
+					       "chain. file cluster %u out "
+					       "of %u\n", fcluster_start,
+					       fcluster);
+			mutex_unlock(&cache->mutex);
+			return -EIO;
+		}
+		if (*dcluster < EXFAT_CLUSTER_FIRSTVALID) {
+			exfat_fs_error(inode->i_sb, "invalid cluster %u found "
+				       "in fat chain.", *dcluster);
+			mutex_unlock(&cache->mutex);
+			return -EIO;
+		}
+		++fcluster_start;
+	}
+
+	/*
+	 * cache the result.
+	 */
+	__exfat_cache_cluster(cache, e, fcluster, *dcluster);
+	mutex_unlock(&cache->mutex);
+	return 0;
+}
+
+int exfat_get_fat_cluster(struct inode *inode, u32 fcluster, u32 *dcluster)
+{
+	return __exfat_get_fat_cluster(inode, fcluster, dcluster, true);
+}
+
+int exfat_init_fat(struct super_block *sb)
+{
+	struct exfat_sb_info *sbi = EXFAT_SB(sb);
+	struct buffer_head *bh;
+	int error = 0;
+	u32 first, second;
+
+	bh = sb_bread(sb, sbi->fat_offset);
+	if (!bh) {
+		exfat_msg(sb, KERN_ERR, "unable to read FAT sector at %u",
+			  sbi->fat_offset);
+		return -EIO;
+	}
+
+	first = __le32_to_cpu(*(__le32*)(bh->b_data + 0));
+	second = __le32_to_cpu(*(__le32*)(bh->b_data + sizeof (__le32)));
+
+	if (first != 0xf8ffffff && second != 0xffffffff) {
+		exfat_msg(sb, KERN_INFO, "invalid FAT start: %08x, %08x",
+			  first, second);
+		error = -ENXIO;
+	}
+
+	brelse(bh);
+	return error;
+}
+
+/*
+ * fat write context, store the current buffer_head and current
+ * cluster to avoid having sb_bread all the time when the clusters are
+ * contiguous or at least not too far apart.
+ */
+struct fat_write_ctx {
+	struct super_block *sb;
+	struct buffer_head *bh;
+	u32 cur_cluster;
+};
+
+static void fat_init_write_ctx(struct fat_write_ctx *fwctx,
+				struct super_block *sb)
+{
+	memset(fwctx, 0, sizeof (*fwctx));
+	fwctx->sb = sb;
+}
+
+static void fat_exit_write_ctx(struct fat_write_ctx *fwctx)
+{
+	if (fwctx->bh)
+		brelse(fwctx->bh);
+}
+
+static int __fat_write_entry(struct fat_write_ctx *fwctx,
+			       u32 cluster, u32 next)
+{
+	struct exfat_sb_info *sbi = EXFAT_SB(fwctx->sb);
+	sector_t current_sector = cluster_sector(sbi, fwctx->cur_cluster);
+	sector_t wanted_sector = cluster_sector(sbi, cluster);
+	off_t off = cluster_offset(sbi, cluster);
+
+	/*
+	 * first see if we need a different buffer head from the
+	 * current one in the fat_write_ctx.
+	 */
+	if (current_sector != wanted_sector || !fwctx->bh) {
+		if (fwctx->bh)
+			brelse(fwctx->bh);
+		fwctx->bh = sb_bread(fwctx->sb, wanted_sector);
+		if (!fwctx->bh) {
+			exfat_msg(fwctx->sb, KERN_ERR,
+				  "unable to read FAT sector at %llu",
+				  wanted_sector);
+			return -EIO;
+		}
+	}
+
+	/*
+	 * set fat cluster to point to the next cluster, and mark bh
+	 * dirty so that the change hits the storage device.
+	 */
+	fwctx->cur_cluster = cluster;
+	*(__le32*)(fwctx->bh->b_data + off) = __cpu_to_le32(next);
+	mark_buffer_dirty(fwctx->bh);
+	return 0;
+}
+
+/*
+ * write nr_clusters contiguous clusters starting at first_cluster.
+ */
+int exfat_write_fat_contiguous(struct inode *inode, u32 first_cluster,
+			       u32 nr_clusters)
+{
+	u32 cluster;
+	struct fat_write_ctx fwctx;
+	int error = 0;
+
+	fat_init_write_ctx(&fwctx, inode->i_sb);
+	for (cluster = first_cluster;
+	     cluster < first_cluster + nr_clusters - 1;
+	     ++cluster) {
+		error = __fat_write_entry(&fwctx, cluster, cluster + 1);
+		if (error)
+			goto end;
+	}
+
+	/*
+	 * set EOF
+	 */
+	error = __fat_write_entry(&fwctx, cluster, EXFAT_CLUSTER_EOF);
+end:
+	fat_exit_write_ctx(&fwctx);
+	return error;
+
+}
+
+/*
+ * write cluster nr_clusters stored in clusters array, link with prev_cluster.
+ */
+int exfat_write_fat(struct inode *inode, u32 prev_cluster, u32 *clusters,
+		    u32 nr_clusters)
+{
+	u32 i;
+	struct fat_write_ctx fwctx;
+	int error;
+
+	if (!nr_clusters)
+		/* ??! */
+		return 0;
+
+	fat_init_write_ctx(&fwctx, inode->i_sb);
+
+	if (prev_cluster) {
+		/*
+		 * link with previous cluster if applicable.
+		 */
+		error = __fat_write_entry(&fwctx, prev_cluster, clusters[0]);
+		if (error)
+			goto end;
+	}
+	for (i = 0; i < nr_clusters - 1; ++i) {
+		error = __fat_write_entry(&fwctx, clusters[i], clusters[i + 1]);
+		if (error)
+			goto end;
+	}
+
+	/*
+	 * set EOF.
+	 */
+	error = __fat_write_entry(&fwctx, clusters[i], EXFAT_CLUSTER_EOF);
+
+ end:
+	fat_exit_write_ctx(&fwctx);
+	return error;
+}
diff -Nruw linux-4.2-fbx/fs/exfat./file.c linux-4.2-fbx/fs/exfat/file.c
--- linux-4.2-fbx/fs/exfat./file.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/fs/exfat/file.c	2015-09-15 19:18:39.538464718 +0200
@@ -0,0 +1,427 @@
+/*
+ * file.c for exfat
+ * Created by <nschichan@freebox.fr> on Tue Aug 20 14:39:41 2013
+ */
+
+#include <linux/buffer_head.h>
+#include <linux/fs.h>
+#include <linux/exfat_user.h>
+
+#include "exfat.h"
+#include "exfat_fs.h"
+
+static int append_fragment(struct exfat_fragment __user *ufrag,
+			   struct exfat_fragment *kfrag)
+{
+	if (copy_to_user(ufrag, kfrag, sizeof (*kfrag)))
+		return -EFAULT;
+	return 0;
+}
+
+static void setup_fragment(struct exfat_sb_info *sbi,
+			  struct exfat_fragment *fragment, uint32_t fcluster,
+			  uint32_t dcluster)
+{
+	fragment->fcluster_start = fcluster;
+	fragment->dcluster_start = dcluster;
+	fragment->sector_start = exfat_cluster_sector(sbi, dcluster);
+	fragment->nr_clusters = 1;
+}
+
+static int exfat_ioctl_get_fragments(struct inode *inode,
+				     struct exfat_fragment_head __user *uhead)
+{
+	struct exfat_fragment_head head;
+	struct exfat_fragment fragment;
+	u32 fcluster;
+	u32 prev_dcluster;
+	u32 cur_fragment;
+	struct exfat_inode_info *info = EXFAT_I(inode);
+	struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb);
+	int error;
+
+	memset(&fragment, 0, sizeof (fragment));
+
+	if (copy_from_user(&head, uhead, sizeof (head)))
+		return -EFAULT;
+
+
+	if (put_user(sbi->sectorsize, &uhead->sector_size) ||
+	    put_user(sbi->clustersize, &uhead->cluster_size))
+		return -EFAULT;
+
+	if (!head.nr_fragments) {
+		/*
+		 * user did not provide space for fragments after
+		 * header.
+		 */
+		return 0;
+	}
+
+	if (head.fcluster_start >= info->allocated_clusters) {
+		/*
+		 * requested start cluster is after file EOF
+		 */
+		if (put_user(0, &uhead->nr_fragments))
+			return -EFAULT;
+		return 0;
+	}
+
+	if (info->flags & EXFAT_I_FAT_INVALID) {
+		/*
+		 * not FAT chain, this file has only one fragment.
+		 */
+		fragment.fcluster_start = head.fcluster_start;
+		fragment.dcluster_start =
+			info->first_cluster + head.fcluster_start;
+		fragment.nr_clusters = info->allocated_clusters -
+			head.fcluster_start;
+		fragment.sector_start =
+			exfat_cluster_sector(sbi, fragment.dcluster_start);
+
+		if (copy_to_user(&uhead->fragments[0], &fragment,
+				 sizeof (fragment)))
+			return -EFAULT;
+		if (put_user(1, &uhead->nr_fragments))
+			return -EFAULT;
+		if (put_user(info->first_cluster + info->allocated_clusters,
+			     &uhead->fcluster_start))
+			return -EFAULT;
+		return 0;
+	}
+
+	fcluster = head.fcluster_start;
+	cur_fragment = 0;
+
+	/*
+	 * initial fragment setup
+	 */
+	error = exfat_get_fat_cluster(inode, fcluster,
+				      &prev_dcluster);
+	if (error)
+		return error;
+	setup_fragment(sbi, &fragment, fcluster, prev_dcluster);
+	++fcluster;
+	while (fcluster < info->allocated_clusters) {
+		int error;
+		u32 dcluster;
+
+		/*
+		 * walk one step in the FAT.
+		 */
+		error = exfat_get_fat_cluster(inode, fcluster, &dcluster);
+		if (error)
+			return error;
+
+		if (prev_dcluster == dcluster - 1) {
+			/*
+			 * dcluster and prev_dcluster are contiguous.
+			 */
+			++fragment.nr_clusters;
+		} else {
+			/*
+			 * put this cluster in the user array
+			 */
+			error = append_fragment(&uhead->fragments[cur_fragment],
+						&fragment);
+			if (error)
+				return error;
+
+			++cur_fragment;
+			if (cur_fragment == head.nr_fragments)
+				break;
+
+			/*
+			 * setup a new fragment.
+			 */
+			setup_fragment(sbi, &fragment, fcluster, dcluster);
+		}
+		++fcluster;
+		prev_dcluster = dcluster;
+	}
+
+	if (cur_fragment < head.nr_fragments) {
+		append_fragment(&uhead->fragments[cur_fragment], &fragment);
+		++cur_fragment;
+	}
+
+	/*
+	 * update nr_fragments in user supplied head.
+	 */
+	if (cur_fragment != head.nr_fragments &&
+	    put_user(cur_fragment, &uhead->nr_fragments))
+		return -EFAULT;
+
+	/*
+	 * update fcluster_start in user supplied head.
+	 */
+	if (put_user(fcluster, &uhead->fcluster_start))
+		return -EFAULT;
+
+
+	return 0;
+}
+
+static int exfat_ioctl_get_bitmap(struct super_block *sb,
+				  struct exfat_bitmap_head __user *uhead)
+{
+	struct exfat_sb_info *sbi = EXFAT_SB(sb);
+	struct exfat_bitmap_head head;
+	uint32_t i;
+	int error;
+	struct exfat_bitmap_ctx ctx;
+	uint32_t start_cluster;
+
+	if (copy_from_user(&head, uhead, sizeof (head)))
+		return -EFAULT;
+
+	start_cluster = head.start_cluster;
+	if (start_cluster < 2)
+		return -EINVAL;
+
+
+	error = exfat_init_bitmap_context(sb, &ctx, head.start_cluster);
+	if (error)
+		return error;
+	for (i = 0; i < head.nr_entries; ++i) {
+		uint32_t first_in_use;
+		uint32_t nr_in_use;
+		int error;
+
+		error = exfat_test_bitmap(&ctx, start_cluster, &first_in_use,
+					  &nr_in_use);
+		if (error)
+			goto out_error;
+
+		if (first_in_use == sbi->cluster_count)
+			break;
+		if (put_user(first_in_use, &uhead->entries[i].start_cluster))
+			goto out_efault;
+		if (put_user(nr_in_use, &uhead->entries[i].nr_clusters))
+			goto out_efault;
+		if (put_user(exfat_cluster_sector(sbi, first_in_use),
+			     &uhead->entries[i].sector_start))
+			goto out_efault;
+		if (put_user((u64)nr_in_use * sbi->sectors_per_cluster,
+			     &uhead->entries[i].nr_sectors))
+			goto out_efault;
+		start_cluster = first_in_use + nr_in_use + 1;
+	}
+
+	exfat_exit_bitmap_context(&ctx);
+	if (put_user(i, &uhead->nr_entries))
+		return -EFAULT;
+	if (put_user(start_cluster, &uhead->start_cluster))
+		return -EFAULT;
+
+	return 0;
+
+out_efault:
+	error = -EFAULT;
+out_error:
+	exfat_exit_bitmap_context(&ctx);
+	return error;
+}
+
+static int exfat_ioctl_get_dirents(struct inode *inode,
+				   struct exfat_dirent_head __user *uhead)
+{
+	struct exfat_dir_ctx dctx;
+	struct exfat_dirent_head head;
+	int error;
+	uint32_t i;
+
+	if (!S_ISDIR(inode->i_mode))
+		return -ENOTDIR;
+
+	if (copy_from_user(&head, uhead, sizeof (head)))
+		return -EFAULT;
+
+	/* make sure we're aligned on an entry boundary */
+	head.offset &= ~0x1f;
+
+	error = exfat_init_dir_ctx(inode, &dctx, head.offset);
+	if (error < 0)
+		return error;
+
+	error = 0;
+	for (i = 0; i < head.nr_entries; ++i) {
+		bool end;
+		u8 *entry = __exfat_dentry_next(&dctx, 0, 0, false, &end);
+		u8 type;
+
+		if (!entry && end)
+			/* genuine end of file */
+			break;
+		if (!entry) {
+			/* something went wrong */
+			error = -EIO;
+			goto out;
+		}
+		type = *entry;
+
+		if (put_user(type, &uhead->entries[i])) {
+			error = -EFAULT;
+			goto out;
+		}
+	}
+
+	/*
+	 * update head nr_entries and offset.
+	 */
+	if (put_user(i, &uhead->nr_entries))  {
+		error = -EFAULT;
+		goto out;
+	}
+	if (put_user(head.offset + 0x20 * i, &uhead->offset)) {
+		error = -EFAULT;
+		goto out;
+	}
+
+ out:
+	exfat_cleanup_dir_ctx(&dctx);
+	return error;
+}
+
+long exfat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	switch (cmd) {
+	case EXFAT_IOCGETFRAGMENTS:
+		return exfat_ioctl_get_fragments(file_inode(file),
+						 (void __user*)arg);
+	case EXFAT_IOCGETBITMAP:
+		return exfat_ioctl_get_bitmap(file_inode(file)->i_sb,
+					      (void __user*)arg);
+	case EXFAT_IOCGETDIRENTS:
+		return exfat_ioctl_get_dirents(file_inode(file),
+					       (void __user*)arg);
+	default:
+		return -ENOTTY;
+	}
+}
+
+static int exfat_cont_expand(struct inode *inode, loff_t newsize)
+{
+	int error;
+
+	error = generic_cont_expand_simple(inode, newsize);
+	if (error)
+		return error;
+
+	inode->i_mtime = CURRENT_TIME_SEC;
+	mark_inode_dirty(inode);
+
+	if (IS_SYNC(inode))
+		exfat_msg(inode->i_sb, KERN_ERR, "TODO: cont_expand with "
+			  "sync mode.");
+	return 0;
+}
+
+int exfat_truncate_blocks(struct inode *inode, loff_t newsize)
+{
+	struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb);
+	u32 fcluster = (newsize + sbi->clustersize - 1) >> sbi->clusterbits;
+	int error;
+
+	if (EXFAT_I(inode)->mmu_private > newsize)
+		EXFAT_I(inode)->mmu_private = newsize;
+
+	error = exfat_free_clusters_inode(inode, fcluster);
+	if (error) {
+		exfat_msg(inode->i_sb, KERN_INFO, "exfat_free_clusters_inode: "
+			  "%i", error);
+		return error;
+	}
+
+	return 0;
+}
+
+int exfat_getattr(struct vfsmount *mnt, struct dentry *dentry,
+		  struct kstat *stat)
+{
+	struct inode *inode = dentry->d_inode;
+	generic_fillattr(inode, stat);
+	stat->blksize = EXFAT_SB(inode->i_sb)->clustersize;
+	return 0;
+}
+
+#define EXFAT_VALID_MODE       (S_IFREG | S_IFDIR | S_IRWXUGO)
+
+static int exfat_mode_fixup(struct inode *inode, mode_t *mode)
+{
+	mode_t mask, perm;
+	struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb);
+
+	if (S_ISDIR(*mode))
+		mask = sbi->options.dmask;
+	else
+		mask = sbi->options.fmask;
+
+	perm = *mode & ~(S_IFMT | mask);
+
+	/*
+	 * we want 'r' and 'x' bits when mask allows for it.
+	 */
+	if ((perm & (S_IRUGO | S_IXUGO)) !=
+	    (inode->i_mode & ~mask & (S_IRUGO | S_IXUGO))) {
+		return -EPERM;
+	}
+
+	/*
+	 * we want all 'w' bits or none, depending on mask.
+	 */
+	if ((perm & S_IWUGO) && (perm & S_IWUGO) != (~mask & S_IWUGO))
+		return -EPERM;
+	*mode &= ~mask;
+	return 0;
+}
+
+int exfat_setattr(struct dentry *dentry, struct iattr *attrs)
+{
+	struct inode *inode = dentry->d_inode;
+	int error;
+
+	/*
+	 * can set uid/gid, only if it the same as the current one in
+	 * the inode.
+	 */
+	if (attrs->ia_valid & ATTR_UID &&
+	    !uid_eq(inode->i_uid, attrs->ia_uid))
+		return -EPERM;
+
+	if (attrs->ia_valid & ATTR_GID &&
+	    !gid_eq(inode->i_gid, attrs->ia_gid))
+		return -EPERM;
+
+	if (attrs->ia_valid & ATTR_MODE &&
+	    (attrs->ia_mode & ~EXFAT_VALID_MODE ||
+	     exfat_mode_fixup(inode, &attrs->ia_mode) < 0)) {
+		/*
+		 * silently ignore mode change if we're not OK with
+		 * it (same behavior as vfat).
+		 */
+		attrs->ia_valid &= ~ATTR_MODE;
+	}
+
+	if (attrs->ia_valid & ATTR_SIZE) {
+		inode_dio_wait(inode);
+		if (attrs->ia_size > inode->i_size) {
+			/*
+			 * expand file
+			 */
+			error = exfat_cont_expand(inode, attrs->ia_size);
+			if (error)
+				return error;
+		} else {
+			/*
+			 * shrink file
+			 */
+			truncate_setsize(inode, attrs->ia_size);
+			exfat_truncate_blocks(inode, attrs->ia_size);
+		}
+	}
+
+	setattr_copy(inode, attrs);
+	mark_inode_dirty(inode);
+	return 0;
+}
diff -Nruw linux-4.2-fbx/fs/exfat./inode.c linux-4.2-fbx/fs/exfat/inode.c
--- linux-4.2-fbx/fs/exfat./inode.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/fs/exfat/inode.c	2014-05-09 14:12:54.236546158 +0200
@@ -0,0 +1,278 @@
+/*
+ * inode.c<2> for exfat
+ * Created by <nschichan@freebox.fr> on Wed Jul 24 16:15:52 2013
+ */
+
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/buffer_head.h>
+#include <linux/writeback.h>
+#include <linux/hash.h>
+
+#include "exfat_fs.h"
+#include "exfat.h"
+
+static struct kmem_cache *exfat_inodes_cachep;
+
+/*
+ * inode callbacks.
+ */
+struct inode *exfat_alloc_inode(struct super_block *sb)
+{
+	struct exfat_inode_info *ei = kmem_cache_alloc(exfat_inodes_cachep,
+						       GFP_NOFS);
+
+	if (!ei)
+		return NULL;
+
+	return &ei->vfs_inode;
+}
+
+static void exfat_i_callback(struct rcu_head *head)
+{
+	struct inode *inode = container_of(head, struct inode, i_rcu);
+
+	kmem_cache_free(exfat_inodes_cachep, EXFAT_I(inode));
+}
+
+void exfat_destroy_inode(struct inode *_inode)
+{
+	struct exfat_inode_info *inode = EXFAT_I(_inode);
+
+	call_rcu(&inode->vfs_inode.i_rcu, exfat_i_callback);
+}
+
+static void exfat_inode_init_once(void *ptr)
+{
+	struct exfat_inode_info *info = ptr;
+
+	INIT_HLIST_NODE(&info->hash_list);
+	exfat_inode_cache_init(&info->vfs_inode);
+	inode_init_once(&info->vfs_inode);
+}
+
+/*
+ * inode cache create/destroy.
+ */
+int exfat_init_inodes(void)
+{
+	exfat_inodes_cachep = kmem_cache_create("exfat-inodes",
+				       sizeof (struct exfat_inode_info), 0,
+				       SLAB_RECLAIM_ACCOUNT |SLAB_MEM_SPREAD,
+				       exfat_inode_init_once);
+	if (!exfat_inodes_cachep)
+		return -ENOMEM;
+	return 0;
+}
+
+void exfat_exit_inodes(void)
+{
+	kmem_cache_destroy(exfat_inodes_cachep);
+}
+
+int exfat_drop_inode(struct inode *inode)
+{
+	return generic_drop_inode(inode);
+}
+
+void exfat_evict_inode(struct inode *inode)
+{
+	if (inode->i_data.nrpages)
+		truncate_inode_pages(&inode->i_data, 0);
+	if (!inode->i_nlink) {
+		inode->i_size = 0;
+		exfat_free_clusters_inode(inode, 0);
+	}
+	invalidate_inode_buffers(inode);
+	clear_inode(inode);
+	exfat_remove_inode_hash(inode);
+	exfat_inode_cache_drop(inode);
+}
+
+static u32 exfat_hash(loff_t disk_pos)
+{
+	return hash_32(disk_pos, EXFAT_HASH_BITS);
+}
+
+struct inode *exfat_iget(struct super_block *sb, loff_t disk_pos)
+{
+	struct exfat_inode_info *info;
+	struct exfat_sb_info *sbi = EXFAT_SB(sb);
+	struct hlist_head *head = sbi->inode_hash + exfat_hash(disk_pos);
+	struct inode *ret = NULL;
+
+
+	spin_lock(&sbi->inode_hash_lock);
+	hlist_for_each_entry (info, head, hash_list) {
+		if (info->iloc.disk_offs[0] != disk_pos)
+			continue ;
+		ret = igrab(&info->vfs_inode);
+		if (ret)
+			break;
+	}
+	spin_unlock(&sbi->inode_hash_lock);
+	return ret;
+}
+
+void exfat_insert_inode_hash(struct inode *inode)
+{
+	struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb);
+	struct exfat_inode_info *info = EXFAT_I(inode);
+	struct hlist_head *head = sbi->inode_hash +
+		exfat_hash(info->iloc.disk_offs[0]);
+
+	spin_lock(&sbi->inode_hash_lock);
+	hlist_add_head(&info->hash_list, head);
+	spin_unlock(&sbi->inode_hash_lock);
+}
+
+void exfat_remove_inode_hash(struct inode *inode)
+{
+	struct exfat_inode_info *info = EXFAT_I(inode);
+	struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb);
+
+	spin_lock(&sbi->inode_hash_lock);
+	info->iloc.disk_offs[0] = 0;
+	hlist_del_init(&info->hash_list);
+	spin_unlock(&sbi->inode_hash_lock);
+}
+
+/*
+ * calculate the number of links in a directory. this is the number of
+ * EXFAT_FILEDIR_ENTRY typed elements in the directory stream. This
+ * does not include the '.' and '..' entries.
+ */
+loff_t exfat_dir_links(struct inode *inode)
+{
+	size_t ret = 0;
+	struct exfat_dir_ctx dctx;
+	int error;
+	bool end;
+
+	error = exfat_init_dir_ctx(inode, &dctx, 0);
+	if (error)
+		return error;
+
+	error = -EIO;
+	for (;;) {
+		struct exfat_filedir_entry *e =
+			__exfat_dentry_next(&dctx, E_EXFAT_FILEDIR, 0xff,
+					    true, &end);
+		if (!e) {
+			if (end)
+				error = 0;
+			goto out;
+		}
+		++ret;
+	}
+out:
+	exfat_cleanup_dir_ctx(&dctx);
+	if (error)
+		return error;
+	return ret;
+}
+
+int exfat_get_cluster_hint(struct inode *inode, u32 *out_hint)
+{
+	struct exfat_inode_info *info = EXFAT_I(inode);
+	int error;
+	u32 first_cluster = info->first_cluster;
+
+
+	if (!first_cluster) {
+		/*
+		 * empty file, return a cluster likely to be free.
+		 */
+		*out_hint = EXFAT_SB(inode->i_sb)->prev_free_cluster + 2;
+		return 0;
+	}
+
+	if (info->flags & EXFAT_I_FAT_INVALID) {
+		/*
+		 * not fat run, all clusters are contiguous, set hint
+		 * to next last file cluster.
+		 */
+		*out_hint = first_cluster + info->allocated_clusters;
+		return 0;
+	}
+
+	/*
+	 * fat run available, walk it to get the last physical cluster
+	 * address and set hint to the immediate next physical
+	 * cluster.
+	 */
+	error = exfat_get_fat_cluster(inode, info->allocated_clusters - 1,
+				      out_hint);
+	if (error)
+		return error;
+	(*out_hint)++;
+	return 0;
+}
+
+int __exfat_write_inode(struct inode *inode, bool sync)
+{
+	struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb);
+	struct exfat_inode_info *info = EXFAT_I(inode);
+	struct dir_entry_buffer entries[info->iloc.nr_secondary];
+	int error;
+	struct exfat_filedir_entry *efd;
+	struct exfat_stream_extension_entry *esx;
+	u16 checksum;
+
+	if (inode->i_ino == EXFAT_ROOT_INO)
+		return 0;
+
+	if (info->iloc.disk_offs[0] == 0) {
+		/*
+		 * write_inode() to unlinked inode: don't corrupt
+		 * superblock.
+		 */
+		return 0;
+	}
+
+	error = exfat_get_dir_entry_buffers(inode, &info->iloc,
+					    entries, info->iloc.nr_secondary);
+	if (error)
+		return error;
+
+	if (inode->i_mode & S_IWUGO)
+		info->attributes &= ~E_EXFAT_ATTR_RO;
+	else
+		info->attributes |= E_EXFAT_ATTR_RO;
+
+	efd = entries[0].start;
+	esx = entries[1].start;
+
+	efd->attributes = __cpu_to_le16(info->attributes);
+	esx->data_length = __cpu_to_le64(inode->i_size);
+	esx->valid_data_length = esx->data_length =
+		__cpu_to_le64(inode->i_size);
+	esx->flags = info->flags;
+	esx->first_cluster = __cpu_to_le32(info->first_cluster);
+
+	exfat_write_time(sbi, &inode->i_ctime, &efd->create, &efd->create_10ms,
+			 &efd->create_tz_offset);
+	exfat_write_time(sbi, &inode->i_mtime, &efd->modified,
+			 &efd->modified_10ms, &efd->modified_tz_offset);
+	exfat_write_time(sbi, &inode->i_atime, &efd->accessed, NULL,
+			 &efd->accessed_tz_offset);
+
+	checksum = exfat_dir_entries_checksum(entries, info->iloc.nr_secondary);
+	efd->set_checksum = __cpu_to_le16(checksum);
+
+	exfat_dirty_dir_entries(entries, info->iloc.nr_secondary, sync);
+
+
+	return 0;
+}
+
+int exfat_write_inode(struct inode *inode, struct writeback_control *wbc)
+{
+	int ret;
+
+	exfat_lock_super(inode->i_sb);
+	ret = __exfat_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL);
+	exfat_unlock_super(inode->i_sb);
+	return ret;
+}
diff -Nruw linux-4.2-fbx/fs/exfat./Kconfig linux-4.2-fbx/fs/exfat/Kconfig
--- linux-4.2-fbx/fs/exfat./Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/fs/exfat/Kconfig	2013-12-04 14:33:22.527479030 +0100
@@ -0,0 +1,3 @@
+
+config EXFAT_FS
+	tristate "exFAT fs support"
diff -Nruw linux-4.2-fbx/fs/exfat./Makefile linux-4.2-fbx/fs/exfat/Makefile
--- linux-4.2-fbx/fs/exfat./Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/fs/exfat/Makefile	2013-12-04 14:33:22.527479030 +0100
@@ -0,0 +1,13 @@
+
+obj-$(CONFIG_EXFAT_FS)	+= exfat.o
+
+exfat-y	= super.o				\
+	inode.o					\
+	fat.o					\
+	read-write.o				\
+	upcase.o				\
+	bitmap.o				\
+	time.o					\
+	dir.o					\
+	namei.o					\
+	file.o
diff -Nruw linux-4.2-fbx/fs/exfat./namei.c linux-4.2-fbx/fs/exfat/namei.c
--- linux-4.2-fbx/fs/exfat./namei.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/fs/exfat/namei.c	2014-05-09 14:12:54.236546158 +0200
@@ -0,0 +1,924 @@
+/*
+ * namei.c for exfat
+ * Created by <nschichan@freebox.fr> on Tue Aug 20 12:00:27 2013
+ */
+
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/buffer_head.h>
+#include <linux/nls.h>
+
+#include "exfat.h"
+#include "exfat_fs.h"
+
+static u16 exfat_filename_hash_cont(struct super_block *sb,
+				    const __le16 *name, u16 hash, size_t len);
+
+
+void exfat_write_time(struct exfat_sb_info *sbi, struct timespec *ts,
+		      __le32 *datetime, u8 *time_cs, u8 *tz_offset)
+{
+	u32 cpu_datetime;
+
+	exfat_time_2exfat(sbi, ts, &cpu_datetime, time_cs, tz_offset);
+	*datetime = __cpu_to_le32(cpu_datetime);
+}
+
+static void exfat_read_time(struct timespec *ts, __le32 datetime, u8 time_cs,
+			    u8 tz_offset)
+{
+	u32 cpu_datetime = __le32_to_cpu(datetime);
+	exfat_time_2unix(ts, cpu_datetime, time_cs, tz_offset);
+}
+
+static int exfat_zero_cluster(struct super_block *sb, u32 cluster, bool sync)
+{
+	sector_t start = exfat_cluster_sector(EXFAT_SB(sb), cluster);
+	sector_t end = start + EXFAT_SB(sb)->sectors_per_cluster;
+	sector_t sect;
+
+	for (sect = start; sect < end; ++sect) {
+		struct buffer_head *bh = sb_bread(sb, sect);
+		if (!bh) {
+			exfat_msg(sb, KERN_WARNING,
+				  "unable to read sector %llu for zeroing.",
+				  sect);
+			return -EIO;
+		}
+		memset(bh->b_data, 0, bh->b_size);
+		mark_buffer_dirty(bh);
+		if (sync)
+			sync_dirty_buffer(bh);
+		brelse(bh);
+	}
+	return 0;
+}
+
+/*
+ * use per superblock fmask or dmaks, depending on provided entry
+ * attribute to restrict the provided mode even more.
+ */
+mode_t exfat_make_mode(struct exfat_sb_info *sbi, mode_t mode, u16 attrs)
+{
+	if (attrs & E_EXFAT_ATTR_DIRECTORY)
+		mode = (mode & ~sbi->options.dmask) | S_IFDIR;
+	else
+		mode = (mode & ~sbi->options.fmask) | S_IFREG;
+	if (attrs & E_EXFAT_ATTR_RO)
+		mode &= ~S_IWUGO;
+	return mode;
+}
+
+/*
+ * populate inode fields.
+ */
+static struct inode *exfat_populate_inode(struct super_block *sb,
+			  const struct exfat_filedir_entry *efd,
+			  const struct exfat_stream_extension_entry *esx,
+			  const struct exfat_iloc *iloc)
+{
+	struct exfat_sb_info *sbi = EXFAT_SB(sb);
+	struct inode *inode;
+
+	inode = exfat_iget(sb, iloc->disk_offs[0]);
+	if (inode)
+		return inode;
+
+	inode = new_inode(sb);
+	if (!inode)
+		return NULL;
+
+	inode->i_ino = iunique(sb, EXFAT_ROOT_INO);
+	EXFAT_I(inode)->first_cluster = __le32_to_cpu(esx->first_cluster);
+	EXFAT_I(inode)->flags = esx->flags;
+	EXFAT_I(inode)->iloc = *iloc;
+	EXFAT_I(inode)->attributes = __le16_to_cpu(efd->attributes);
+
+	inode->i_size = __le64_to_cpu(esx->data_length);
+	EXFAT_I(inode)->allocated_clusters = inode->i_size >> sbi->clusterbits;
+	if (inode->i_size & sbi->clustermask)
+		EXFAT_I(inode)->allocated_clusters++;
+	inode->i_blocks = EXFAT_I(inode)->allocated_clusters <<
+		(sbi->clusterbits - 9);
+	EXFAT_I(inode)->mmu_private = inode->i_size;
+
+	inode->i_uid = sbi->options.uid;
+	inode->i_gid = sbi->options.gid;
+	inode->i_mode = exfat_make_mode(sbi, S_IRWXUGO,
+					EXFAT_I(inode)->attributes);
+
+	if (EXFAT_I(inode)->attributes & E_EXFAT_ATTR_DIRECTORY) {
+		loff_t nlinks = exfat_dir_links(inode);
+		if (nlinks < 0)
+			goto iput;
+		set_nlink(inode, nlinks + 2);
+	} else
+		set_nlink(inode, 1);
+
+	if (esx->data_length != esx->valid_data_length)
+		exfat_msg(sb, KERN_WARNING, "data length (%llu) != valid data "
+			  "length (%llu)", __le64_to_cpu(esx->data_length),
+			  __le64_to_cpu(esx->valid_data_length));
+
+	if (S_ISDIR(inode->i_mode)) {
+		inode->i_fop = &exfat_dir_operations;
+		inode->i_op = &exfat_dir_inode_operations;
+	} else {
+		/* until we support write */
+		inode->i_fop = &exfat_file_operations;
+		inode->i_op = &exfat_file_inode_operations;
+		inode->i_data.a_ops = &exfat_address_space_operations;
+	}
+
+
+	exfat_read_time(&inode->i_ctime, efd->create, efd->create_10ms,
+			efd->create_tz_offset);
+	exfat_read_time(&inode->i_mtime, efd->modified, efd->modified_10ms,
+			efd->modified_tz_offset);
+	exfat_read_time(&inode->i_atime, efd->accessed, 0,
+			efd->accessed_tz_offset);
+
+	exfat_insert_inode_hash(inode);
+	insert_inode_hash(inode);
+	return inode;
+iput:
+	iput(inode);
+	return NULL;
+}
+
+/*
+ * lookup an inode.
+ */
+struct dentry *exfat_inode_lookup(struct inode *parent, struct dentry *dentry,
+				  unsigned int flags)
+{
+	struct super_block *sb = dentry->d_sb;
+	struct exfat_dir_ctx dctx;
+	int error;
+	struct exfat_filedir_entry efd;
+	struct exfat_stream_extension_entry esx;
+	__le16 *name = __getname();
+	__le16 *utf16_name = __getname();
+	unsigned int utf16_name_length;
+	__le16 name_hash;
+
+	exfat_lock_super(parent->i_sb);
+
+	if (!name || !utf16_name) {
+		error = -ENOMEM;
+		goto putnames;
+	}
+
+	utf16_name_length = utf8s_to_utf16s(dentry->d_name.name,
+					    dentry->d_name.len,
+					    UTF16_LITTLE_ENDIAN,
+					    utf16_name, 255 + 2);
+	if (utf16_name_length > 255) {
+		error = -ENAMETOOLONG;
+		goto putnames;
+	}
+
+	/*
+	 * get the name hash of the wanted inode early so that we can
+	 * skip entries with only an efd and an esx entry.
+	 */
+	name_hash = __cpu_to_le16(exfat_filename_hash_cont(sb, utf16_name, 0,
+							   utf16_name_length));
+
+	/*
+	 * create a dir ctx from the parent so that we can iterate on
+	 * it.
+	 */
+	error = exfat_init_dir_ctx(parent, &dctx, 0);
+	if (error)
+		goto putnames;
+
+	for (;;) {
+		u32 name_length;
+		struct inode *inode;
+		u16 calc_checksum;
+		u16 expect_checksum;
+		struct exfat_iloc iloc;
+
+		memset(&iloc, 0, sizeof (iloc));
+		/*
+		 * get filedir and stream extension entries.
+		 */
+		error = exfat_dentry_next(&efd, &dctx, E_EXFAT_FILEDIR, true);
+		if (error < 0)
+			/* end of directory reached, or other error */
+			goto cleanup;
+
+		error = -EINVAL;
+		if (efd.secondary_count > 18)
+			goto cleanup;
+
+		iloc.file_off = exfat_dctx_fpos(&dctx);
+		iloc.disk_offs[0] = exfat_dctx_dpos(&dctx);
+		iloc.nr_secondary = efd.secondary_count + 1;
+
+		error = exfat_dentry_next(&esx, &dctx, E_EXFAT_STREAM_EXT,
+					  false);
+		if (error)
+			goto cleanup;
+
+		if (esx.name_hash != name_hash)
+			/*
+			 * stored name hash is not the same as the
+			 * wanted hash: no point in processing the
+			 * remaining entries for the current efd/esx
+			 * any further.
+			 */
+			continue ;
+
+		/*
+		 * now that the hash matches it is ok to update the
+		 * checksum for the efd and esx entries.
+		 */
+		expect_checksum = __le16_to_cpu(efd.set_checksum);
+		calc_checksum = exfat_direntry_checksum(&efd, 0, true);
+
+		calc_checksum = exfat_direntry_checksum(&esx,
+							calc_checksum, false);
+		iloc.disk_offs[1] = exfat_dctx_dpos(&dctx);
+
+		/*
+		 * fetch name.
+		 */
+		name_length = esx.name_length;
+		error = __exfat_get_name(&dctx, name_length, name,
+					 &calc_checksum, &iloc);
+		if (error)
+			goto cleanup;
+
+		if (calc_checksum != expect_checksum) {
+			exfat_msg(dctx.sb, KERN_INFO, "checksum: "
+				  "calculated %04x, expect %04x",
+				  calc_checksum, expect_checksum);
+			error = -EIO;
+			goto cleanup;
+		}
+
+
+		if (utf16_name_length != name_length)
+			continue ;
+
+		if (memcmp(utf16_name, name, name_length * sizeof (__le16)))
+			continue ;
+
+		inode = exfat_populate_inode(sb, &efd, &esx, &iloc);
+		if (inode) {
+			d_add(dentry, inode);
+			error = 0;
+		} else
+			error = -EIO;
+		goto cleanup;
+	}
+
+cleanup:
+	exfat_cleanup_dir_ctx(&dctx);
+putnames:
+	if (name)
+		__putname(name);
+	if (utf16_name)
+		__putname(utf16_name);
+	exfat_unlock_super(parent->i_sb);
+	if (error && error != -ENOENT)
+		return ERR_PTR(error);
+	return NULL;
+}
+
+/*
+ * find nr unused directory entries (type & 0x80 == 0).
+ */
+static int exfat_find_dir_iloc(struct inode *inode, int nr,
+			       struct exfat_iloc *iloc)
+{
+	struct exfat_dir_ctx dctx;
+	bool end = false;
+	int error;
+	struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb);
+	u32 nr_new_clusters, i;
+	u32 new_clusters[2];
+	u32 hint_cluster;
+
+retry:
+	memset(iloc, 0, sizeof (*iloc));
+	iloc->nr_secondary = nr;
+
+	error = exfat_init_dir_ctx(inode, &dctx, 0);
+	if (error)
+		return error;
+
+	while (1) {
+		int nr_free;
+		void *ent;
+
+		ent = __exfat_dentry_next(&dctx, 0x00, 0x80, true, &end);
+		if (end)
+			break;
+		if (!ent) {
+			exfat_cleanup_dir_ctx(&dctx);
+			return -EIO;
+		}
+
+		nr_free = 1;
+		iloc->file_off = exfat_dctx_fpos(&dctx);
+		iloc->disk_offs[0] = exfat_dctx_dpos(&dctx);
+		while (__exfat_dentry_next(&dctx, 0x00, 0x80, false, &end)
+		       != NULL && nr_free < nr) {
+			iloc->disk_offs[nr_free] = exfat_dctx_dpos(&dctx);
+			++nr_free;
+		}
+		if (nr_free == nr) {
+			/*
+			 * we found enough consecutive free entries.
+			 */
+			exfat_cleanup_dir_ctx(&dctx);
+			return 0;
+		}
+
+	}
+
+	/*
+	 * not enough consecutive free entries found, kick the cluster
+	 * allocator and retry.
+	 */
+	exfat_cleanup_dir_ctx(&dctx);
+
+	/*
+	 * with the smallest cluster size, a file can take more than
+	 * two clusters. allocate two in that case reardless of what
+	 * is needed to make code simplier.
+	 */
+	switch (sbi->clustersize) {
+	case 512:
+		nr_new_clusters = 2;
+		break;
+	default:
+		nr_new_clusters = 1;
+		break;
+	}
+
+	/*
+	 * get a hint cluster for the cluster allocator.
+	 */
+	error = exfat_get_cluster_hint(inode, &hint_cluster);
+	if (error)
+		return error;
+
+	/*
+	 * peform the allocation.
+	 */
+	error = exfat_alloc_clusters(inode, hint_cluster, new_clusters,
+				     nr_new_clusters);
+	if (error)
+		return error;
+
+	/*
+	 * fill new cluster(s) with zero.
+	 */
+	for (i = 0; i < nr_new_clusters; ++i)
+		exfat_zero_cluster(inode->i_sb, new_clusters[i], false);
+
+	/*
+	 * update size and mark inode as dirty so that write_inode()
+	 * can update it's size, and the other fields updated by
+	 * exfat_alloc_clusters.
+	 */
+	inode->i_size += nr_new_clusters << sbi->clusterbits;
+	mark_inode_dirty(inode);
+
+	/*
+	 * kick the whole place search again, this time with the newly
+	 * allocated clusters.
+	 */
+	goto retry;
+}
+
+/*
+ * setup dir_entry_buffers starting at using iloc.
+ */
+int exfat_get_dir_entry_buffers(struct inode *dir, struct exfat_iloc *iloc,
+				struct dir_entry_buffer *entries,
+				size_t nr_entries)
+{
+	size_t i;
+	int error;
+	struct exfat_sb_info *sbi = EXFAT_SB(dir->i_sb);
+
+	BUG_ON(iloc->nr_secondary != nr_entries);
+
+	memset(entries, 0, sizeof (*entries) * nr_entries);
+	for (i = 0; i < nr_entries; ++i) {
+		sector_t sector = iloc->disk_offs[i] >> sbi->sectorbits;
+
+		entries[i].off = iloc->disk_offs[i] & sbi->sectormask;
+		entries[i].bh = sb_bread(dir->i_sb, sector);
+		if (!entries[i].bh) {
+			error = -EIO;
+			goto fail;
+		}
+		entries[i].start = entries[i].bh->b_data + entries[i].off;
+	}
+	return 0;
+
+fail:
+	for (i = 0; i < nr_entries; ++i)
+		if (entries[i].bh)
+			brelse(entries[i].bh);
+	return error;
+}
+
+static u16 exfat_filename_hash_cont(struct super_block *sb,
+				    const __le16 *name, u16 hash, size_t len)
+{
+	while (len) {
+		u16 c = __le16_to_cpu(exfat_upcase_convert(sb, *name));
+
+		hash = ((hash << 15) | (hash >> 1)) + (c & 0xff);
+		hash = ((hash << 15) | (hash >> 1)) + (c >> 8);
+		--len;
+		++name;
+	}
+	return hash;
+}
+
+u16 exfat_dir_entries_checksum(struct dir_entry_buffer *entries, u32 nr)
+{
+	u32 checksum = 0;
+
+	if (nr) {
+		checksum = exfat_direntry_checksum(entries->start,
+						   checksum, true);
+		--nr;
+		++entries;
+	}
+	while (nr) {
+		checksum = exfat_direntry_checksum(entries->start,
+						   checksum, false);
+		--nr;
+		++entries;
+	}
+	return checksum;
+}
+
+/*
+ * setup exfat_filedir_entry and exfat_stream_extension_entry for a
+ * new entry, with attribute attrs, and named name.
+ */
+static void exfat_fill_dir_entries(struct super_block *sb,
+				  struct dir_entry_buffer *entries,
+				  size_t nr_entries, u8 attrs,
+				  __le16 *name, int name_length)
+{
+	struct exfat_filedir_entry *efd;
+	struct exfat_stream_extension_entry *esx;
+	int i;
+	u16 name_hash;
+	u16 checksum;
+	struct timespec ts = CURRENT_TIME_SEC;
+
+	efd = entries[0].start;
+	esx = entries[1].start;
+
+	/*
+	 * fill exfat filedir entry
+	 */
+	memset(efd, 0, sizeof (*efd));
+	efd->type = E_EXFAT_FILEDIR;
+	efd->secondary_count = nr_entries - 1;
+	efd->set_checksum = 0;
+	efd->attributes = __cpu_to_le16(attrs);
+
+	/*
+	 * update file directory entry times
+	 */
+	efd = entries[0].start;
+	exfat_write_time(EXFAT_SB(sb), &ts, &efd->create, &efd->create_10ms,
+			 &efd->create_tz_offset);
+	efd->modified = efd->accessed = efd->create;
+	efd->modified_10ms = efd->create_10ms;
+	efd->accessed_tz_offset = efd->modified_tz_offset =
+		efd->create_tz_offset;
+
+	/*
+	 * fill exfat stream extension entry
+	 */
+	memset(esx, 0, sizeof (*esx));
+	esx->type = E_EXFAT_STREAM_EXT;
+	esx->flags = EXFAT_I_ALLOC_POSSIBLE;
+	esx->first_cluster = __cpu_to_le32(0);
+	esx->data_length = __cpu_to_le64(0);
+	esx->valid_data_length = __cpu_to_le64(0);
+	esx->name_length = name_length;
+
+	/*
+	 * fill name fragments.
+	 */
+	name_hash = 0;
+	for (i = 0; i < nr_entries - 2; ++i, name_length -= 15) {
+		struct exfat_filename_entry *efn = entries[i + 2].start;
+		int len = 15;
+
+		if (name_length < 15)
+			len = name_length;
+
+		memset(efn, 0, sizeof (*efn));
+		efn->type = E_EXFAT_FILENAME;
+		memcpy(efn->name_frag, name + i * 15, len * sizeof (__le16));
+		name_hash = exfat_filename_hash_cont(sb, efn->name_frag,
+						     name_hash, len);
+	}
+	esx->name_hash = __cpu_to_le16(name_hash);
+
+	checksum = exfat_dir_entries_checksum(entries, nr_entries);
+	efd->set_checksum = __cpu_to_le16(checksum);
+}
+
+/*
+ * mark all buffer heads in the entries array as dirty. optionally
+ * sync them if required.
+ */
+void exfat_dirty_dir_entries(struct dir_entry_buffer *entries,
+			     size_t nr_entries, bool sync)
+{
+	size_t i;
+
+	for (i = 0; i < nr_entries; ++i) {
+		mark_buffer_dirty(entries[i].bh);
+		if (sync)
+			sync_dirty_buffer(entries[i].bh);
+		brelse(entries[i].bh);
+	}
+}
+
+/*
+ * cleanup all buffer heads in entries.
+ */
+static void exfat_cleanup_dir_entries(struct dir_entry_buffer *entries,
+				     size_t nr_entries)
+{
+	size_t i;
+
+	for (i = 0; i < nr_entries; ++i)
+		brelse(entries[i].bh);
+}
+
+/*
+ * create an inode
+ */
+static int __exfat_inode_create(struct inode *dir, struct dentry *dentry,
+				umode_t mode, bool is_dir)
+{
+	int nr_entries;
+	struct dir_entry_buffer entries[19];
+	struct inode *new;
+	struct exfat_iloc iloc;
+	int error;
+	u8 attr = 0;
+	__le16 *utf16_name;
+	int utf16_name_length;
+
+	if (is_dir)
+		attr |= E_EXFAT_ATTR_DIRECTORY;
+
+	exfat_lock_super(dir->i_sb);
+
+	utf16_name = __getname();
+	if (!utf16_name) {
+		error = -ENOMEM;
+		goto unlock_super;
+	}
+
+	utf16_name_length = utf8s_to_utf16s(dentry->d_name.name,
+					    dentry->d_name.len,
+					    UTF16_LITTLE_ENDIAN, utf16_name,
+					    255 + 2);
+	if (utf16_name_length < 0) {
+		error = utf16_name_length;
+		goto putname;
+	}
+	if (utf16_name_length > 255) {
+		error = -ENAMETOOLONG;
+		goto putname;
+	}
+
+
+	nr_entries = 2 + DIV_ROUND_UP(utf16_name_length, 15);
+	if (nr_entries > 19) {
+		error = -ENAMETOOLONG;
+		goto putname;
+	}
+
+	error = exfat_find_dir_iloc(dir, nr_entries, &iloc);
+	if (error < 0)
+		goto putname;
+
+	error = exfat_get_dir_entry_buffers(dir, &iloc, entries, nr_entries);
+	if (error)
+		goto putname;
+	exfat_fill_dir_entries(dir->i_sb, entries, nr_entries, attr,
+				       utf16_name, utf16_name_length);
+
+	/*
+	 * create an inode with it.
+	 */
+	error = -ENOMEM;
+	new = exfat_populate_inode(dir->i_sb, entries[0].start,
+				   entries[1].start, &iloc);
+	if (!new)
+		goto cleanup;
+	inc_nlink(dir);
+	d_instantiate(dentry, new);
+
+	/*
+	 * update directory atime / ctime.
+	 */
+	dir->i_atime = dir->i_mtime = CURRENT_TIME_SEC;
+	if (IS_DIRSYNC(dir))
+		__exfat_write_inode(dir, true);
+	else
+		mark_inode_dirty(dir);
+
+	/*
+	 * write to disk
+	 */
+	exfat_dirty_dir_entries(entries, nr_entries, false);
+	__putname(utf16_name);
+	exfat_unlock_super(dir->i_sb);
+	return 0;
+
+cleanup:
+	exfat_cleanup_dir_entries(entries, nr_entries);
+putname:
+	__putname(utf16_name);
+unlock_super:
+	exfat_unlock_super(dir->i_sb);
+	return error;
+}
+
+int exfat_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+		       bool excl)
+{
+	return __exfat_inode_create(dir, dentry, mode, false);
+}
+
+int exfat_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+{
+	return __exfat_inode_create(dir, dentry, mode, true);
+}
+
+/*
+ * inode unlink: find all direntry buffers and clear seventh bit of
+ * the entry type to mark the as unused.
+ */
+static int __exfat_inode_unlink(struct inode *dir, struct dentry *dentry)
+{
+	struct inode *inode = dentry->d_inode;
+	struct exfat_inode_info *info = EXFAT_I(inode);
+	struct dir_entry_buffer entries[info->iloc.nr_secondary];
+	int error;
+	u32 i;
+
+	error = exfat_get_dir_entry_buffers(inode, &info->iloc,
+					    entries, info->iloc.nr_secondary);
+	if (error)
+		return error;
+
+	for (i = 0; i < info->iloc.nr_secondary; ++i) {
+		u8 *type = entries[i].start;
+
+		*type &= 0x7f;
+	}
+
+	drop_nlink(dir);
+	clear_nlink(inode);
+	inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC;
+
+	/*
+	 * update atime & mtime for parent directory.
+	 */
+	dir->i_mtime = dir->i_atime = CURRENT_TIME_SEC;
+	if (IS_DIRSYNC(dir))
+		__exfat_write_inode(dir, true);
+	else
+		mark_inode_dirty(dir);
+
+	exfat_dirty_dir_entries(entries, info->iloc.nr_secondary, false);
+	exfat_remove_inode_hash(inode);
+	return 0;
+}
+
+int exfat_inode_unlink(struct inode *dir, struct dentry *dentry)
+{
+	int ret;
+
+	exfat_lock_super(dir->i_sb);
+	ret = __exfat_inode_unlink(dir, dentry);
+	exfat_unlock_super(dir->i_sb);
+	return ret;
+}
+
+/*
+ * inode rmdir: check that links is not greater than 2 (meaning that
+ * the directory is empty) and invoke unlink.
+ */
+static int __exfat_inode_rmdir(struct inode *dir, struct dentry *dentry)
+{
+	struct inode *inode = dentry->d_inode;
+
+	if (inode->i_nlink > 2)
+		return -ENOTEMPTY;
+
+	return __exfat_inode_unlink(dir, dentry);
+}
+
+int exfat_inode_rmdir(struct inode *dir, struct dentry *dentry)
+{
+	int ret;
+
+	exfat_lock_super(dir->i_sb);
+	ret = __exfat_inode_rmdir(dir, dentry);
+	exfat_unlock_super(dir->i_sb);
+	return ret;
+}
+
+int exfat_rename(struct inode *old_dir, struct dentry *old_dentry,
+		 struct inode *new_dir, struct dentry *new_dentry)
+{
+	struct inode *old_inode = old_dentry->d_inode;
+	struct inode *new_inode = new_dentry->d_inode;
+	int new_nr_entries;
+	int error = 0;
+	struct exfat_iloc new_iloc;
+	struct exfat_inode_info *old_info = EXFAT_I(old_inode);
+	struct dir_entry_buffer old_buffers[old_info->iloc.nr_secondary];
+	struct dir_entry_buffer new_buffers[19];
+	struct exfat_filedir_entry *efd;
+	struct exfat_stream_extension_entry *esx;
+	int name_length;
+	__le16 *name;
+	u16 name_hash;
+	int i;
+
+	exfat_lock_super(new_dir->i_sb);
+
+	/*
+	 * convert new name to utf16
+	 */
+	name = __getname();
+	if (!name) {
+		error = -ENOMEM;
+		goto unlock_super;
+	}
+	name_length = utf8s_to_utf16s(new_dentry->d_name.name,
+				      new_dentry->d_name.len,
+				      UTF16_LITTLE_ENDIAN, name, 255 + 2);
+
+	if (name_length > 255) {
+		error = -ENAMETOOLONG;
+		goto err_putname;
+	}
+	if (name_length < 0) {
+		error = name_length;
+		goto err_putname;
+	}
+
+	new_nr_entries = 2 + DIV_ROUND_UP(name_length, 15);
+
+	/*
+	 * find space for new entry
+	 */
+	error = exfat_find_dir_iloc(new_dir, new_nr_entries, &new_iloc);
+	if (error < 0)
+		goto err_putname;
+
+	/*
+	 * get buffers for old and new entries.
+	 */
+	error = exfat_get_dir_entry_buffers(old_dir, &old_info->iloc,
+				    old_buffers, old_info->iloc.nr_secondary);
+	if (error < 0)
+		goto err_putname;
+
+	error = exfat_get_dir_entry_buffers(new_dir, &new_iloc, new_buffers,
+					    new_nr_entries);
+	if (error < 0)
+		goto err_cleanup_old_buffers;
+
+
+	/*
+	 * remove new inode, if it exists.
+	 */
+	if (new_inode) {
+		if (S_ISDIR(new_inode->i_mode))
+			error = __exfat_inode_rmdir(new_dir, new_dentry);
+		else
+			error = __exfat_inode_unlink(new_dir, new_dentry);
+		if (error < 0)
+			goto err_cleanup_new_buffers;
+	}
+
+	/*
+	 * move old esd to new esd (and ditto for esx).
+	 */
+	efd = new_buffers[0].start;
+	esx = new_buffers[1].start;
+	memcpy(efd, old_buffers[0].start, sizeof (*efd));
+	memcpy(esx, old_buffers[1].start, sizeof (*esx));
+
+	efd->secondary_count = new_nr_entries - 1;
+
+	/*
+	 * patch new name after that.
+	 */
+	esx->name_length = __cpu_to_le16(name_length);
+
+	/*
+	 * fill name fragments.
+	 */
+	name_hash = 0;
+	for (i = 0; i < new_nr_entries - 2; ++i, name_length -= 15) {
+		struct exfat_filename_entry *efn = new_buffers[i + 2].start;
+		int len = 15;
+
+		if (name_length < 15)
+			len = name_length;
+
+		memset(efn, 0, sizeof (*efn));
+		efn->type = E_EXFAT_FILENAME;
+		memcpy(efn->name_frag, name + i * 15, len * sizeof (__le16));
+		name_hash = exfat_filename_hash_cont(new_dir->i_sb,
+						     efn->name_frag,
+						     name_hash, len);
+	}
+	__putname(name);
+	esx->name_hash = __cpu_to_le16(name_hash);
+	efd->set_checksum = exfat_dir_entries_checksum(new_buffers,
+						       new_nr_entries);
+	efd->set_checksum = __cpu_to_le16(efd->set_checksum);
+
+	/*
+	 * mark old buffer entries as unused.
+	 */
+	for (i = 0; i < old_info->iloc.nr_secondary; ++i)
+		*((u8*)old_buffers[i].start) &= 0x7f;
+
+	/*
+	 * dirty old & new entries buffers.
+	 */
+	exfat_dirty_dir_entries(new_buffers, new_nr_entries, false);
+	exfat_dirty_dir_entries(old_buffers, old_info->iloc.nr_secondary,
+				false);
+
+	/*
+	 * update links if new_dir and old_dir are differents.
+	 */
+	if (new_dir != old_dir) {
+		drop_nlink(old_dir);
+		inc_nlink(new_dir);
+	}
+
+	/*
+	 * make old inode use the new iloc, and update sb inode hash.
+	 */
+	exfat_remove_inode_hash(old_inode);
+	old_info->iloc = new_iloc;
+	exfat_insert_inode_hash(old_inode);
+
+	/*
+	 * update new dir & old dir mtime/atime
+	 */
+	if (new_dir == old_dir) {
+		new_dir->i_mtime = new_dir->i_atime = CURRENT_TIME_SEC;
+		if (IS_DIRSYNC(new_dir))
+			__exfat_write_inode(new_dir, true);
+		else
+			mark_inode_dirty(new_dir);
+	} else {
+		new_dir->i_mtime = new_dir->i_atime =
+			old_dir->i_mtime = old_dir->i_atime = CURRENT_TIME_SEC;
+		if (IS_DIRSYNC(new_dir)) {
+			__exfat_write_inode(new_dir, true);
+			__exfat_write_inode(old_dir, true);
+		} else {
+			mark_inode_dirty(new_dir);
+			mark_inode_dirty(old_dir);
+		}
+	}
+
+	exfat_unlock_super(new_dir->i_sb);
+	return 0;
+
+err_cleanup_new_buffers:
+	exfat_cleanup_dir_entries(new_buffers, new_nr_entries);
+err_cleanup_old_buffers:
+	exfat_cleanup_dir_entries(old_buffers, old_info->iloc.nr_secondary);
+err_putname:
+	__putname(name);
+unlock_super:
+	exfat_unlock_super(new_dir->i_sb);
+	return error;
+}
diff -Nruw linux-4.2-fbx/fs/exfat./read-write.c linux-4.2-fbx/fs/exfat/read-write.c
--- linux-4.2-fbx/fs/exfat./read-write.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/fs/exfat/read-write.c	2015-09-15 19:18:39.538464718 +0200
@@ -0,0 +1,150 @@
+/*
+ * read-write.c for exfat
+ * Created by <nschichan@freebox.fr> on Wed Jul 31 16:37:51 2013
+ */
+
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/mpage.h>
+#include <linux/buffer_head.h>
+
+#include "exfat.h"
+#include "exfat_fs.h"
+
+/*
+ * map file sector to disk sector.
+ */
+static int exfat_bmap(struct inode *inode, sector_t fsect, sector_t *dsect)
+{
+	struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb);
+	struct exfat_inode_info *info = EXFAT_I(inode);
+	u32 cluster_nr = fsect >> (sbi->clusterbits - sbi->sectorbits);
+	u32 cluster;
+	unsigned int offset = fsect & (sbi->sectors_per_cluster - 1);
+
+	if (info->flags & EXFAT_I_FAT_INVALID)
+		cluster = info->first_cluster + cluster_nr;
+	else {
+		int error;
+
+		error = exfat_get_fat_cluster(inode, cluster_nr, &cluster);
+		if (error)
+			return error;
+	}
+
+	*dsect = exfat_cluster_sector(sbi, cluster) + offset;
+	return 0;
+}
+
+static int exfat_get_block(struct inode *inode, sector_t block,
+			   struct buffer_head *bh, int create)
+{
+	struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb);
+	struct exfat_inode_info *info = EXFAT_I(inode);
+	sector_t last_block;
+	unsigned int offset;
+	sector_t dblock;
+	int error;
+
+	last_block = (i_size_read(inode) + sbi->sectorsize - 1) >>
+		sbi->sectorbits;
+	offset = block & (sbi->sectors_per_cluster - 1);
+
+	if (!create && block >= last_block)
+		return 0;
+
+	if (create && block >= last_block && offset == 0) {
+		u32 hint, cluster;
+
+		/*
+		 * request for first sector in a cluster immediate to
+		 * the last allocated cluster of the file: must
+		 * allocate a new clluster.
+		 */
+		error = exfat_get_cluster_hint(inode, &hint);
+		if (error)
+			return error;
+
+		error = exfat_alloc_clusters(inode, hint, &cluster, 1);
+		if (error)
+			return error;
+	}
+
+	error = exfat_bmap(inode, block, &dblock);
+	if (error)
+		return error;
+
+	if (create && block >= last_block) {
+		/*
+		 * currently in create mode: we need to update
+		 * mmu_private.
+		 */
+		info->mmu_private += sbi->sectorsize;
+		set_buffer_new(bh);
+	}
+	map_bh(bh, inode->i_sb, dblock);
+	return 0;
+}
+
+int exfat_readpage(struct file *file, struct page *page)
+{
+	return mpage_readpage(page, exfat_get_block);
+}
+
+int exfat_readpages(struct file *file, struct address_space *mapping,
+		    struct list_head *pages, unsigned nr_pages)
+{
+	return mpage_readpages(mapping, pages, nr_pages, exfat_get_block);
+}
+
+static int exfat_write_error(struct inode *inode, loff_t to)
+{
+	if (to > inode->i_size) {
+		truncate_pagecache(inode, to);
+		exfat_truncate_blocks(inode, inode->i_size);
+	}
+	return 0;
+}
+
+int exfat_write_begin(struct file *file, struct address_space *mapping,
+		      loff_t pos, unsigned len, unsigned flags,
+		      struct page **pagep, void **fsdata)
+{
+	struct inode *inode = mapping->host;
+	int error;
+
+	*pagep = NULL;
+	error = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
+				 exfat_get_block, &EXFAT_I(inode)->mmu_private);
+
+	if (error)
+		exfat_write_error(inode, pos + len);
+	return error;
+}
+
+int exfat_write_end(struct file *file, struct address_space *mapping,
+		    loff_t pos, unsigned len, unsigned copied,
+		    struct page *page, void *fsdata)
+{
+	struct inode *inode = mapping->host;
+	int error;
+
+	error = generic_write_end(file, mapping, pos, len, copied, page,
+				  fsdata);
+
+	if (error < len)
+		exfat_write_error(inode, pos + len);
+	return error;
+}
+
+int exfat_writepage(struct page *page, struct writeback_control *wbc)
+{
+	return block_write_full_page(page, exfat_get_block, wbc);
+}
+
+int exfat_writepages(struct address_space *mapping,
+		     struct writeback_control *wbc)
+{
+	return mpage_writepages(mapping, wbc, exfat_get_block);
+}
diff -Nruw linux-4.2-fbx/fs/exfat./super.c linux-4.2-fbx/fs/exfat/super.c
--- linux-4.2-fbx/fs/exfat./super.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/fs/exfat/super.c	2015-09-15 19:18:39.538464718 +0200
@@ -0,0 +1,735 @@
+/*
+ * super.c<2> for exfat
+ * Created by <nschichan@freebox.fr> on Tue Jul 23 12:33:53 2013
+ */
+
+#include <linux/kernel.h>
+#include <linux/bug.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/buffer_head.h>
+#include <linux/statfs.h>
+#include <linux/parser.h>
+#include <linux/seq_file.h>
+#include <linux/sched.h>
+#include <linux/cred.h>
+
+#include "exfat_fs.h"
+#include "exfat.h"
+
+
+#define PFX	"exFAT: "
+
+static void exfat_put_super(struct super_block *sb);
+static int exfat_statfs(struct dentry *dentry, struct kstatfs *kstat);
+static int exfat_show_options(struct seq_file *m, struct dentry *root);
+static int exfat_remount(struct super_block *sb, int *flags, char *opts);
+
+static const struct super_operations exfat_super_ops = {
+	.alloc_inode	= exfat_alloc_inode,
+	.destroy_inode	= exfat_destroy_inode,
+	.drop_inode	= exfat_drop_inode,
+	.evict_inode	= exfat_evict_inode,
+	.write_inode	= exfat_write_inode,
+	.statfs         = exfat_statfs,
+	.put_super      = exfat_put_super,
+	.show_options	= exfat_show_options,
+	.remount_fs	= exfat_remount,
+};
+
+const struct file_operations exfat_dir_operations = {
+	.llseek = generic_file_llseek,
+	.read = generic_read_dir,
+	.iterate = exfat_iterate,
+	.unlocked_ioctl	= exfat_ioctl,
+};
+
+const struct file_operations exfat_file_operations = {
+	.llseek		= generic_file_llseek,
+	.read_iter	= generic_file_read_iter,
+	.write_iter	= generic_file_write_iter,
+	.mmap		= generic_file_mmap,
+	.splice_read	= generic_file_splice_read,
+	.unlocked_ioctl	= exfat_ioctl,
+	.fsync		= generic_file_fsync,
+};
+
+const struct inode_operations exfat_dir_inode_operations =
+{
+	.create = exfat_inode_create,
+	.mkdir	= exfat_inode_mkdir,
+	.lookup = exfat_inode_lookup,
+	.rmdir	= exfat_inode_rmdir,
+	.unlink	= exfat_inode_unlink,
+	.rename	= exfat_rename,
+	.setattr = exfat_setattr,
+	.getattr = exfat_getattr,
+};
+
+const struct inode_operations exfat_file_inode_operations = {
+	.setattr = exfat_setattr,
+	.getattr = exfat_getattr,
+};
+
+const struct address_space_operations exfat_address_space_operations = {
+	.readpage	= exfat_readpage,
+	.readpages	= exfat_readpages,
+	.write_begin	= exfat_write_begin,
+	.write_end	= exfat_write_end,
+	.writepage	= exfat_writepage,
+	.writepages	= exfat_writepages,
+};
+
+void exfat_msg(struct super_block *sb, const char *prefix,
+		const char *fmt, ...)
+{
+	struct va_format vaf;
+	va_list args;
+
+	va_start(args, fmt);
+	vaf.fmt = fmt;
+	vaf.va = &args;
+	printk("%sexFAT-fs (%s): %pV\n", prefix, sb->s_id, &vaf);
+	va_end(args);
+}
+
+void exfat_fs_error(struct super_block *sb, const char *fmt, ...)
+{
+	struct exfat_sb_info *sbi = EXFAT_SB(sb);
+	struct va_format vaf;
+	va_list args;
+
+	va_start(args, fmt);
+	vaf.fmt = fmt;
+	vaf.va = &args;
+	exfat_msg(sb, KERN_ERR, "error: %pV", &vaf);
+	va_end(args);
+
+	if (sbi->options.error_action == EXFAT_ERROR_ACTION_REMOUNT_RO &&
+	    !(sb->s_flags & MS_RDONLY)) {
+		sb->s_flags |= MS_RDONLY;
+		exfat_msg(sb, KERN_ERR, "remounted read-only due to fs error.");
+	} else if (sbi->options.error_action == EXFAT_ERROR_ACTION_PANIC)
+		panic("exFAT-fs (%s): panic due fs error.\n", sb->s_id);
+}
+
+/*
+ * process checksum on buffer head. first indicates if the special
+ * treatment of the first sector needs to be done or not.
+ *
+ * first sector can be changed (volume flags, and heap use percent),
+ * those fields are excluded from the checksum to allow updating
+ * without recalculating the checksum.
+ */
+static u32 exfat_sb_checksum_process(struct buffer_head *bh, u32 checksum,
+				     unsigned int size,
+				     bool first)
+{
+	unsigned int i;
+
+	for (i = 0; i < size; ++i) {
+		if (first && (i == 106 || i == 107 || i == 112))
+			continue ;
+		checksum = ((checksum << 31) | (checksum >> 1)) +
+			(unsigned char)bh->b_data[i];
+	}
+	return checksum;
+}
+
+static int exfat_check_sb_checksum(struct super_block *sb)
+{
+	struct exfat_sb_info *sbi = EXFAT_SB(sb);
+	u32 checksum;
+	int i;
+	int err;
+	struct buffer_head *bh[EXFAT_CHECKSUM_SECTORS + 1];
+
+	/*
+	 * fetch needed sectors, reuse first sector from sbi.
+	 */
+	err = -ENOMEM;
+	memset(bh, 0, sizeof (struct buffer_head*) *
+	       (EXFAT_CHECKSUM_SECTORS + 1));
+	bh[0] = sbi->sb_bh;
+	for (i = 1; i < EXFAT_CHECKSUM_SECTORS + 1; ++i) {
+		bh[i] = sb_bread(sb, i);
+		if (!bh[i])
+			goto out;
+	}
+
+	/*
+	 * calculate checksum.
+	 */
+	checksum = exfat_sb_checksum_process(bh[0], 0, sbi->sectorsize, true);
+	for (i = 1; i < EXFAT_CHECKSUM_SECTORS; ++i) {
+		checksum = exfat_sb_checksum_process(bh[i], checksum,
+						     sbi->sectorsize, false);
+	}
+
+	/*
+	 * compare with the checksum sector.
+	 */
+	err = -EINVAL;
+	for (i = 0; i < sbi->sectorsize; i += sizeof (u32)) {
+		__le32 val = *(u32*)(bh[EXFAT_CHECKSUM_SECTORS]->b_data + i);
+
+		if (__le32_to_cpu(val) != checksum) {
+			exfat_msg(sb, KERN_INFO, "at offset %i, checksum "
+				  "%08x != %08x", i, __le32_to_cpu(val), checksum);
+			goto out;
+		}
+	}
+	err = 0;
+
+out:
+	for (i = 1; i < EXFAT_CHECKSUM_SECTORS; ++i)
+		if (bh[i])
+			brelse(bh[i]);
+	return err;
+}
+
+static int exfat_check_sb(struct super_block *sb)
+{
+	struct exfat_sb_info *sbi = EXFAT_SB(sb);
+	struct exfat_vbr *vbr = sbi->vbr;
+	u16 fs_rev;
+	u16 flags;
+	int active_fat;
+	u16 num_fats;
+
+	if (memcmp(vbr->jump, "\xeb\x76\x90", sizeof (vbr->jump))) {
+		exfat_msg(sb, KERN_INFO, "invalid jump field in vbr.");
+		return -EINVAL;
+	}
+
+	if (memcmp(vbr->fsname, "EXFAT   ", 8)) {
+		exfat_msg(sb, KERN_INFO, "invalid fsname field in vbr: %s.",
+			  vbr->fsname);
+		return -EINVAL;
+	}
+
+	fs_rev = __le16_to_cpu(vbr->fs_rev);
+	if (fs_rev != 0x0100) {
+		exfat_msg(sb, KERN_INFO, "filesystem version invalid: "
+			  "have 0x%04x, need 0x0100", fs_rev);
+		return -EINVAL;
+	}
+
+	flags = __le16_to_cpu(vbr->volume_flags);
+	active_fat = exfat_active_fat(flags);
+	if (active_fat != 0) {
+		exfat_msg(sb, KERN_INFO, "filesystems with active fat > 0 are "
+			  "not supported.");
+		return -EINVAL;
+	}
+
+	if (flags & EXFAT_FLAG_MEDIA_FAILURE)
+		exfat_msg(sb, KERN_WARNING, "filesystem had media failure(s)");
+
+	/*
+	 * bytes per sectors are on the range 2^9 - 2^12 (512 - 4096)
+	 */
+	if (vbr->bytes_per_sector < 9 || vbr->bytes_per_sector > 12) {
+		exfat_msg(sb, KERN_ERR, "invalid byte per sectors: %u",
+			  (1 << vbr->bytes_per_sector));
+		return -EINVAL;
+	}
+
+	/*
+	 * sectors per cluster can be as low as 0, and must not result
+	 * in a cluster size higher than 32MB (byte_per_sector +
+	 * sectors_per_cluster must not be creater than 25)
+	 */
+	if (vbr->bytes_per_sector + vbr->sectors_per_cluster > 25) {
+		exfat_msg(sb, KERN_ERR, "invalid cluster size: %u",
+		  1 << (vbr->bytes_per_sector + vbr->sectors_per_cluster));
+		return -EINVAL;
+	}
+
+	num_fats = __le16_to_cpu(vbr->fat_num);
+	if (num_fats == 0) {
+		exfat_msg(sb, KERN_ERR, "superblock reports no FAT.");
+		return -EINVAL;
+	}
+	if (num_fats > 1) {
+		exfat_msg(sb, KERN_ERR, "TexFAT is not supported.");
+		return -EINVAL;
+	}
+
+	if (memcmp(vbr->boot_sig, "\x55\xaa", 2)) {
+		exfat_msg(sb, KERN_ERR, "invalid end boot signature: %02x%02x.",
+			  vbr->boot_sig[0], vbr->boot_sig[1]);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int exfat_fill_root(struct super_block *sb, struct inode *root)
+{
+	struct exfat_sb_info *sbi = EXFAT_SB(sb);
+	u32 nclust;
+	u32 dummy;
+	loff_t links;
+
+	root->i_ino = EXFAT_ROOT_INO;
+	root->i_version = 1;
+	EXFAT_I(root)->first_cluster =
+		__le32_to_cpu(sbi->root_dir_cluster);
+	EXFAT_I(root)->attributes = E_EXFAT_ATTR_DIRECTORY;
+
+	root->i_uid = sbi->options.uid;
+	root->i_gid = sbi->options.gid;
+
+	root->i_mode = exfat_make_mode(sbi, S_IRWXUGO, E_EXFAT_ATTR_DIRECTORY);
+	root->i_version++;
+	root->i_generation = 0;
+
+	root->i_op = &exfat_dir_inode_operations;
+	root->i_fop = &exfat_dir_operations;
+
+	/*
+	 * root inode cannot use bitmap.
+	 */
+	EXFAT_I(root)->flags = EXFAT_I_ALLOC_POSSIBLE;
+
+	/*
+	 * set i_size
+	 */
+	nclust = 0;
+	while (__exfat_get_fat_cluster(root, nclust, &dummy, false) == 0)
+		++nclust;
+	root->i_size = nclust << sbi->clusterbits;
+	root->i_blocks = nclust << (sbi->clusterbits - 9);
+	EXFAT_I(root)->allocated_clusters = nclust;
+
+	/*
+	 * +2 to account for '.' and '..'
+	 */
+	links = exfat_dir_links(root);
+	if (links < 0)
+		return links;
+	set_nlink(root, links + 2);
+
+	root->i_mtime = root->i_atime = root->i_ctime = CURRENT_TIME_SEC;
+
+	return 0;
+}
+
+static loff_t exfat_file_max_byte(struct exfat_sb_info *sbi)
+{
+	u32 max_clusters = EXFAT_CLUSTER_LASTVALID -
+		EXFAT_CLUSTER_FIRSTVALID + 1;
+
+	return (loff_t)max_clusters << sbi->clusterbits;
+}
+
+static int exfat_show_options(struct seq_file *m, struct dentry *root)
+{
+	struct exfat_sb_info *sbi = EXFAT_SB(root->d_inode->i_sb);
+
+	if (!uid_eq(sbi->options.uid, GLOBAL_ROOT_UID))
+		seq_printf(m, ",uid=%u",
+			   from_kuid_munged(&init_user_ns, sbi->options.uid));
+	if (!gid_eq(sbi->options.gid, GLOBAL_ROOT_GID))
+		seq_printf(m, ",gid=%u",
+			   from_kgid_munged(&init_user_ns, sbi->options.gid));
+
+	seq_printf(m, ",fmask=%04o", sbi->options.fmask);
+	seq_printf(m, ",dmask=%04o", sbi->options.dmask);
+
+	if (sbi->options.time_offset_set)
+		seq_printf(m, ",time_offset=%d", sbi->options.time_offset);
+
+	switch (sbi->options.error_action) {
+	case EXFAT_ERROR_ACTION_PANIC:
+		seq_printf(m, ",errors=panic");
+		break;
+	case EXFAT_ERROR_ACTION_REMOUNT_RO:
+		seq_printf(m, ",errors=remount-ro");
+		break;
+	default:
+		seq_printf(m, ",errors=continue");
+		break;
+	}
+
+	return 0;
+}
+
+enum {
+	Opt_exfat_uid,
+	Opt_exfat_gid,
+	Opt_exfat_dmask,
+	Opt_exfat_fmask,
+	Opt_exfat_time_offset,
+	Opt_exfat_error_continue,
+	Opt_exfat_error_remount_ro,
+	Opt_exfat_error_panic,
+	Opt_exfat_err,
+};
+
+static const match_table_t exfat_tokens = {
+	{ Opt_exfat_uid, "uid=%u", },
+	{ Opt_exfat_gid, "gid=%u", },
+	{ Opt_exfat_dmask, "dmask=%04o", },
+	{ Opt_exfat_fmask, "fmask=%04o", },
+	{ Opt_exfat_time_offset, "time_offset=%d", },
+	{ Opt_exfat_error_continue, "errors=continue", },
+	{ Opt_exfat_error_remount_ro, "errors=remount-ro", },
+	{ Opt_exfat_error_panic, "errors=panic", },
+	{ Opt_exfat_err, NULL },
+};
+
+static int exfat_parse_options(struct super_block *sb, char *opts, int silent)
+{
+	struct exfat_sb_info *sbi = EXFAT_SB(sb);
+	char *p;
+
+	sbi->options.uid = current_uid();
+	sbi->options.gid = current_gid();
+
+	sbi->options.dmask = current_umask();
+	sbi->options.fmask = current_umask();
+	sbi->options.time_offset_set = 0;
+	sbi->options.error_action = EXFAT_ERROR_ACTION_CONTINUE;
+
+	while (1) {
+		int token;
+		substring_t args[MAX_OPT_ARGS];
+		unsigned int optval;
+
+		p = strsep(&opts, ",");
+		if (!p)
+			break;
+		token = match_token(p, exfat_tokens, args);
+
+		switch (token) {
+		case Opt_exfat_uid:
+			if (match_int(&args[0], &optval))
+				return -EINVAL;
+			sbi->options.uid = make_kuid(current_user_ns(), optval);
+			break;
+
+		case Opt_exfat_gid:
+			if (match_int(&args[0], &optval))
+				return -EINVAL;
+			sbi->options.gid = make_kgid(current_user_ns(), optval);
+			break;
+
+		case Opt_exfat_dmask:
+			if (match_octal(&args[0], &optval))
+				return -EINVAL;
+			sbi->options.dmask = optval;
+			break;
+
+		case Opt_exfat_fmask:
+			if (match_octal(&args[0], &optval))
+				return -EINVAL;
+			sbi->options.fmask = optval;
+			break;
+
+		case Opt_exfat_time_offset:
+			if (match_int(&args[0], &optval))
+				return -EINVAL;
+			if (optval < -12 * 60 && optval > 12 * 60) {
+				if (!silent)
+					exfat_msg(sb, KERN_INFO, "invalid "
+						  "time_offset value %d: "
+						  "should be between %d and %d",
+						  optval, -12 * 60, 12 * 60);
+				return -EINVAL;
+			}
+			sbi->options.time_offset = optval;
+			sbi->options.time_offset_set = 1;
+			break;
+
+		case Opt_exfat_error_continue:
+			sbi->options.error_action = EXFAT_ERROR_ACTION_CONTINUE;
+			break;
+
+		case Opt_exfat_error_remount_ro:
+			sbi->options.error_action =
+				EXFAT_ERROR_ACTION_REMOUNT_RO;
+			break;
+
+		case Opt_exfat_error_panic:
+			sbi->options.error_action = EXFAT_ERROR_ACTION_PANIC;
+			break;
+
+		default:
+			if (!silent)
+				exfat_msg(sb, KERN_INFO, "Unrecognized mount "
+					  "option %s or missing parameter.\n",
+					  p);
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+static void exfat_set_sb_dirty(struct super_block *sb, bool set, bool force)
+{
+	struct exfat_sb_info *sbi = EXFAT_SB(sb);
+	u16 flags;
+
+	/*
+	 * do not change anything if mounted read only and not
+	 * forced. the force case would happen during remount.
+	 */
+	if ((sb->s_flags & MS_RDONLY) && !force)
+		return ;
+
+	if (sbi->dirty) {
+		if (set)
+			exfat_msg(sb, KERN_WARNING, "Volume was not cleanly "
+				  "umounted. fsck should probably be needed.");
+		return ;
+	}
+
+	flags = __le16_to_cpu(sbi->vbr->volume_flags);
+	if (set)
+		flags |= EXFAT_FLAG_DIRTY;
+	else
+		flags &= ~EXFAT_FLAG_DIRTY;
+	sbi->vbr->volume_flags = __cpu_to_le16(flags);
+
+	mark_buffer_dirty(sbi->sb_bh);
+	sync_dirty_buffer(sbi->sb_bh);
+}
+
+static int exfat_remount(struct super_block *sb, int *flags, char *opts)
+{
+	int new_rdonly = *flags & MS_RDONLY;
+
+	if (new_rdonly != (sb->s_flags & MS_RDONLY)) {
+		if (new_rdonly)
+			exfat_set_sb_dirty(sb, false, false);
+		else
+			/*
+			 * sb->s_flag still has MS_RDONLY, so we need
+			 * to force the dirty state
+			 */
+			exfat_set_sb_dirty(sb, true, true);
+	}
+	return 0;
+}
+
+static int exfat_fill_super(struct super_block *sb, void *data, int silent)
+{
+	struct exfat_sb_info *sbi = NULL;
+	int ret = -ENOMEM;
+	struct inode *root = NULL;
+	int i;
+
+	sbi = kzalloc(sizeof (*sbi), GFP_KERNEL);
+	if (!sbi)
+		return -ENOMEM;
+
+	sb->s_fs_info = sbi;
+	if (exfat_parse_options(sb, data, silent) < 0)
+		return -EINVAL;
+
+	mutex_init(&sbi->sb_mutex);
+	spin_lock_init(&sbi->inode_hash_lock);
+
+	/*
+	 * first block, before we know sector size.
+	 */
+	sbi->sb_bh = sb_bread(sb, 0);
+	if (!sbi->sb_bh)
+		goto fail;
+
+	sbi->vbr = (struct exfat_vbr*)sbi->sb_bh->b_data;
+	sb->s_op = &exfat_super_ops;
+
+
+	ret = exfat_check_sb(sb);
+	if (ret)
+		goto fail;
+
+	/*
+	 * vbr seems sane, fill sbi.
+	 */
+	sbi->sectorsize = (1 << sbi->vbr->bytes_per_sector);
+	sbi->clustersize = sbi->sectorsize *
+		(1 << sbi->vbr->sectors_per_cluster);
+
+	sbi->sectors_per_cluster = sbi->clustersize / sbi->sectorsize;
+
+	sbi->sectorbits = sbi->vbr->bytes_per_sector;
+	sbi->clusterbits = sbi->vbr->sectors_per_cluster + sbi->sectorbits;
+	sbi->sectormask = sbi->sectorsize - 1;
+	sbi->clustermask = sbi->clustersize - 1;
+
+
+	sbi->fat_offset = __le32_to_cpu(sbi->vbr->fat_offset);
+	sbi->fat_length = __le32_to_cpu(sbi->vbr->fat_length);
+
+	sbi->root_dir_cluster = __le32_to_cpu(sbi->vbr->cluster_root_dir);
+
+	sbi->cluster_heap_offset = __le32_to_cpu(sbi->vbr->cluster_heap_offset);
+	sbi->cluster_count = __le32_to_cpu(sbi->vbr->cluster_count);
+
+	sbi->dirty = !!(__le16_to_cpu(sbi->vbr->volume_flags) &
+			EXFAT_FLAG_DIRTY);
+
+	/*
+	 * now that we know sector size, reread superblock with
+	 * correct sector size.
+	 */
+	ret = -EIO;
+	if (sb->s_blocksize != sbi->sectorsize) {
+		if (!sb_set_blocksize(sb, sbi->sectorsize)) {
+			exfat_msg(sb, KERN_INFO, "bad block size %d.",
+				  sbi->sectorsize);
+			goto fail;
+		}
+
+		brelse(sbi->sb_bh);
+		sbi->vbr = NULL;
+
+		sbi->sb_bh = sb_bread(sb, 0);
+		if (!sbi->sb_bh)
+			goto fail;
+		sbi->vbr = (struct exfat_vbr*)sbi->sb_bh->b_data;
+		sb->s_fs_info = sbi;
+	}
+
+	ret = exfat_check_sb_checksum(sb);
+	if (ret)
+		goto fail;
+
+	sb->s_maxbytes = exfat_file_max_byte(sbi);
+
+	ret = exfat_init_fat(sb);
+	if (ret)
+		goto fail;
+
+	for (i = 0 ; i < EXFAT_HASH_SIZE; ++i) {
+		INIT_HLIST_HEAD(&sbi->inode_hash[i]);
+	}
+
+	/*
+	 * create root inode.
+	 */
+	root = new_inode(sb);
+	if (!root)
+		goto fail;
+
+	exfat_fill_root(sb, root);
+
+	ret = exfat_upcase_init(root);
+	if (ret)
+		goto fail_iput;
+
+	ret = exfat_init_bitmap(root);
+	if (ret)
+		goto fail_iput;
+
+
+	sb->s_root = d_make_root(root);
+	if (!sb->s_root)
+		goto fail_iput;
+
+	exfat_set_sb_dirty(sb, true, false);
+	return 0;
+
+fail_iput:
+	iput(root);
+
+fail:
+	if (sbi->sb_bh)
+		brelse(sbi->sb_bh);
+	if (sbi)
+		kfree(sbi);
+	return ret;
+}
+
+static struct dentry *exfat_mount(struct file_system_type *fstype,
+				  int flags, const char *dev_name, void *data)
+{
+	return mount_bdev(fstype, flags, dev_name, data, exfat_fill_super);
+}
+
+static void exfat_put_super(struct super_block *sb)
+{
+	struct exfat_sb_info *sbi;
+
+	sbi = EXFAT_SB(sb);
+	if (sbi) {
+		exfat_set_sb_dirty(sb, false, false);
+		exfat_exit_bitmap(sb);
+		brelse(sbi->sb_bh);
+		kfree(sbi->upcase_table);
+		kfree(sbi);
+	}
+}
+
+static int exfat_statfs(struct dentry *dentry, struct kstatfs *kstat)
+{
+	struct super_block *sb = dentry->d_inode->i_sb;
+	struct exfat_sb_info *sbi = EXFAT_SB(sb);
+	u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
+
+	memset(kstat, 0, sizeof (*kstat));
+
+
+	kstat->f_bsize = sbi->clustersize;
+	kstat->f_blocks = sbi->cluster_count;
+	kstat->f_bfree = sbi->free_clusters;
+	kstat->f_bavail = sbi->free_clusters;
+	kstat->f_namelen = 255;
+	kstat->f_fsid.val[0] = (u32)id;
+	kstat->f_fsid.val[1] = (u32)(id >> 32);
+
+	return 0;
+}
+
+static struct file_system_type exfat_fs_type = {
+	.owner		= THIS_MODULE,
+	.name		= "exfat",
+	.mount		= exfat_mount,
+	.kill_sb	= kill_block_super,
+	.fs_flags	= FS_REQUIRES_DEV,
+};
+
+static int __init exfat_init(void)
+{
+	int error;
+
+	/* some sanity check on internal structure sizes */
+	BUILD_BUG_ON(sizeof (struct exfat_vbr) != 512);
+
+	BUILD_BUG_ON(sizeof (struct exfat_volume_label_entry) != 0x20);
+	BUILD_BUG_ON(sizeof (struct exfat_bitmap_entry) != 0x20);
+	BUILD_BUG_ON(sizeof (struct exfat_upcase_entry) != 0x20);
+	BUILD_BUG_ON(sizeof (struct exfat_guid_entry) != 0x20);
+	BUILD_BUG_ON(sizeof (struct exfat_padding_entry) != 0x20);
+	BUILD_BUG_ON(sizeof (struct exfat_acl_entry) != 0x20);
+	BUILD_BUG_ON(sizeof (struct exfat_filedir_entry) != 0x20);
+	BUILD_BUG_ON(sizeof (struct exfat_stream_extension_entry) != 0x20);
+	BUILD_BUG_ON(sizeof (struct exfat_filename_entry) != 0x20);
+
+	error = exfat_init_inodes();
+	if (error)
+		return error;
+
+
+	error = register_filesystem(&exfat_fs_type);
+	if (error)
+		exfat_exit_inodes();
+	return error;
+}
+
+static void __exit exfat_exit(void)
+{
+	unregister_filesystem(&exfat_fs_type);
+	exfat_exit_inodes();
+}
+
+module_init(exfat_init);
+module_exit(exfat_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Nicolas Schichan <nschichan@freebox.fr>");
diff -Nruw linux-4.2-fbx/fs/exfat./time.c linux-4.2-fbx/fs/exfat/time.c
--- linux-4.2-fbx/fs/exfat./time.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/fs/exfat/time.c	2013-12-04 14:33:22.639479032 +0100
@@ -0,0 +1,126 @@
+
+#include <linux/kernel.h>
+#include <linux/fs.h>
+
+#include "exfat.h"
+#include "exfat_fs.h"
+
+
+
+extern struct timezone sys_tz;
+
+/*
+ * The epoch of FAT timestamp is 1980.
+ *     :  bits :     value
+ * date:  0 -  4: day	(1 -  31)
+ * date:  5 -  8: month	(1 -  12)
+ * date:  9 - 15: year	(0 - 127) from 1980
+ * time:  0 -  4: sec	(0 -  29) 2sec counts
+ * time:  5 - 10: min	(0 -  59)
+ * time: 11 - 15: hour	(0 -  23)
+ */
+#define SECS_PER_MIN	60
+#define SECS_PER_HOUR	(60 * 60)
+#define SECS_PER_DAY	(SECS_PER_HOUR * 24)
+/* days between 1.1.70 and 1.1.80 (2 leap days) */
+#define DAYS_DELTA	(365 * 10 + 2)
+/* 120 (2100 - 1980) isn't leap year */
+#define YEAR_2100	120
+#define IS_LEAP_YEAR(y)	(!((y) & 3) && (y) != YEAR_2100)
+
+/* Linear day numbers of the respective 1sts in non-leap years. */
+static time_t days_in_year[] = {
+	/* Jan  Feb  Mar  Apr  May  Jun  Jul  Aug  Sep  Oct  Nov  Dec */
+	0,   0,  31,  59,  90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0,
+};
+
+/* Convert a FAT time/date pair to a UNIX date (seconds since 1 1 70). */
+void exfat_time_2unix(struct timespec *ts, u32 datetime, u8 time_cs,
+		      s8 tz_offset)
+{
+	u16 date = (datetime >> 16);
+	u16 time = (datetime & 0xffff);
+	time_t second, day, leap_day, month, year;
+
+	year  = date >> 9;
+	month = max(1, (date >> 5) & 0xf);
+	day   = max(1, date & 0x1f) - 1;
+
+	if (((tz_offset & (1 << 6)) == 0))
+		tz_offset &= ~(1 << 7);
+
+	leap_day = (year + 3) / 4;
+	if (year > YEAR_2100)		/* 2100 isn't leap year */
+		leap_day--;
+	if (IS_LEAP_YEAR(year) && month > 2)
+		leap_day++;
+
+	second =  (time & 0x1f) << 1;
+	second += ((time >> 5) & 0x3f) * SECS_PER_MIN;
+	second += (time >> 11) * SECS_PER_HOUR;
+	second += (year * 365 + leap_day
+		   + days_in_year[month] + day
+		   + DAYS_DELTA) * SECS_PER_DAY;
+
+	second -= tz_offset * 15 * SECS_PER_MIN;
+
+	if (time_cs) {
+		ts->tv_sec = second + (time_cs / 100);
+		ts->tv_nsec = (time_cs % 100) * 10000000;
+	} else {
+		ts->tv_sec = second;
+		ts->tv_nsec = 0;
+	}
+}
+
+/* Convert linear UNIX date to a FAT time/date pair. */
+void exfat_time_2exfat(struct exfat_sb_info *sbi, struct timespec *ts,
+		       u32 *datetime, u8 *time_cs, s8 *tz_offset)
+{
+	struct tm tm;
+	u16 time;
+	u16 date;
+	int offset;
+
+	if (sbi->options.time_offset_set) {
+		offset = -sbi->options.time_offset;
+	} else
+		offset = sys_tz.tz_minuteswest;
+
+	time_to_tm(ts->tv_sec, -offset * SECS_PER_MIN, &tm);
+
+	/*  FAT can only support year between 1980 to 2107 */
+	if (tm.tm_year < 1980 - 1900) {
+		time = 0;
+		date = cpu_to_le16((0 << 9) | (1 << 5) | 1);
+		if (time_cs)
+			*time_cs = 0;
+		*tz_offset = 0;
+		return;
+	}
+	if (tm.tm_year > 2107 - 1900) {
+		time = cpu_to_le16((23 << 11) | (59 << 5) | 29);
+		date = cpu_to_le16((127 << 9) | (12 << 5) | 31);
+		if (time_cs)
+			*time_cs = 199;
+		*tz_offset = 0;
+		return;
+	}
+
+	/* from 1900 -> from 1980 */
+	tm.tm_year -= 80;
+	/* 0~11 -> 1~12 */
+	tm.tm_mon++;
+	/* 0~59 -> 0~29(2sec counts) */
+	tm.tm_sec >>= 1;
+
+	time = cpu_to_le16(tm.tm_hour << 11 | tm.tm_min << 5 | tm.tm_sec);
+	date = cpu_to_le16(tm.tm_year << 9 | tm.tm_mon << 5 | tm.tm_mday);
+
+	*datetime = (date << 16) | time;
+
+	if (time_cs)
+		*time_cs = (ts->tv_sec & 1) * 100 + ts->tv_nsec / 10000000;
+	*tz_offset = -offset / 15;
+	*tz_offset |= (1 << 7);
+}
diff -Nruw linux-4.2-fbx/fs/exfat./upcase.c linux-4.2-fbx/fs/exfat/upcase.c
--- linux-4.2-fbx/fs/exfat./upcase.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/fs/exfat/upcase.c	2013-12-04 14:33:22.639479032 +0100
@@ -0,0 +1,136 @@
+/*
+ * upcase.c for exfat
+ * Created by <nschichan@freebox.fr> on Wed Aug  7 11:51:37 2013
+ */
+
+#include <linux/buffer_head.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+
+#include "exfat.h"
+#include "exfat_fs.h"
+
+static u32 exfat_calc_upcase_checksum(const u8 *data, u32 checksum,
+				      size_t count)
+{
+	while (count) {
+		checksum = ((checksum << 31) | (checksum >> 1)) + *data;
+		--count;
+		++data;
+	}
+	return checksum;
+}
+
+static int exfat_load_upcase_table(struct super_block *sb, u32 disk_cluster,
+				   u32 *out_checksum)
+{
+	struct exfat_sb_info *sbi = EXFAT_SB(sb);
+	struct buffer_head *bh;
+	sector_t start, sect, end;
+	u32 off = 0;
+	u32 byte_len = sbi->upcase_len * sizeof (__le16);
+	u32 checksum = 0;
+
+	/*
+	 * up-case table are not fragmented, so sequential cluster
+	 * read will do here.
+	 */
+	start = exfat_cluster_sector(sbi, disk_cluster);
+	end = start + DIV_ROUND_UP(byte_len,
+			   sbi->sectorsize);
+	for (sect = start; sect < end; ++sect) {
+		u32 len = sbi->sectorsize;
+
+		if (sect == end - 1)
+			len = byte_len & sbi->sectormask;
+
+		bh = sb_bread(sb, sect);
+		if (!bh) {
+			exfat_msg(sb, KERN_ERR,
+				  "unable to read upcase sector %llu", sect);
+			return -EIO;
+		}
+		memcpy((u8*)sbi->upcase_table + off, bh->b_data,
+		       len);
+
+		checksum = exfat_calc_upcase_checksum(bh->b_data, checksum,
+						      len);
+
+		off += len;
+		brelse(bh);
+	}
+
+	BUG_ON(off != byte_len);
+	*out_checksum = checksum;
+	return 0;
+}
+
+int exfat_upcase_init(struct inode *root)
+{
+	struct exfat_sb_info *sbi = EXFAT_SB(root->i_sb);
+	struct exfat_upcase_entry *upcase;
+	struct exfat_dir_ctx dctx;
+	int error;
+	u64 upcase_length;
+	u32 checksum;
+
+	/*
+	 * configure directory context and look for an upcase table
+	 * entry.
+	 */
+	if (exfat_init_dir_ctx(root, &dctx, 0) < 0)
+		return -EIO;
+
+	error = -EIO;
+	upcase = __exfat_dentry_next(&dctx, E_EXFAT_UPCASE_TABLE, 0xff,
+				     true, NULL);
+	if (!upcase)
+		goto fail;
+
+	/*
+	 * check upcase table length. we need it to be non-zero,
+	 * ending on a __le16 boundary and provide at most a
+	 * conversion for the whole __le16 space.
+	 */
+	upcase_length = __le64_to_cpu(upcase->length);
+	if (upcase_length == 0 ||
+	    upcase_length & (sizeof (__le16) - 1) ||
+	    upcase_length > 0xffff * sizeof (__le16)) {
+		exfat_msg(root->i_sb, KERN_ERR, "invalid upcase length %llu",
+			  upcase_length);
+		goto fail;
+	}
+
+	/*
+	 * load complete upcase table in memory.
+	 */
+	error = -ENOMEM;
+	sbi->upcase_len = upcase_length / sizeof (__le16);
+	sbi->upcase_table = kmalloc(upcase_length, GFP_NOFS);
+	if (!sbi->upcase_table)
+		goto fail;
+
+	error = exfat_load_upcase_table(root->i_sb,
+					__le32_to_cpu(upcase->cluster_addr),
+					&checksum);
+	if (error)
+		goto fail;
+
+	if (checksum != __le32_to_cpu(upcase->checksum)) {
+		exfat_msg(root->i_sb, KERN_INFO,
+			  "upcase table checksum mismatch: have %08x, "
+			  "expect %08x", checksum,
+			  __le32_to_cpu(upcase->checksum));
+		error = -EINVAL;
+		goto fail;
+	}
+
+	exfat_cleanup_dir_ctx(&dctx);
+	return 0;
+
+fail:
+	if (sbi->upcase_table)
+		kfree(sbi->upcase_table);
+	exfat_cleanup_dir_ctx(&dctx);
+	return error;
+}
--- /dev/null	2015-07-31 18:17:35.952031993 +0200
+++ linux-4.2-fbx/include/linux/fbxbootinfo.h	2010-08-16 18:15:01.008432229 +0200
@@ -0,0 +1,11 @@
+#ifndef FBXBOOTINFO_H
+#define FBXBOOTINFO_H
+
+struct fbx_bootinfo {
+	u32 bank_number;
+	char uboot_version_str[128];
+	u32 bank0_forced;
+	char cefdk_version_str[256];
+} __attribute__ ((packed));
+
+#endif /* FBXBOOTINFO_H */
--- /dev/null	2015-07-31 18:17:35.952031993 +0200
+++ linux-4.2-fbx/include/linux/fbxbridge.h	2013-12-04 14:33:24.227479057 +0100
@@ -0,0 +1,242 @@
+#ifndef _FBXBRIDGE_H
+# define _FBXBRIDGE_H
+
+#include <linux/if.h>
+#include <linux/if_ether.h>
+
+#define MAX_ALIASES		3
+
+#define FBXBRIDGE_PFX		"fbxbridge: "
+
+#define FBXBRIDGE_LAN_TO_WAN	1
+#define FBXBRIDGE_WAN_TO_LAN	2
+
+#define FBXBRIDGE_FLAGS_FILTER			(1 << 0)
+#define FBXBRIDGE_FLAGS_DHCPD			(1 << 1)
+#define FBXBRIDGE_FLAGS_NETFILTER		(1 << 2)
+
+/*
+ * ioctl command
+ */
+
+enum fbxbridge_ioctl_cmd
+{
+	E_CMD_BR_CHG = 0,
+	E_CMD_BR_DEV_CHG,
+	E_CMD_BR_PARAMS,
+};
+
+struct fbxbridge_ioctl_chg
+{
+	char	brname[IFNAMSIZ];
+	int	action;
+};
+
+struct fbxbridge_ioctl_dev_chg
+{
+	char	brname[IFNAMSIZ];
+	char	devname[IFNAMSIZ];
+	int	wan;
+	int	action;
+};
+
+struct fbxbridge_port_info
+{
+	char	name[IFNAMSIZ];
+	int	present;
+};
+
+struct fbxbridge_ioctl_params
+{
+	int				action;
+	char				brname[IFNAMSIZ];
+	struct fbxbridge_port_info	wan_dev;
+	struct fbxbridge_port_info	lan_dev;
+	unsigned int			flags;
+	unsigned char			lan_hwaddr[ETH_ALEN];
+	unsigned char			have_hw_addr;
+	unsigned int			dns1_addr;
+	unsigned int			dns2_addr;
+	unsigned long			ip_aliases[MAX_ALIASES];
+
+	unsigned long			dhcpd_renew_time;
+	unsigned long			dhcpd_rebind_time;
+	unsigned long			dhcpd_lease_time;
+	unsigned int			inputmark;
+};
+
+struct fbxbridge_ioctl_req
+{
+	enum fbxbridge_ioctl_cmd	cmd;
+	unsigned long			arg;
+};
+
+#ifdef __KERNEL__
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+
+#define ARP_RATE_LIMIT		(HZ)
+#define ARP_ETHER_SIZE		(8 + ETH_ALEN * 2 + 4 * 2)
+
+#define FBXBR_PORT_WAN		0
+#define FBXBR_PORT_LAN		1
+
+#define FBXBR_CACHE_SIZE	128
+#define FBXBR_MAX_RULES		256
+
+struct fbxbridge_port;
+
+struct fbxbridge_fp_rule {
+	u32			sip;
+	u32			dip;
+	u16			sport;
+	u16			dport;
+
+	u8			dest_hwaddr[6];
+	struct fbxbridge_port	*oport;
+
+	struct hlist_node	hnext;
+	struct list_head	next;
+};
+
+struct fbxbridge_fp {
+	struct hlist_head	hrules[FBXBR_CACHE_SIZE];
+	struct list_head	rules;
+	unsigned int		count;
+};
+
+struct fbxbridge_port {
+	struct net_device	*dev;
+	struct net_device	*master_dev;
+	u16			vlan1;
+	u16			vlan2;
+	struct fbxbridge_fp	tcp_fp;
+	struct fbxbridge_fp	udp_fp;
+};
+
+struct fbxbridge {
+	struct fbxbridge	*next;
+	unsigned int		refcount;
+
+	char			name[IFNAMSIZ];
+	struct net_device	*dev;
+
+	/* local and remote (fbx) ip address */
+	unsigned long		br_ipaddr;
+	unsigned long		br_remote_ipaddr;
+
+	/* list of ip we consider to be local */
+	unsigned long		ip_aliases[MAX_ALIASES];
+
+	/* wan side inet info */
+	unsigned long		wan_ipaddr;
+	unsigned long		wan_netmask;
+	unsigned long		lan_netmask;
+	/* this is the _client_ gw */
+	unsigned long		wan_gw;
+
+	char			wan_dev_name[IFNAMSIZ];
+	char			lan_dev_name[IFNAMSIZ];
+	int			fast_path_enabled;
+	struct fbxbridge_port	ports[2];
+
+	unsigned char		lan_hwaddr[ETH_ALEN];
+	unsigned char		have_hw_addr;
+
+	unsigned int		flags;
+	unsigned int		inputmark;
+
+	unsigned int		dns1_ipaddr;
+	unsigned int		dns2_ipaddr;
+
+	unsigned long		last_arp_send;
+
+	unsigned long		dhcpd_renew_time;
+	unsigned long		dhcpd_rebind_time;
+	unsigned long		dhcpd_lease_time;
+};
+
+extern struct fbxbridge *fbxbridge_list;
+
+/* fbxbridge_dev.c */
+void __fbxbridge_keep_hw_addr(struct fbxbridge *br, unsigned char *hwaddr);
+
+/* fbxbridge_dhcp.c */
+void fbxbridge_dhcpd(struct fbxbridge *br, struct sk_buff *skb);
+
+
+/* fbxbridge_forward.c */
+struct sk_buff *fbxbridge_handle_frame(struct fbxbridge *br,
+				       struct sk_buff *skb);
+
+
+/* fbxbridge_filter.c */
+int
+fbxbridge_filter_lan_to_wan_packet(struct fbxbridge *br, struct sk_buff *skb);
+
+int
+fbxbridge_filter_wan_to_lan_packet(struct fbxbridge *br, struct sk_buff *skb);
+
+int fbxbridge_nf_hook(struct fbxbridge *br, uint8_t pf, unsigned int hook,
+		      struct sk_buff *skb, struct net_device *in,
+		      struct net_device *out);
+
+/* fbxbridge_local.c */
+void
+handle_local_input_lan_frame(struct fbxbridge *br, struct sk_buff *skb);
+
+int
+handle_local_output_frame(struct fbxbridge *br, struct sk_buff *skb);
+
+
+/* fbxbridge_output.c */
+void output_arp_frame(struct fbxbridge *br, struct net_device *dev,
+		      unsigned short type,
+		      unsigned long src_ip, unsigned char *src_hw,
+		      unsigned long target_ip, unsigned char *target_hw);
+
+void output_lan_frame(struct fbxbridge *br, struct sk_buff *skb);
+
+void output_lan_mcast_frame(struct fbxbridge *br, struct sk_buff *skb);
+
+void output_wan_frame(struct fbxbridge *br, struct sk_buff *skb);
+
+
+/* fbxbridge_utils.c */
+void fbxbridge_snat_packet(struct sk_buff *skb, unsigned long new_addr);
+
+void fbxbridge_dnat_packet(struct sk_buff *skb, unsigned long new_addr);
+
+int fbxbridge_check_ip_packet(struct sk_buff *skb);
+
+int fbxbridge_check_udp_tcp_packet(struct sk_buff *skb);
+
+/* fbxbridge_fastpath.c */
+int __fbxbridge_fp_in_vlan_tcp4(struct net_device *idev, struct sk_buff *skb);
+
+int __fbxbridge_fp_in_vlan_udp4(struct net_device *idev, struct sk_buff *skb);
+
+int __fbxbridge_fp_add_wan_to_lan(struct fbxbridge *br,
+				  const struct sk_buff *skb,
+				  const uint8_t *new_dest_hw_addr);
+
+int __fbxbridge_fp_add_lan_to_wan(struct fbxbridge *br,
+				  const struct sk_buff *skb,
+				  const uint8_t *new_dest_hw_addr);
+
+void __fbxbridge_fp_flush_by_dip(struct fbxbridge_port *bport, uint32_t dip);
+
+void __fbxbridge_fp_flush(struct fbxbridge *br);
+
+void fbxbridge_fp_flush_all(void);
+
+void fbxbridge_fp_init(struct fbxbridge *br);
+
+void __fbxbridge_fp_check(struct fbxbridge *br);
+
+#endif /* ! __KERNEL__ */
+
+#endif
--- /dev/null	2015-07-31 18:17:35.952031993 +0200
+++ linux-4.2-fbx/include/linux/fbxjtag.h	2013-12-04 14:33:24.227479057 +0100
@@ -0,0 +1,88 @@
+#ifndef FBXJTAG_H_
+# define FBXJTAG_H_
+
+#ifdef __KERNEL__
+# include <linux/types.h>
+#endif
+
+# define JTAG_RESET_STEPS	16
+# define JTAG_DATA_READ_SIZE	128
+# define JTAG_INST_READ_SIZE	128
+# define JTAG_DEF_CLOCK_DELAY	500
+# define JTAG_DEF_WAIT_TMS	0
+
+enum jtag_main_state {
+	JTAG_STATE_TEST_MASK	=	0x10,
+	JTAG_STATE_RUN_MASK	=	0x20,
+	JTAG_STATE_DR_MASK	=	0x40,
+	JTAG_STATE_IR_MASK	=	0x80,
+};
+#define JTAG_STATE_MASK			0xF0
+
+enum jtag_sub_state {
+	JTAG_SUB_STATE_SELECT	=	0x0,
+	JTAG_SUB_STATE_CAPTURE	=	0x1,
+	JTAG_SUB_STATE_SHIFT	=	0x2,
+	JTAG_SUB_STATE_EXIT1	=	0x3,
+	JTAG_SUB_STATE_PAUSE	=	0x4,
+	JTAG_SUB_STATE_EXIT2	=	0x5,
+	JTAG_SUB_STATE_UPDATE	=	0x6,
+};
+#define JTAG_SUB_STATE_MASK		0xF
+
+enum jtag_state {
+	JTAG_STATE_UNDEF	= 0,
+	JTAG_STATE_TEST_LOGIC_RESET	= JTAG_STATE_TEST_MASK,
+	JTAG_STATE_RUN_TEST_IDLE	= JTAG_STATE_RUN_MASK,
+
+	JTAG_STATE_SELECT_DR	= JTAG_STATE_DR_MASK | JTAG_SUB_STATE_SELECT,
+	JTAG_STATE_CAPTURE_DR	= JTAG_STATE_DR_MASK | JTAG_SUB_STATE_CAPTURE,
+	JTAG_STATE_SHIFT_DR	= JTAG_STATE_DR_MASK | JTAG_SUB_STATE_SHIFT,
+	JTAG_STATE_EXIT1_DR	= JTAG_STATE_DR_MASK | JTAG_SUB_STATE_EXIT1,
+	JTAG_STATE_PAUSE_DR	= JTAG_STATE_DR_MASK | JTAG_SUB_STATE_PAUSE,
+	JTAG_STATE_EXIT2_DR	= JTAG_STATE_DR_MASK | JTAG_SUB_STATE_EXIT2,
+	JTAG_STATE_UPDATE_DR	= JTAG_STATE_DR_MASK | JTAG_SUB_STATE_UPDATE,
+
+	JTAG_STATE_SELECT_IR	= JTAG_STATE_IR_MASK | JTAG_SUB_STATE_SELECT,
+	JTAG_STATE_CAPTURE_IR	= JTAG_STATE_IR_MASK | JTAG_SUB_STATE_CAPTURE,
+	JTAG_STATE_SHIFT_IR	= JTAG_STATE_IR_MASK | JTAG_SUB_STATE_SHIFT,
+	JTAG_STATE_EXIT1_IR	= JTAG_STATE_IR_MASK | JTAG_SUB_STATE_EXIT1,
+	JTAG_STATE_PAUSE_IR	= JTAG_STATE_IR_MASK | JTAG_SUB_STATE_PAUSE,
+	JTAG_STATE_EXIT2_IR	= JTAG_STATE_IR_MASK | JTAG_SUB_STATE_EXIT2,
+	JTAG_STATE_UPDATE_IR	= JTAG_STATE_IR_MASK | JTAG_SUB_STATE_UPDATE,
+
+	JTAG_STATE_MAX
+};
+
+#define JTAG_STATE_IN_DR(state)	((state) & JTAG_STATE_DR_MASK)
+#define JTAG_STATE_IN_IR(state)	((state) & JTAG_STATE_IR_MASK)
+
+#ifdef __KERNEL__
+
+#define JTAG_BUF_SIZE	2048
+
+struct fbxjtag_data {
+	const char	*name;
+	struct {
+		struct fbxgpio_pin	*tck;
+		struct fbxgpio_pin	*tms;
+		struct fbxgpio_pin	*tdi;
+		struct fbxgpio_pin	*tdo;
+	}		gpios;
+	unsigned long	clock_delay;
+	unsigned long	wait_tms;
+	unsigned long	data_read_size;
+	unsigned long	instruction_read_size;
+	struct device	*dev;
+	enum jtag_state state;
+	char		nb_reset;
+	char		dr_buf[JTAG_BUF_SIZE];
+	unsigned 	dr_w;
+	unsigned 	dr_r;
+	char		ir_buf[JTAG_BUF_SIZE];
+	unsigned 	ir_r;
+	unsigned 	ir_w;
+};
+#endif
+
+#endif /* !FBXJTAG_H_ */
--- /dev/null	2015-07-31 18:17:35.952031993 +0200
+++ linux-4.2-fbx/include/linux/fbxmtd_map_ioctl.h	2010-02-25 15:41:10.079486299 +0100
@@ -0,0 +1,52 @@
+/*
+ * fbxmtd_map_ioctl.h for linux-freebox
+ * Created by <nschichan@freebox.fr> on Thu Feb  8 20:37:28 2007
+ * Freebox SA
+ */
+
+#ifndef FBXMTD_MAP_IOCTL_H
+# define FBXMTD_MAP_IOCTL_H
+
+/*
+ * IOCTL interface
+ */
+#define FBXMTD_MINOR	242
+
+#define FBXMTD_MAP_IOCTL_MAX_DEV	2
+#define FBXMTD_MAP_IOCTL_MAX_PART	16
+
+struct fbxmtd_map_ioctl_part
+{
+	char		name[32];
+	uint32_t	offset;
+	uint32_t	size;
+	uint32_t	flags;
+};
+
+struct fbxmtd_map_ioctl_dev
+{
+	char				name[32];
+	uint32_t			base_phys;
+	int				bus_width;
+	uint32_t			size;
+	uint32_t			status;
+	struct fbxmtd_map_ioctl_part	parts[FBXMTD_MAP_IOCTL_MAX_PART];
+	int				num_parts;
+};
+
+#define FBXMTD_MAP_IOCTL_NR	0x42
+
+struct fbxmtd_map_ioctl_query
+{
+	uint32_t	cmd;
+	uint32_t	param;
+	int		result;
+	void __user	*user_buf;
+	uint32_t	user_buf_size;
+};
+
+#define FBXMTDCTL_CMD_GET_DEVICES	0x1
+#define FBXMTDCTL_CMD_ADD_DEVICE	0x2
+#define FBXMTDCTL_CMD_DEL_DEVICE	0x3
+
+#endif /* !FBXMTD_MAP_IOCTL_H */
--- /dev/null	2015-07-31 18:17:35.952031993 +0200
+++ linux-4.2-fbx/include/linux/fbxprocfs.h	2013-12-04 14:33:24.227479057 +0100
@@ -0,0 +1,40 @@
+#ifndef FBXPROCFS_H_
+#define FBXPROCFS_H_
+
+#include <linux/proc_fs.h>
+#include <asm/atomic.h>
+#include <linux/seq_file.h>
+
+struct fbxprocfs_client
+{
+	const char *dirname;
+	struct module *owner;
+	struct proc_dir_entry *dir;
+	atomic_t refcount;
+	struct list_head list;
+};
+
+struct fbxprocfs_desc {
+	char		*name;
+	unsigned long	id;
+	int	(*rfunc)(struct seq_file *, void *);
+	int	(*wfunc)(struct file *, const char *, unsigned long, void *);
+};
+
+struct fbxprocfs_client *fbxprocfs_add_client(const char *dirname,
+					      struct module *owner);
+
+int fbxprocfs_remove_client(struct fbxprocfs_client *client);
+
+
+int
+fbxprocfs_create_entries(struct fbxprocfs_client *client,
+			 const struct fbxprocfs_desc *ro_desc,
+			 const struct fbxprocfs_desc *rw_desc);
+
+int
+fbxprocfs_remove_entries(struct fbxprocfs_client *client,
+			 const struct fbxprocfs_desc *ro_desc,
+			 const struct fbxprocfs_desc *rw_desc);
+
+#endif /* FBXPROCFS_H_ */
--- /dev/null	2015-07-31 18:17:35.952031993 +0200
+++ linux-4.2-fbx/include/linux/fbxserial.h	2015-09-15 19:18:39.834466564 +0200
@@ -0,0 +1,122 @@
+#ifndef FBXSERIAL_H_
+#define FBXSERIAL_H_
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+/*
+ * some part of serial may vary, we use abstract struct to store this,
+ * data content depends on type.
+ */
+#define EXTINFO_SIZE		128
+#define EXTINFO_MAX_COUNT	16
+
+/*
+ * extdev desc
+ */
+#define EXTINFO_TYPE_EXTDEV	1
+
+#define EXTDEV_TYPE_BUNDLE	1
+#define EXTDEV_TYPE_MAX		2
+
+struct fbx_serial_extinfo {
+	u32			type;
+
+	union {
+		/* extdev */
+		struct {
+			u32	type;
+			u32	model;
+			char	serial[64];
+		} extdev;
+
+		/* raw access */
+		unsigned char	data[EXTINFO_SIZE];
+	} u;
+}  __attribute__ ((packed));;
+
+
+/*
+ * master serial structure
+ */
+
+#define FBXSERIAL_VERSION	1
+
+#define FBXSERIAL_MAGIC		0x2d9521ab
+
+#define MAC_ADDR_SIZE		6
+#define RANDOM_DATA_SIZE	32
+
+/*
+ * this  is the  maximum size  we accept  to check  crc32  against, so
+ * structure may no grow larger than this
+ */
+#define FBXSERIAL_MAX_SIZE	8192
+
+struct fbx_serial {
+	u32	crc32;
+	u32	magic;
+	u32	struct_version;
+	u32	len;
+
+	/* board serial */
+	u16	type;
+	u8	version;
+	u8	manufacturer;
+	u16	year;
+	u8	week;
+	u32	number;
+	u32	flags;
+
+	/* mac address base */
+	u8	mac_addr_base[MAC_ADDR_SIZE];
+
+	/* mac address count */
+	u8	mac_count;
+
+	/* random data */
+	u8	random_data[RANDOM_DATA_SIZE];
+
+	/* last update of data (seconds since epoch) */
+	u32	last_modified;
+
+	/* count of following extinfo tag */
+	u32	extinfo_count;
+
+	/* beginning of extended info */
+	struct fbx_serial_extinfo	extinfos[EXTINFO_MAX_COUNT];
+
+} __attribute__ ((packed));
+
+
+/*
+ * default value to use in case magic is wrong (no cksum in that case)
+ */
+static inline void fbxserial_set_default(struct fbx_serial *s)
+{
+	memset(s, 0, sizeof (*s));
+	s->magic = FBXSERIAL_MAGIC;
+	s->struct_version = FBXSERIAL_VERSION;
+	s->len = sizeof (*s);
+	s->manufacturer = '_';
+	memcpy(s->mac_addr_base, "\x00\x07\xCB\x00\x00\xFD", 6);
+	s->mac_count = 1;
+}
+
+void
+fbxserialinfo_get_random(unsigned char *data, unsigned int len);
+
+const void *
+fbxserialinfo_get_mac_addr(unsigned int index);
+
+int
+fbxserialinfo_read(void *data, struct fbx_serial *out);
+
+struct fbx_serial *fbxserialinfo_get(void);
+
+/*
+ * implemented in board specific code
+ */
+const struct fbx_serial *arch_get_fbxserial(void);
+
+#endif /* FBXSERIAL_H_ */
diff -Nruw linux-4.2-fbx/include/linux/hdmi-cec./dev.h linux-4.2-fbx/include/linux/hdmi-cec/dev.h
--- linux-4.2-fbx/include/linux/hdmi-cec./dev.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/include/linux/hdmi-cec/dev.h	2013-12-04 14:33:24.291479058 +0100
@@ -0,0 +1,30 @@
+#ifndef __HDMI_CEC_DEV_H
+#define __HDMI_CEC_DEV_H
+
+#include <linux/ioctl.h>
+#include <linux/hdmi-cec/hdmi-cec.h>
+
+#define CEC_IOCTL_BASE	'C'
+
+#define CEC_SET_LOGICAL_ADDRESS	_IOW(CEC_IOCTL_BASE, 0, int)
+#define CEC_RESET_DEVICE	_IOW(CEC_IOCTL_BASE, 3, int)
+#define CEC_GET_COUNTERS	_IOR(CEC_IOCTL_BASE, 4, struct cec_counters)
+#define CEC_SET_RX_MODE		_IOW(CEC_IOCTL_BASE, 5, enum cec_rx_mode)
+#define CEC_GET_TX_STATUS	_IOW(CEC_IOCTL_BASE, 6, struct cec_tx_status)
+#define CEC_SET_DETACHED_CONFIG	_IOW(CEC_IOCTL_BASE, 7, struct cec_detached_config)
+
+#define CEC_MAX_DEVS	(10)
+
+#ifdef __KERNEL__
+
+struct cec_adapter;
+
+int __init cec_cdev_init(void);
+void __exit cec_cdev_exit(void);
+
+int cec_create_adapter_node(struct cec_adapter *);
+void cec_remove_adapter_node(struct cec_adapter *);
+
+#endif /* __KERNEL__ */
+
+#endif /* __HDMI_CEC_DEV_H */
diff -Nruw linux-4.2-fbx/include/linux/hdmi-cec./hdmi-cec.h linux-4.2-fbx/include/linux/hdmi-cec/hdmi-cec.h
--- linux-4.2-fbx/include/linux/hdmi-cec./hdmi-cec.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/include/linux/hdmi-cec/hdmi-cec.h	2013-12-04 14:33:24.291479058 +0100
@@ -0,0 +1,126 @@
+/*
+ * Header for the HDMI CEC core infrastructure
+ */
+#ifndef __HDMI_CEC_H
+#define __HDMI_CEC_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/completion.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+
+#include <uapi/linux/hdmi-cec/hdmi-cec.h>
+
+struct cec_adapter;
+
+#define CEC_HW_HAS_COUNTERS	(1 << 0)	/* HW counts events */
+#define CEC_HW_HAS_RX_FILTER	(1 << 1)	/* HW has receive filter */
+
+/**
+ * struct cec_adapter_ops - cec adapter low-level operations
+ * @set_logical_address:	callback to set the logical address
+ * @send:	callback to send a cec payload
+ * @reset:	callback to reset the hardware
+ * @get_counters:	callback to get the counters (if supported by HW)
+ * @set_rx_mode:	callback to set the receive mode
+ * @attach:	callback to attach the host to the device
+ * @detach:	callbackt to detach the host from the device
+ * @set_detached_config:	callback to configure adapter when detached
+ */
+struct cec_adapter_ops {
+	int	(*set_logical_address)(struct cec_adapter *, const u8);
+	int	(*send)(struct cec_adapter *, u16, const u8 *, const u8);
+	int	(*reset)(struct cec_adapter *);
+	int	(*get_counters)(struct cec_adapter *, struct cec_counters *);
+	int	(*set_rx_mode)(struct cec_adapter *, enum cec_rx_mode);
+	int	(*attach)(struct cec_adapter *);
+	int	(*detach)(struct cec_adapter *);
+	int	(*set_detached_config)(struct cec_adapter *,
+				       const struct cec_detached_config *);
+};
+
+/**
+ * struct cec_adapter - cec adapter structure
+ * @driver_name:	driver prefix used for device naming
+ * @module:		module pointer for refcounting
+ * @ops:		struct cec_adapter_ops pointer
+ * @flags:		adapter flags bitmask
+ * @name:		adapter unique name
+ * @dev:		device structure for device/driver model interaction
+ * @lock:		adapter all-purpose mutex for exclusive locking
+ * @attached:		adapter attached to host or not
+ * @tx_pending:		true if tx is ongoing
+ * @tx_lock:		transmit lock
+ * @rx_msg_list:	receive message list head
+ * @rx_msg_list_lock:	receive message list lock
+ * @rx_msg_len:		receive message queue len
+ * @wait:		receive waitqueue (used for poll, read)
+ * @cdev:		character device node
+ */
+struct cec_adapter {
+	const char		*driver_name;
+	struct module		*module;
+	const struct cec_adapter_ops	*ops;
+	unsigned int		flags;
+	atomic_t		users;
+
+	/* unique device name, used for sysfs & chardev */
+	char			name[128];
+
+	/* associated sysfs device */
+	struct device		dev;
+
+	/* private */
+	struct mutex		lock;
+	bool			attached;
+
+	wait_queue_head_t	wait;
+
+	/* transmit message list */
+	unsigned long		tx_pending;
+	bool			last_tx_success;
+	u8			last_tx_flags;
+	u8			last_tx_tries;
+	struct timer_list	tx_timeout_timer;
+
+	/* receive message list */
+	struct list_head	rx_msg_list;
+	spinlock_t		rx_msg_list_lock;
+	unsigned int		rx_msg_len;
+
+	/* associated chardev */
+	struct cdev		cdev;
+
+	/* true when unregistering device */
+	bool			dead;
+};
+
+#define CECDEV_PRIV_ALIGN	8
+
+static inline void *cec_adapter_priv(struct cec_adapter *adapter)
+{
+	return (u8 *)adapter + ((sizeof(struct cec_adapter)
+			      + (CECDEV_PRIV_ALIGN - 1))
+			     & ~(CECDEV_PRIV_ALIGN - 1));
+}
+
+static inline struct cec_adapter *to_cec_adapter(struct device *d)
+{
+	return container_of(d, struct cec_adapter, dev);
+}
+
+struct cec_adapter *alloc_cec_adapter(size_t priv_size);
+int register_cec_adapter(struct cec_adapter *);
+void unregister_cec_adapter(struct cec_adapter *);
+void free_cec_adapter(struct cec_adapter *);
+int adapter_rx_done(struct cec_adapter *, const u8 *, const u8 len,
+		    bool valid, u8 flags);
+void adapter_tx_done(struct cec_adapter *, bool success, u8 flags, u8 tries);
+
+#endif /* __HDMI_CEC_H */
diff -Nruw linux-4.2-fbx/include/linux/remoti./leds.h linux-4.2-fbx/include/linux/remoti/leds.h
--- linux-4.2-fbx/include/linux/remoti./leds.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/include/linux/remoti/leds.h	2013-12-04 14:33:24.819479067 +0100
@@ -0,0 +1,11 @@
+#ifndef __REMOTI_LEDS_H
+#define __REMOTI_LEDS_H
+
+#define REMOTI_LEDS_COUNT	2
+
+struct remoti_leds_pdata {
+	unsigned num_leds;
+	const char *names[REMOTI_LEDS_COUNT];
+};
+
+#endif /* __REMOTI_LEDS_H */
diff -Nruw linux-4.2-fbx/include/linux/remoti./remoti.h linux-4.2-fbx/include/linux/remoti/remoti.h
--- linux-4.2-fbx/include/linux/remoti./remoti.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/include/linux/remoti/remoti.h	2013-12-04 14:33:24.819479067 +0100
@@ -0,0 +1,60 @@
+#ifndef __REMOTI_H
+#define __REMOTI_H
+
+#include <uapi/linux/remoti/remoti.h>
+
+/*
+ * platform data definition
+ */
+struct remoti_dev_pdata {
+	unsigned int		id;
+	unsigned int		reset_gpio;
+	unsigned int		reset_polarity;
+};
+
+/*
+ * kernel API to access remoti device
+ */
+struct rti_udev;
+
+struct rti_udev *rti_get_udevice(unsigned int id);
+
+void rti_release_udevice(struct rti_udev *udev);
+
+int rti_send_sync_msg(struct rti_udev *udev, struct rti_msg *msg);
+
+int rti_send_async_msg(struct rti_udev *udev, struct rti_msg *msg);
+
+int rti_register_cmd_callback(struct rti_udev *udev,
+			      u8 subsys, u8 cmd,
+			      void (*cb)(void *cb_priv,
+					 const struct rti_msg *msg),
+			      void *cb_priv);
+
+void rti_unregister_cmd_callback(struct rti_udev *udev, u8 subsys, u8 cmd);
+
+struct rti_kcallback {
+	__u8		subsys;
+	__u8		cmd;
+	void		(*cb)(void *cb_priv, const struct rti_msg *msg);
+};
+
+int rti_register_cmds_callback(struct rti_udev *udev,
+			       const struct rti_kcallback *cbs,
+			       size_t cb_count,
+			       void *cb_priv);
+
+void rti_unregister_cmds_callback(struct rti_udev *udev,
+				  const struct rti_kcallback *cbs,
+				  size_t cb_count);
+
+
+enum rti_udev_state {
+	RTI_UDEV_UP = 0,
+	RTI_UDEV_GOING_DOWN,
+};
+
+void rti_register_udevice_notifier(struct notifier_block *nb);
+void rti_unregister_udevice_notifier(struct notifier_block *nb);
+
+#endif /* __REMOTI_H */
--- /dev/null	2015-07-31 18:17:35.952031993 +0200
+++ linux-4.2-fbx/include/uapi/linux/exfat_user.h	2013-12-04 14:33:25.331479075 +0100
@@ -0,0 +1,47 @@
+/*
+ * exfat_user.h for exfat
+ * Created by <nschichan@freebox.fr> on Fri Aug 23 15:31:08 2013
+ */
+
+#ifndef __EXFAT_USER_H
+# define __EXFAT_USER_H
+
+struct exfat_fragment {
+	uint32_t	fcluster_start;
+	uint32_t	dcluster_start;
+	uint32_t	nr_clusters;
+	uint64_t	sector_start;
+};
+
+struct exfat_fragment_head {
+	uint32_t		fcluster_start;
+	uint32_t		nr_fragments;
+	uint32_t		sector_size;
+	uint32_t		cluster_size;
+	struct exfat_fragment	fragments[0];
+};
+
+struct exfat_bitmap_data {
+	uint32_t		start_cluster;
+	uint32_t		nr_clusters;
+	uint64_t		sector_start;
+	uint64_t		nr_sectors;
+};
+
+struct exfat_bitmap_head {
+	uint32_t			start_cluster;
+	uint32_t			nr_entries;
+	struct exfat_bitmap_data	entries[0];
+};
+
+struct exfat_dirent_head {
+	uint32_t offset;
+	uint32_t nr_entries;
+	uint8_t entries[0];
+};
+
+#define EXFAT_IOCGETFRAGMENTS	_IOR('X', 0x01, struct exfat_fragment_head)
+#define EXFAT_IOCGETBITMAP	_IOR('X', 0x02, struct exfat_bitmap_head)
+#define EXFAT_IOCGETDIRENTS	_IOR('X', 0x03, struct exfat_dirent_head)
+
+#endif /* !__EXFAT_USER_H */
--- /dev/null	2015-07-31 18:17:35.952031993 +0200
+++ linux-4.2-fbx/include/uapi/linux/fbxatm.h	2015-09-15 19:18:39.986467512 +0200
@@ -0,0 +1,158 @@
+/*
+ * Generic fbxatm definition, exported to userspace
+ */
+#ifndef LINUX_FBXATM_H_
+#define LINUX_FBXATM_H_
+
+#include <linux/types.h>
+#include <linux/if.h>
+
+#define FBXATM_IOCTL_MAGIC		0xd3
+
+/* allow userspace usage without up to date kernel headers */
+#ifndef PF_FBXATM
+#define PF_FBXATM			32
+#define AF_FBXATM			PF_FBXATM
+#endif
+
+struct fbxatm_vcc_id {
+	int				dev_idx;
+	__u32				vpi;
+	__u32				vci;
+};
+
+enum fbxatm_vcc_user {
+	FBXATM_VCC_USER_NONE = 0,
+	FBXATM_VCC_USER_2684,
+	FBXATM_VCC_USER_PPPOA,
+};
+
+enum fbxatm_vcc_traffic_class {
+	FBXATM_VCC_TC_UBR_NO_PCR = 0,
+	FBXATM_VCC_TC_UBR,
+};
+
+struct fbxatm_vcc_qos {
+	__u32				traffic_class;
+	__u32				max_sdu;
+	__u32				max_buffered_pkt;
+	__u32				priority;
+	__u32				rx_priority;
+};
+
+
+/*
+ * VCC related
+ */
+struct fbxatm_vcc_params {
+	/* ADD/DEL/GET */
+	struct fbxatm_vcc_id		id;
+
+	/* ADD/GET */
+	struct fbxatm_vcc_qos		qos;
+
+	/* GET */
+	enum fbxatm_vcc_user		user;
+};
+
+#define FBXATM_IOCADD		_IOW(FBXATM_IOCTL_MAGIC,	1,	\
+					struct fbxatm_vcc_params)
+
+#define FBXATM_IOCDEL		_IOR(FBXATM_IOCTL_MAGIC,	2,	\
+					struct fbxatm_vcc_params)
+
+#define FBXATM_IOCGET		_IOWR(FBXATM_IOCTL_MAGIC,	3,	\
+					struct fbxatm_vcc_params)
+
+
+struct fbxatm_vcc_drop_params {
+	struct fbxatm_vcc_id		id;
+	unsigned int			drop_count;
+};
+
+#define FBXATM_IOCDROP		_IOWR(FBXATM_IOCTL_MAGIC,	5,	\
+					struct fbxatm_vcc_drop_params)
+
+/*
+ * OAM related
+ */
+enum fbxatm_oam_ping_type {
+	FBXATM_OAM_PING_SEG_F4	= 0,
+	FBXATM_OAM_PING_SEG_F5,
+	FBXATM_OAM_PING_E2E_F4,
+	FBXATM_OAM_PING_E2E_F5,
+};
+
+struct fbxatm_oam_ping_req {
+	/* only dev_idx for F4 */
+	struct fbxatm_vcc_id		id;
+
+	__u8				llid[16];
+	enum fbxatm_oam_ping_type	type;
+};
+
+#define FBXATM_IOCOAMPING	_IOWR(FBXATM_IOCTL_MAGIC,	10,	\
+				      struct fbxatm_oam_ping_req)
+
+
+/*
+ * PPPOA related
+ */
+enum fbxatm_pppoa_encap {
+	FBXATM_EPPPOA_AUTODETECT = 0,
+	FBXATM_EPPPOA_VCMUX,
+	FBXATM_EPPPOA_LLC,
+};
+
+struct fbxatm_pppoa_vcc_params {
+	struct fbxatm_vcc_id		id;
+	__u32				encap;
+	__u32				cur_encap;
+};
+
+#define FBXATM_PPPOA_IOCADD	_IOW(FBXATM_IOCTL_MAGIC,	20,	\
+					struct fbxatm_pppoa_vcc_params)
+
+#define FBXATM_PPPOA_IOCDEL	_IOW(FBXATM_IOCTL_MAGIC,	21,	\
+					struct fbxatm_pppoa_vcc_params)
+
+#define FBXATM_PPPOA_IOCGET	_IOWR(FBXATM_IOCTL_MAGIC,	22,	\
+					struct fbxatm_pppoa_vcc_params)
+
+
+
+/*
+ * 2684 related
+ */
+enum fbxatm_2684_encap {
+	FBXATM_E2684_VCMUX = 0,
+	FBXATM_E2684_LLC,
+};
+
+enum fbxatm_2684_payload {
+	FBXATM_P2684_BRIDGE = 0,
+	FBXATM_P2684_ROUTED,
+};
+
+#define FBXATM_2684_MAX_VCC		8
+
+struct fbxatm_2684_vcc_params {
+	struct fbxatm_vcc_id		id_list[FBXATM_2684_MAX_VCC];
+	size_t				id_count;
+
+	__u32				encap;
+	__u32				payload;
+	char				dev_name[IFNAMSIZ];
+};
+
+
+#define FBXATM_2684_IOCADD	_IOW(FBXATM_IOCTL_MAGIC,	30,	\
+					struct fbxatm_2684_vcc_params)
+
+#define FBXATM_2684_IOCDEL	_IOW(FBXATM_IOCTL_MAGIC,	31,	\
+					struct fbxatm_2684_vcc_params)
+
+#define FBXATM_2684_IOCGET	_IOWR(FBXATM_IOCTL_MAGIC,	32,	\
+					struct fbxatm_2684_vcc_params)
+
+#endif /* LINUX_FBXATM_H_ */
diff -Nruw linux-4.2-fbx/include/uapi/linux/hdmi-cec./hdmi-cec.h linux-4.2-fbx/include/uapi/linux/hdmi-cec/hdmi-cec.h
--- linux-4.2-fbx/include/uapi/linux/hdmi-cec./hdmi-cec.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/include/uapi/linux/hdmi-cec/hdmi-cec.h	2013-12-04 14:33:25.335479075 +0100
@@ -0,0 +1,153 @@
+#ifndef __UAPI_HDMI_CEC_H
+#define __UAPI_HDMI_CEC_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+/* Common defines for HDMI CEC */
+#define CEC_BCAST_ADDR		(0x0f)
+#define CEC_ADDR_MAX		CEC_BCAST_ADDR
+
+#define CEC_MAX_MSG_LEN		(16)	/* 16 blocks */
+
+enum cec_rx_msg_flags {
+	/*
+	 * an ACK was received for this message
+	 */
+	CEC_RX_F_ACKED			= (1 << 0),
+
+	/*
+	 * message was fully received
+	 */
+	CEC_RX_F_COMPLETE		= (1 << 1),
+};
+
+/**
+ * struct cec_rx_msg - user-space exposed cec message cookie
+ * @data:	cec message payload
+ * @len:	cec message length
+ * @valid:	0 for invalid message
+ * @flags:	flag field (cec_rx_msg_flags)
+ */
+struct cec_rx_msg {
+	__u8	data[CEC_MAX_MSG_LEN];
+	__u8	len;
+	__u8	valid;
+	__u8	flags;
+
+} __attribute__((packed));
+
+enum cec_tx_status_flags {
+	/*
+	 * message was nacked at some point
+	 */
+	CEC_TX_F_NACK			= (1 << 0),
+
+	/*
+	 * abort sending because total time to send was elapsed
+	 */
+	CEC_TX_F_TIMEOUT		= (1 << 1),
+
+	/*
+	 * abort sending because maximum number of retry has passed
+	 */
+	CEC_TX_F_MAX_RETRIES		= (1 << 2),
+
+	/*
+	 * abort sending because of arbitration loss
+	 */
+	CEC_TX_F_ARBITRATION_LOST	= (1 << 3),
+
+	/*
+	 * message failed for other reason
+	 */
+	CEC_TX_F_UNKNOWN_ERROR		= (1 << 7),
+};
+
+/**
+ * struct cec_tx_msg - user-space exposed cec message cookie
+ * @expire_ms:	how long we try to send message (milliseconds)
+ * @data:	cec message payload
+ * @len:	cec message length
+ * @success:	0 => message was sent, else => failed to send message
+ * @flags:	flag field (cec_tx_msg_flags)
+ * @tries:	number of try done to send message
+ */
+struct cec_tx_msg {
+	__u16	expire_ms;
+	__u8	data[CEC_MAX_MSG_LEN];
+	__u8	len;
+	__u8	success;
+	__u8	flags;
+	__u8	tries;
+} __attribute__((packed));
+
+struct cec_tx_status {
+	__u8	sent;
+	__u8	success;
+	__u8	flags;
+	__u8	tries;
+} __attribute__((packed));
+
+#define DETACH_CFG_F_WAKEUP		(1 << 0)
+
+struct cec_detached_config {
+	__u8	phys_addr_valid;
+	__u8	phys_addr[2];
+	__u8	flags;
+} __attribute__((packed));
+
+/* Counters */
+
+/**
+ * struct cec_rx_counters - cec adpater RX counters
+ */
+struct cec_rx_counters {
+	__u8	pkts;
+	__u8	filtered_pkts;
+	__u8	valid_pkts;
+	__u8	rx_queue_full;
+	__u8	late_ack;
+	__u8	error;
+	__u8	rx_timeout_abort;
+	__u8	rx_throttled;
+};
+
+/**
+ * struct cec_tx_counters - cec adapter TX counters
+ */
+struct cec_tx_counters {
+	__u8	done;
+	__u8	fail;
+	__u8	timeout;
+	__u8	arb_loss;
+	__u8	bad_ack_timings;
+	__u8	tx_miss_early;
+	__u8	tx_miss_late;
+};
+
+/**
+ * struct cec_counters - tx and rx cec counters
+ * @rx:	struct cec_rx_counters
+ * @tx: struct cec_tx_counters
+ */
+struct cec_counters {
+	struct cec_rx_counters	rx;
+	struct cec_tx_counters	tx;
+};
+
+/**
+ * enum cec_rx_mode - cec adapter rx mode
+ * @CEC_RX_MODE_DISABLED:	RX path is disabled (default)
+ * @CEC_RX_MODE_DEFAULT:	accept only unicast traffic
+ * @CEC_RX_MODE_ACCEPT_ALL:	accept all incoming RX traffic (sniffing mode)
+ * @CEC_RX_MODE_MAX:		sentinel
+ */
+enum cec_rx_mode {
+	CEC_RX_MODE_DISABLED = 0,
+	CEC_RX_MODE_DEFAULT,
+	CEC_RX_MODE_ACCEPT_ALL,
+	CEC_RX_MODE_MAX
+};
+
+#endif /* __UAPI_HDMI_CEC_H */
diff -Nruw linux-4.2-fbx/include/uapi/linux/hdmi-cec./Kbuild linux-4.2-fbx/include/uapi/linux/hdmi-cec/Kbuild
--- linux-4.2-fbx/include/uapi/linux/hdmi-cec./Kbuild	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/include/uapi/linux/hdmi-cec/Kbuild	2013-12-04 14:33:25.335479075 +0100
@@ -0,0 +1 @@
+header-y	+= hdmi-cec.h dev.h
--- /dev/null	2015-07-31 18:17:35.952031993 +0200
+++ linux-4.2-fbx/include/uapi/linux/prctl-private.h	2015-09-17 19:19:40.392808329 +0200
@@ -0,0 +1,10 @@
+#ifndef _LINUX_PRCTL_PRIVATE_H
+#define _LINUX_PRCTL_PRIVATE_H
+
+/*
+ * Freebox addition: set/get exec mode.
+ */
+#define PR_SET_EXEC_MODE	54
+#define PR_GET_EXEC_MODE	55
+
+#endif /* ! _LINUX_PRCTL_PRIVATE_H */
diff -Nruw linux-4.2-fbx/include/uapi/linux/remoti./Kbuild linux-4.2-fbx/include/uapi/linux/remoti/Kbuild
--- linux-4.2-fbx/include/uapi/linux/remoti./Kbuild	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/include/uapi/linux/remoti/Kbuild	2013-12-04 14:33:25.391479076 +0100
@@ -0,0 +1 @@
+header-y	+= remoti.h
diff -Nruw linux-4.2-fbx/include/uapi/linux/remoti./remoti.h linux-4.2-fbx/include/uapi/linux/remoti/remoti.h
--- linux-4.2-fbx/include/uapi/linux/remoti./remoti.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/include/uapi/linux/remoti/remoti.h	2013-12-04 14:33:25.391479076 +0100
@@ -0,0 +1,137 @@
+#ifndef _UAPI_REMOTI_H
+#define _UAPI_REMOTI_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+/*
+ * subsystem definitions
+ */
+#define NPI_SYS_RES0		0
+#define NPI_SYS_SYS		1
+#define NPI_SYS_MAC		2
+#define NPI_SYS_NWK		3
+#define NPI_SYS_AF		4
+#define NPI_SYS_ZDO		5
+#define NPI_SYS_SAPI		6
+#define NPI_SYS_UTIL		7
+#define NPI_SYS_DBG		8
+#define NPI_SYS_APP		9
+#define NPI_SYS_RCAF		10
+#define NPI_SYS_RCN		11
+#define NPI_SYS_RCN_CLI		12
+#define NPI_SYS_BOOT		13
+#define NPI_SYS_MAX		14
+#define NPI_SYS_MASK		0x1F
+
+/*
+ * type definitions
+ */
+#define NPI_POLL		0
+#define NPI_SREQ		1
+#define NPI_AREQ		2
+#define NPI_SRSP		3
+#define NPI_TYPE_MAX		4
+#define NPI_TYPE_MASK		3
+#define NPI_TYPE_SHIFT		5
+
+
+/* common error codes (see RemoTI API) */
+#define RTI_SUCCESS		0x00
+
+/*
+ * rti user message
+ */
+#define NPI_MAX_DATA_LEN	123
+
+struct rti_msg {
+	__u8	type;
+	__u8	subsys;
+	__u8	cmd;
+
+	__u8	data_len;
+	__u8	data[NPI_MAX_DATA_LEN];
+
+	__u8	custom_reply_cmd;
+	__u8	reply_cmd;
+	__u8	reply_len;
+	__u8	reply[NPI_MAX_DATA_LEN];
+};
+
+/*
+ * socket addr family on "user" device
+ */
+#ifndef PF_REMOTI
+#define PF_REMOTI			37
+#define AF_REMOTI			PF_REMOTI
+#endif
+
+struct sockaddr_rti {
+	__u32	device_id;
+};
+
+#define SOL_REMOTI			280
+#define REMOTI_REGISTER_CB		0
+
+struct rti_callback {
+	__u8	subsys;
+	__u8	cmd;
+};
+
+/*
+ * ioctl on uart device
+ */
+enum rti_dev_state {
+	RTI_DEV_S_STOPPED = 0,
+	RTI_DEV_S_BOOTING,
+	RTI_DEV_S_BOOT_FAILED,
+	RTI_DEV_S_OPERATIONAL,
+	RTI_DEV_S_STOPPING,
+	RTI_DEV_S_DEAD,
+};
+
+struct rti_dev_status {
+	__u32	dev_state;
+	__u32	fw_version;
+};
+
+struct rti_dev_stats {
+	__u64	tx_bytes;
+	__u64	tx_packets;
+
+	__u64	tx_boot_packets;
+	__u64	tx_rcaf_packets;
+	__u64	tx_util_packets;
+	__u64	tx_other_packets;
+
+
+	__u64	rx_bytes;
+	__u64	rx_packets;
+	__u64	rx_bad_sof;
+	__u64	rx_len_errors;
+	__u64	rx_fcs_errors;
+	__u64	rx_tty_errors;
+	__u64	rx_full_errors;
+	__u64	rx_subsys_errors;
+	__u64	rx_type_errors;
+	__u64	rx_no_callback;
+
+	__u64	rx_boot_packets;
+	__u64	rx_rcaf_packets;
+	__u64	rx_util_packets;
+	__u64	rx_other_packets;
+};
+
+enum {
+	RTI_BOOT_FLAGS_FORCE_UPDATE	= (1 << 0),
+};
+
+#define RTI_IOCTL_MAGIC		0xd4
+#define RTI_ATTACH_DEVICE	_IOR(RTI_IOCTL_MAGIC, 1, __u32)
+#define RTI_GET_STATUS		_IOW(RTI_IOCTL_MAGIC, 2, struct rti_dev_status)
+#define RTI_GET_STATS		_IOW(RTI_IOCTL_MAGIC, 3, struct rti_dev_stats)
+
+#define RTI_START_DEVICE	_IOR(RTI_IOCTL_MAGIC, 8, __u32)
+#define RTI_STOP_DEVICE		_IO(RTI_IOCTL_MAGIC, 9)
+
+#endif /* _UAPI_REMOTI_H */
--- /dev/null	2015-07-31 18:17:35.952031993 +0200
+++ linux-4.2-fbx/lib/fbxserial.c	2015-09-15 19:18:40.090468161 +0200
@@ -0,0 +1,174 @@
+#include <linux/compiler.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/crc32.h>
+#include <linux/slab.h>
+
+#include <asm/io.h>
+
+#include <linux/fbxserial.h>
+
+#define PFX "builtin-fbxserial: "
+
+static void __init
+fbxserialinfo_use_default(struct fbx_serial *serial)
+{
+	printk(KERN_WARNING PFX "warning: using default serial infos\n");
+	fbxserial_set_default(serial);
+}
+
+/*
+ * add trailing 0 for bundle string here.
+ */
+static void __init
+bundle_fixup(struct fbx_serial *serial)
+{
+	struct fbx_serial_extinfo *p;
+	int i;
+
+	for (i = 0; i < be32_to_cpu(serial->extinfo_count); i++) {
+
+		if (i >= EXTINFO_MAX_COUNT)
+			break;
+
+		p = &serial->extinfos[i];
+		if (be32_to_cpu(p->type) == EXTINFO_TYPE_EXTDEV &&
+		    be32_to_cpu(p->u.extdev.type) == EXTDEV_TYPE_BUNDLE) {
+			int size;
+
+			size = sizeof (p->u.extdev.serial);
+			p->u.extdev.serial[size - 1] = 0;
+		}
+	}
+}
+
+/*
+ * called from  arch code early  in the boot sequence.   This function
+ * returns 1  in case serial infos are  invalid/unreadable and default
+ * values have been used.
+ */
+int __init
+fbxserialinfo_read(void *data, struct fbx_serial *out)
+{
+	uint32_t sum;
+
+	/*
+	 * get partial serial data from flash/whatever.
+	 */
+	memcpy(out, data, sizeof (*out));
+
+	/* check magic first */
+	if (be32_to_cpu(out->magic) != FBXSERIAL_MAGIC) {
+		printk(KERN_NOTICE PFX "invalid magic (%08x, expected %08x), "
+			"using defaults !\n", be32_to_cpu(out->magic),
+		       FBXSERIAL_MAGIC);
+		goto out_default;
+	}
+
+	/* fetch size for which we have to check CRC */
+	if (be32_to_cpu(out->len) > FBXSERIAL_MAX_SIZE) {
+		printk(KERN_NOTICE PFX "structure size too big (%d), "
+		       "using defaults !\n", be32_to_cpu(out->len));
+		goto out_default;
+	}
+
+	/* compute and check checksum */
+	sum = crc32(0, data + 4, be32_to_cpu(out->len) - 4);
+
+	if (be32_to_cpu(out->crc32) != sum) {
+		printk(KERN_NOTICE PFX "invalid checksum (%08x, "
+		       "expected %08x), using defaults !\n", sum,
+		       be32_to_cpu(out->crc32));
+		goto out_default;
+	}
+
+	printk(KERN_INFO PFX "Found valid serial infos !\n");
+	bundle_fixup(out);
+	return 0;
+
+ out_default:
+	fbxserialinfo_use_default(out);
+	bundle_fixup(out);
+	return 1;
+}
+
+void
+fbxserialinfo_get_random(unsigned char *data, unsigned int len)
+{
+	const struct fbx_serial *s;
+
+	s = arch_get_fbxserial();
+
+	if (len > sizeof (s->random_data))
+		len = sizeof (s->random_data);
+
+	memcpy(data, s->random_data, len);
+}
+EXPORT_SYMBOL(fbxserialinfo_get_random);
+
+static u8 *mac_table;
+
+static void inc_mac(u8 *mac, int count)
+{
+	int index = 5;
+	int overflow;
+
+	do {
+		unsigned int val = mac[index] + count;
+
+		overflow = val >> 8;
+		mac[index] = val;
+		count = (count + 255) >> 8;
+		--index;
+	} while (index >= 0 && overflow);
+}
+
+static int gen_mac_table(const struct fbx_serial *s)
+{
+	int i;
+
+	mac_table = kmalloc(6 * s->mac_count, GFP_KERNEL);
+	if (!mac_table)
+		return -ENOMEM;
+
+	for (i = 0; i < s->mac_count; ++i) {
+		u8 *mac = &mac_table[6 * i];
+
+		memcpy(mac, s->mac_addr_base, 6);
+		inc_mac(mac, i);
+	}
+	return 0;
+}
+
+const void *
+fbxserialinfo_get_mac_addr(unsigned int index)
+{
+	const struct fbx_serial *s;
+
+	s = arch_get_fbxserial();
+	if (!s) {
+		pr_warn(PFX "no serial available: using default.\n");
+		goto default_mac;
+	}
+
+	if (index >= s->mac_count) {
+		pr_warn(PFX "mac index %d too high: using default.\n",
+			index);
+		goto default_mac;
+	}
+
+	if (!mac_table) {
+		int error = gen_mac_table(s);
+		if (error) {
+			pr_err(PFX "gen_mac_table() failed: using default.\n");
+			goto default_mac;
+		}
+	}
+
+	return &mac_table[6 * index];
+
+default_mac:
+	 return "\x00\x07\xcb\x00\x00\xfd";
+}
+EXPORT_SYMBOL(fbxserialinfo_get_mac_addr);
diff -Nruw linux-4.2-fbx/net/fbxatm./Kconfig linux-4.2-fbx/net/fbxatm/Kconfig
--- linux-4.2-fbx/net/fbxatm./Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/net/fbxatm/Kconfig	2010-03-30 17:09:16.308147997 +0200
@@ -0,0 +1,28 @@
+menuconfig FBXATM
+	tristate "Freebox Asynchronous Transfer Mode (ATM)"
+
+if FBXATM
+
+config FBXATM_REMOTE
+	bool
+
+choice
+	prompt "mode"
+	default FBXATM_STACK
+
+config FBXATM_STACK
+	bool "standard"
+
+config FBXATM_REMOTE_STUB
+	bool "remote stub"
+	select FBXATM_REMOTE
+
+endchoice
+
+config FBXATM_REMOTE_DRIVER
+	tristate "remote fbxatm driver"
+	depends on FBXATM_STACK
+	select FBXATM_REMOTE
+	default n
+
+endif
diff -Nruw linux-4.2-fbx/net/fbxbridge./Kconfig linux-4.2-fbx/net/fbxbridge/Kconfig
--- linux-4.2-fbx/net/fbxbridge./Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-4.2-fbx/net/fbxbridge/Kconfig	2013-12-04 14:33:29.627479143 +0100
@@ -0,0 +1,6 @@
+
+#
+# Freebox bridge
+#
+config FBXBRIDGE
+	bool "Freebox Bridge"
